From 2a0b7b6b40dbee9f15ac28671446d1a61e6c7f7d Mon Sep 17 00:00:00 2001 From: Leonard Lyubich Date: Mon, 28 Feb 2022 13:56:46 +0300 Subject: [PATCH] [#140] client: Specify status errors of `Client` methods Extend docs with supported status returns. Add several helper functions which allow to check the particular status. Signed-off-by: Leonard Lyubich --- client/client.go | 3 ++- client/container.go | 6 ++++-- client/errors.go | 42 +++++++++++++++++++++++++++++++++++++++++ client/object_delete.go | 6 +++++- client/object_get.go | 21 ++++++++++++++++++--- client/object_hash.go | 6 +++++- client/object_put.go | 8 +++++++- client/object_search.go | 5 ++++- 8 files changed, 87 insertions(+), 10 deletions(-) create mode 100644 client/errors.go diff --git a/client/client.go b/client/client.go index 7ac0149..d4320d3 100644 --- a/client/client.go +++ b/client/client.go @@ -19,7 +19,8 @@ import ( // Status responses are returned in the result structure, and can be cast // to built-in error instance (or in the returned error if the client is // configured accordingly). Certain statuses can be checked using `apistatus` -// and standard `errors` packages. +// and standard `errors` packages. Note that package provides some helper +// functions to work with status returns (e.g. IsErrContainerNotFound). // All possible responses are documented in methods, however, some may be // returned from all of them (pay attention to the presence of the pointer sign): // - *apistatus.ServerInternal on internal server error; diff --git a/client/container.go b/client/container.go index 6d0dfe8..45f1e5c 100644 --- a/client/container.go +++ b/client/container.go @@ -172,7 +172,8 @@ func (x *ResContainerGet) setContainer(cnr *container.Container) { // Context is required and must not be nil. It is used for network communication. // // Return statuses: -// - global (see Client docs). +// - global (see Client docs); +// - *apistatus.ContainerNotFound. func (c *Client) ContainerGet(ctx context.Context, prm PrmContainerGet) (*ResContainerGet, error) { switch { case ctx == nil: @@ -479,7 +480,8 @@ func (x *ResContainerEACL) setTable(table *eacl.Table) { // Context is required and must not be nil. It is used for network communication. // // Return statuses: -// - global (see Client docs). +// - global (see Client docs); +// - *apistatus.ContainerNotFound. func (c *Client) ContainerEACL(ctx context.Context, prm PrmContainerEACL) (*ResContainerEACL, error) { // check parameters switch { diff --git a/client/errors.go b/client/errors.go new file mode 100644 index 0000000..7e5a69d --- /dev/null +++ b/client/errors.go @@ -0,0 +1,42 @@ +package client + +import apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" + +// IsErrContainerNotFound checks if err corresponds to NeoFS status +// return corresponding to missing container. +func IsErrContainerNotFound(err error) bool { + switch err.(type) { + default: + return false + case + apistatus.ContainerNotFound, + *apistatus.ContainerNotFound: + return true + } +} + +// IsErrObjectNotFound checks if err corresponds to NeoFS status +// return corresponding to missing object. +func IsErrObjectNotFound(err error) bool { + switch err.(type) { + default: + return false + case + apistatus.ObjectNotFound, + *apistatus.ObjectNotFound: + return true + } +} + +// IsErrObjectAlreadyRemoved checks if err corresponds to NeoFS status +// return corresponding to already removed object. +func IsErrObjectAlreadyRemoved(err error) bool { + switch err.(type) { + default: + return false + case + apistatus.ObjectAlreadyRemoved, + *apistatus.ObjectAlreadyRemoved: + return true + } +} diff --git a/client/object_delete.go b/client/object_delete.go index d3e13b5..407822b 100644 --- a/client/object_delete.go +++ b/client/object_delete.go @@ -101,7 +101,11 @@ func (x ResObjectDelete) ReadTombstoneID(dst *oid.ID) bool { // Context is required and must not be nil. It is used for network communication. // // Return statuses: -// - global (see Client docs). +// - global (see Client docs) +// - *apistatus.ContainerNotFound; +// - *apistatus.ObjectAccessDenied; +// - *apistatus.ObjectLocked; +// - *apistatus.SessionTokenExpired. func (c *Client) ObjectDelete(ctx context.Context, prm PrmObjectDelete) (*ResObjectDelete, error) { switch { case ctx == nil: diff --git a/client/object_get.go b/client/object_get.go index ac43c86..3628b94 100644 --- a/client/object_get.go +++ b/client/object_get.go @@ -247,7 +247,12 @@ func (x *ObjectReader) close(ignoreEOF bool) (*ResObjectGet, error) { // *object.SplitInfoError (returned on virtual objects with PrmObjectGet.MakeRaw). // // Return statuses: -// global (see Client docs). +// - global (see Client docs); +// - *apistatus.ContainerNotFound; +// - *apistatus.ObjectNotFound; +// - *apistatus.ObjectAccessDenied; +// - *apistatus.ObjectAlreadyRemoved; +// - *apistatus.SessionTokenExpired. func (x *ObjectReader) Close() (*ResObjectGet, error) { return x.close(true) } @@ -455,7 +460,12 @@ func (x *ResObjectHead) ReadHeader(dst *object.Object) bool { // *object.SplitInfoError (returned on virtual objects with PrmObjectHead.MakeRaw). // // Return statuses: -// - global (see Client docs). +// - global (see Client docs); +// - *apistatus.ContainerNotFound; +// - *apistatus.ObjectNotFound; +// - *apistatus.ObjectAccessDenied; +// - *apistatus.ObjectAlreadyRemoved; +// - *apistatus.SessionTokenExpired. func (c *Client) ObjectHead(ctx context.Context, prm PrmObjectHead) (*ResObjectHead, error) { switch { case ctx == nil: @@ -689,7 +699,12 @@ func (x *ObjectRangeReader) close(ignoreEOF bool) (*ResObjectRange, error) { // *object.SplitInfoError (returned on virtual objects with PrmObjectRange.MakeRaw). // // Return statuses: -// global (see Client docs). +// - global (see Client docs); +// - *apistatus.ContainerNotFound; +// - *apistatus.ObjectNotFound; +// - *apistatus.ObjectAccessDenied; +// - *apistatus.ObjectAlreadyRemoved; +// - *apistatus.SessionTokenExpired. func (x *ObjectRangeReader) Close() (*ResObjectRange, error) { return x.close(true) } diff --git a/client/object_hash.go b/client/object_hash.go index ea8e311..12b8d0f 100644 --- a/client/object_hash.go +++ b/client/object_hash.go @@ -125,7 +125,11 @@ func (x ResObjectHash) Checksums() [][]byte { // Context is required and must not be nil. It is used for network communication. // // Return statuses: -// - global (see Client docs). +// - global (see Client docs); +// - *apistatus.ContainerNotFound; +// - *apistatus.ObjectNotFound; +// - *apistatus.ObjectAccessDenied; +// - *apistatus.SessionTokenExpired. func (c *Client) ObjectHash(ctx context.Context, prm PrmObjectHash) (*ResObjectHash, error) { switch { case ctx == nil: diff --git a/client/object_put.go b/client/object_put.go index 3d0adb8..09d892f 100644 --- a/client/object_put.go +++ b/client/object_put.go @@ -146,7 +146,13 @@ func (x *ObjectWriter) WritePayloadChunk(chunk []byte) bool { // codes are returned as error. // // Return statuses: -// global (see Client docs). +// - global (see Client docs); +// - *apistatus.ContainerNotFound; +// - *apistatus.ObjectAccessDenied; +// - *apistatus.ObjectLocked; +// - *apistatus.LockNonRegularObject; +// - *apistatus.SessionTokenNotFound; +// - *apistatus.SessionTokenExpired. func (x *ObjectWriter) Close() (*ResObjectPut, error) { defer x.cancelCtxStream() diff --git a/client/object_search.go b/client/object_search.go index c0750b1..a67976b 100644 --- a/client/object_search.go +++ b/client/object_search.go @@ -209,7 +209,10 @@ func (x *ObjectListReader) Iterate(f func(oid.ID) bool) error { // codes are returned as error. // // Return statuses: -// global (see Client docs). +// - global (see Client docs); +// - *apistatus.ContainerNotFound; +// - *apistatus.ObjectAccessDenied; +// - *apistatus.SessionTokenExpired. func (x *ObjectListReader) Close() (*ResObjectSearch, error) { defer x.cancelCtxStream()