client: Replace panics with errors

Signed-off-by: Evgenii Baidakov <evgenii@nspcc.io>
This commit is contained in:
Evgenii Baidakov 2023-05-17 13:07:01 +04:00
parent 8094342b1c
commit f9d740487a
No known key found for this signature in database
GPG key ID: 8733EE3D72CDB4DE
12 changed files with 98 additions and 53 deletions

View file

@ -41,12 +41,14 @@ func (x ResBalanceGet) Amount() accounting.Decimal {
// Any errors (local or remote, including returned status codes) are returned as Go errors,
// see [apistatus] package for NeoFS-specific error types.
//
// Immediately panics if parameters are set incorrectly (see PrmBalanceGet docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return errors:
// - [ErrMissingAccount]
func (c *Client) BalanceGet(ctx context.Context, prm PrmBalanceGet) (*ResBalanceGet, error) {
switch {
case !prm.accountSet:
panic("account not set")
return nil, ErrMissingAccount
}
// form request body

View file

@ -47,13 +47,6 @@ func writeXHeadersToMeta(xHeaders []string, h *v2session.RequestMetaHeader) {
h.SetXHeaders(hs)
}
// panic messages.
const (
panicMsgMissingContainer = "missing container"
panicMsgMissingObject = "missing object"
panicMsgOwnerExtract = "extract owner failed"
)
// groups all the details required to send a single request and process a response to it.
type contextCall struct {
// ==================================================

View file

@ -84,13 +84,15 @@ func (c *Client) defaultSigner() neofscrypto.Signer {
//
// Success can be verified by reading by identifier (see ResContainerPut.ID).
//
// Immediately panics if parameters are set incorrectly (see PrmContainerPut docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return errors:
// - [ErrMissingContainer]
func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResContainerPut, error) {
// check parameters
switch {
case !prm.cnrSet:
panic(panicMsgMissingContainer)
return nil, ErrMissingContainer
}
// TODO: check private signer is set before forming the request
@ -204,12 +206,14 @@ func (x ResContainerGet) Container() container.Container {
// Any errors (local or remote, including returned status codes) are returned as Go errors,
// see [apistatus] package for NeoFS-specific error types.
//
// Immediately panics if parameters are set incorrectly (see PrmContainerGet docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return errors:
// - [ErrMissingContainer]
func (c *Client) ContainerGet(ctx context.Context, prm PrmContainerGet) (*ResContainerGet, error) {
switch {
case !prm.idSet:
panic(panicMsgMissingContainer)
return nil, ErrMissingContainer
}
var cidV2 refs.ContainerID
@ -292,13 +296,15 @@ func (x ResContainerList) Containers() []cid.ID {
// Any errors (local or remote, including returned status codes) are returned as Go errors,
// see [apistatus] package for NeoFS-specific error types.
//
// Immediately panics if parameters are set incorrectly (see PrmContainerList docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return errors:
// - [ErrMissingAccount]
func (c *Client) ContainerList(ctx context.Context, prm PrmContainerList) (*ResContainerList, error) {
// check parameters
switch {
case !prm.ownerSet:
panic("account not set")
return nil, ErrMissingAccount
}
// form request body
@ -396,15 +402,17 @@ func (x *PrmContainerDelete) WithinSession(tok session.Container) {
//
// Success can be verified by reading by identifier (see GetContainer).
//
// Immediately panics if parameters are set incorrectly (see PrmContainerDelete docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return errors:
// - [ErrMissingContainer]
//
// Reflects all internal errors in second return value (transport problems, response processing, etc.).
func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) error {
// check parameters
switch {
case !prm.idSet:
panic(panicMsgMissingContainer)
return ErrMissingContainer
}
// sign container ID
@ -502,13 +510,15 @@ func (x ResContainerEACL) Table() eacl.Table {
// Any errors (local or remote, including returned status codes) are returned as Go errors,
// see [apistatus] package for NeoFS-specific error types.
//
// Immediately panics if parameters are set incorrectly (see PrmContainerEACL docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return errors:
// - [ErrMissingContainer]
func (c *Client) ContainerEACL(ctx context.Context, prm PrmContainerEACL) (*ResContainerEACL, error) {
// check parameters
switch {
case !prm.idSet:
panic(panicMsgMissingContainer)
return nil, ErrMissingContainer
}
var cidV2 refs.ContainerID
@ -609,18 +619,21 @@ func (x *PrmContainerSetEACL) WithinSession(s session.Container) {
//
// Success can be verified by reading by identifier (see EACL).
//
// Immediately panics if parameters are set incorrectly (see PrmContainerSetEACL docs).
// Return errors:
// - [ErrMissingEACL]
// - [ErrMissingEACLContainer]
//
// Context is required and must not be nil. It is used for network communication.
func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL) error {
// check parameters
switch {
case !prm.tableSet:
panic("eACL table not set")
return ErrMissingEACL
}
_, isCIDSet := prm.table.CID()
if !isCIDSet {
panic("missing container in eACL table")
return ErrMissingEACLContainer
}
// sign the eACL table
@ -708,13 +721,15 @@ func (x *PrmAnnounceSpace) SetValues(vs []container.SizeEstimation) {
//
// At this moment success can not be checked.
//
// Immediately panics if parameters are set incorrectly (see PrmAnnounceSpace docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return errors:
// - [ErrMissingAnnouncements]
func (c *Client) ContainerAnnounceUsedSpace(ctx context.Context, prm PrmAnnounceSpace) error {
// check parameters
switch {
case len(prm.announcements) == 0:
panic("missing announcements")
return ErrMissingAnnouncements
}
// convert list of SDK announcement structures into NeoFS-API v2 list

View file

@ -1,10 +1,25 @@
package client
import (
"errors"
"fmt"
)
var (
ErrMissingContainer = errors.New("missing container")
ErrMissingObject = errors.New("missing object")
ErrMissingAccount = errors.New("missing account")
ErrMissingEACL = errors.New("missing eACL table")
ErrMissingEACLContainer = errors.New("missing container in eACL table")
ErrMissingAnnouncements = errors.New("missing announcements")
ErrZeroRangeLength = errors.New("zero range length")
ErrMissingRanges = errors.New("missing ranges")
ErrZeroEpoch = errors.New("zero epoch")
ErrMissingTrusts = errors.New("missing trusts")
ErrMissingTrust = errors.New("missing trust")
ErrUnexpectedReadCall = errors.New("unexpected call to `Read`")
errMissingResponseField missingResponseFieldErr
)

View file

@ -114,11 +114,12 @@ func (x ResObjectDelete) Tombstone() oid.ID {
// Any client's internal or transport errors are returned as `error`,
// see [apistatus] package for NeoFS-specific error types.
//
// Immediately panics if parameters are set incorrectly (see PrmObjectDelete docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return errors:
// - global (see Client docs)
// - [ErrMissingContainer];
// - [ErrMissingObject];
// - [apistatus.ErrContainerNotFound];
// - [apistatus.ErrObjectAccessDenied];
// - [apistatus.ErrObjectLocked];
@ -126,9 +127,9 @@ func (x ResObjectDelete) Tombstone() oid.ID {
func (c *Client) ObjectDelete(ctx context.Context, prm PrmObjectDelete) (*ResObjectDelete, error) {
switch {
case prm.addr.GetContainerID() == nil:
panic(panicMsgMissingContainer)
return nil, ErrMissingContainer
case prm.addr.GetObjectID() == nil:
panic(panicMsgMissingObject)
return nil, ErrMissingObject
}
// form request body

View file

@ -289,15 +289,18 @@ func (x *ObjectReader) Read(p []byte) (int, error) {
// The call only opens the transmission channel, explicit fetching is done using the ObjectReader.
// Exactly one return value is non-nil. Resulting reader must be finally closed.
//
// Immediately panics if parameters are set incorrectly (see PrmObjectGet docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return errors:
// - [ErrMissingContainer]
// - [ErrMissingObject]
func (c *Client) ObjectGetInit(ctx context.Context, prm PrmObjectGet) (*ObjectReader, error) {
// check parameters
switch {
case prm.addr.GetContainerID() == nil:
panic(panicMsgMissingContainer)
return nil, ErrMissingContainer
case prm.addr.GetObjectID() == nil:
panic(panicMsgMissingObject)
return nil, ErrMissingObject
}
// form request body
@ -385,11 +388,12 @@ func (x *ResObjectHead) ReadHeader(dst *object.Object) bool {
// Any client's internal or transport errors are returned as `error`,
// see [apistatus] package for NeoFS-specific error types.
//
// Immediately panics if parameters are set incorrectly (see PrmObjectHead docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return errors:
// - global (see Client docs);
// - [ErrMissingContainer];
// - [ErrMissingObject];
// - *[object.SplitInfoError] (returned on virtual objects with PrmObjectHead.MakeRaw).
// - [apistatus.ErrContainerNotFound];
// - [apistatus.ErrObjectNotFound];
@ -399,9 +403,9 @@ func (x *ResObjectHead) ReadHeader(dst *object.Object) bool {
func (c *Client) ObjectHead(ctx context.Context, prm PrmObjectHead) (*ResObjectHead, error) {
switch {
case prm.addr.GetContainerID() == nil:
panic(panicMsgMissingContainer)
return nil, ErrMissingContainer
case prm.addr.GetObjectID() == nil:
panic(panicMsgMissingObject)
return nil, ErrMissingObject
}
var body v2object.HeadRequestBody
@ -635,17 +639,21 @@ func (x *ObjectRangeReader) Read(p []byte) (int, error) {
// The call only opens the transmission channel, explicit fetching is done using the ObjectRangeReader.
// Exactly one return value is non-nil. Resulting reader must be finally closed.
//
// Immediately panics if parameters are set incorrectly (see PrmObjectRange docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return errors:
// - [ErrMissingContainer]
// - [ErrMissingObject]
// - [ErrZeroRangeLength]
func (c *Client) ObjectRangeInit(ctx context.Context, prm PrmObjectRange) (*ObjectRangeReader, error) {
// check parameters
switch {
case prm.addr.GetContainerID() == nil:
panic(panicMsgMissingContainer)
return nil, ErrMissingContainer
case prm.addr.GetObjectID() == nil:
panic(panicMsgMissingObject)
return nil, ErrMissingObject
case prm.rng.GetLength() == 0:
panic("zero range length")
return nil, ErrZeroRangeLength
}
// form request body

View file

@ -152,16 +152,19 @@ func (x ResObjectHash) Checksums() [][]byte {
// Any client's internal or transport errors are returned as `error`,
// see [apistatus] package for NeoFS-specific error types.
//
// Immediately panics if parameters are set incorrectly (see PrmObjectHash docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return errors:
// - [ErrMissingContainer]
// - [ErrMissingObject]
func (c *Client) ObjectHash(ctx context.Context, prm PrmObjectHash) (*ResObjectHash, error) {
switch {
case prm.addr.GetContainerID() == nil:
panic(panicMsgMissingContainer)
return nil, ErrMissingContainer
case prm.addr.GetObjectID() == nil:
panic(panicMsgMissingObject)
return nil, ErrMissingObject
case len(prm.body.GetRanges()) == 0:
panic("missing ranges")
return nil, ErrMissingRanges
}
prm.body.SetAddress(&prm.addr)

View file

@ -205,13 +205,15 @@ func (x *ObjectListReader) Close() error {
// is done using the ObjectListReader. Exactly one return value is non-nil.
// Resulting reader must be finally closed.
//
// Immediately panics if parameters are set incorrectly (see PrmObjectSearch docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return errors:
// - [ErrMissingContainer]
func (c *Client) ObjectSearchInit(ctx context.Context, prm PrmObjectSearch) (*ObjectListReader, error) {
// check parameters
switch {
case !prm.cnrSet:
panic(panicMsgMissingContainer)
return nil, ErrMissingContainer
}
var cidV2 v2refs.ContainerID

View file

@ -136,7 +136,7 @@ func (s *singleStreamResponder) Read(resp *v2object.SearchResponse) error {
if s.endError != nil {
return s.endError
}
panic("unexpected call to `Read`")
return ErrUnexpectedReadCall
}
var body v2object.SearchResponseBody

View file

@ -37,15 +37,18 @@ func (x *PrmAnnounceLocalTrust) SetValues(trusts []reputation.Trust) {
// Any errors (local or remote, including returned status codes) are returned as Go errors,
// see [apistatus] package for NeoFS-specific error types.
//
// Immediately panics if parameters are set incorrectly (see PrmAnnounceLocalTrust docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return errors:
// - [ErrZeroEpoch]
// - [ErrMissingTrusts]
func (c *Client) AnnounceLocalTrust(ctx context.Context, prm PrmAnnounceLocalTrust) error {
// check parameters
switch {
case prm.epoch == 0:
panic("zero epoch")
return ErrZeroEpoch
case len(prm.trusts) == 0:
panic("missing trusts")
return ErrMissingTrusts
}
// form request body
@ -123,15 +126,18 @@ func (x *PrmAnnounceIntermediateTrust) SetCurrentValue(trust reputation.PeerToPe
// Any errors (local or remote, including returned status codes) are returned as Go errors,
// see [apistatus] package for NeoFS-specific error types.
//
// Immediately panics if parameters are set incorrectly (see PrmAnnounceIntermediateTrust docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return errors:
// - [ErrZeroEpoch]
// - [ErrMissingTrust]
func (c *Client) AnnounceIntermediateTrust(ctx context.Context, prm PrmAnnounceIntermediateTrust) error {
// check parameters
switch {
case prm.epoch == 0:
panic("zero epoch")
return ErrZeroEpoch
case !prm.trustSet:
panic("current trust value not set")
return ErrMissingTrust
}
var trust v2reputation.PeerToPeerTrust

View file

@ -2,6 +2,7 @@ package client
import (
"context"
"fmt"
"github.com/nspcc-dev/neofs-api-go/v2/refs"
"github.com/nspcc-dev/neofs-api-go/v2/rpc/client"
@ -64,12 +65,11 @@ func (x ResSessionCreate) PublicKey() []byte {
// Any errors (local or remote, including returned status codes) are returned as Go errors,
// see [apistatus] package for NeoFS-specific error types.
//
// Immediately panics if parameters are set incorrectly (see PrmSessionCreate docs).
// Context is required and must not be nil. It is used for network communication.
func (c *Client) SessionCreate(ctx context.Context, prm PrmSessionCreate) (*ResSessionCreate, error) {
var ownerID user.ID
if err := user.IDFromSigner(&ownerID, prm.signer); err != nil {
panic(panicMsgOwnerExtract)
return nil, fmt.Errorf("IDFromSigner: %w", err)
}
var ownerIDV2 refs.OwnerID

View file

@ -155,7 +155,7 @@ func (x commonData) signedData(w contextWriter) []byte {
func (x *commonData) sign(signer neofscrypto.Signer, w contextWriter) error {
if err := user.IDFromSigner(&x.issuer, signer); err != nil {
return err
return fmt.Errorf("IDFromSigner: %w", err)
}
x.issuerSet = true