[#2] Remove panic from RPCs

Signed-off-by: Anton Nikiforov <an.nikiforov@yadro.com>
This commit is contained in:
Anton Nikiforov 2023-02-27 10:53:27 +03:00 committed by Anton Nikiforov
parent d4f5bba459
commit 5e759bf089
13 changed files with 90 additions and 78 deletions

View file

@ -46,7 +46,7 @@ func (x ResBalanceGet) Amount() accounting.Decimal {
// FrostFS status codes are returned as `error`, otherwise, are included
// in the returned result structure.
//
// Immediately panics if parameters are set incorrectly (see PrmBalanceGet docs).
// Returns an error if parameters are set incorrectly (see PrmBalanceGet docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return statuses:
@ -54,9 +54,9 @@ func (x ResBalanceGet) Amount() accounting.Decimal {
func (c *Client) BalanceGet(ctx context.Context, prm PrmBalanceGet) (*ResBalanceGet, error) {
switch {
case ctx == nil:
panic(panicMsgMissingContext)
return nil, errorMissingContext
case !prm.accountSet:
panic("account not set")
return nil, errorAccountNotSet
}
// form request body

View file

@ -69,7 +69,7 @@ func (c *Client) Init(prm PrmInit) {
// argument, otherwise context.Background() is used. Dial returns context
// errors, see context package docs for details.
//
// Panics if required parameters are set incorrectly, look carefully
// Returns an error if required parameters are set incorrectly, look carefully
// at the method documentation.
//
// One-time method call during application start-up stage (after Init ) is expected.
@ -78,12 +78,12 @@ func (c *Client) Init(prm PrmInit) {
// See also Init / Close.
func (c *Client) Dial(prm PrmDial) error {
if prm.endpoint == "" {
panic("server address is unset or empty")
return errorServerAddrUnset
}
if prm.timeoutDialSet {
if prm.timeoutDial <= 0 {
panic("non-positive timeout")
return errorNonPositiveTimeout
}
} else {
prm.timeoutDial = 5 * time.Second
@ -91,7 +91,7 @@ func (c *Client) Dial(prm PrmDial) error {
if prm.streamTimeoutSet {
if prm.streamTimeout <= 0 {
panic("non-positive timeout")
return errorNonPositiveTimeout
}
} else {
prm.streamTimeout = 10 * time.Second

View file

@ -2,6 +2,7 @@ package client
import (
"crypto/ecdsa"
"errors"
"fmt"
"github.com/TrueCloudLab/frostfs-api-go/v2/refs"
@ -70,11 +71,21 @@ func writeXHeadersToMeta(xHeaders []string, h *v2session.RequestMetaHeader) {
h.SetXHeaders(hs)
}
// panic messages.
const (
panicMsgMissingContext = "missing context"
panicMsgMissingContainer = "missing container"
panicMsgMissingObject = "missing object"
// error messages.
var (
errorMissingContext = errors.New("missing context")
errorMissingContainer = errors.New("missing container")
errorMissingObject = errors.New("missing object")
errorAccountNotSet = errors.New("account not set")
errorServerAddrUnset = errors.New("server address is unset or empty")
errorNonPositiveTimeout = errors.New("non-positive timeout")
errorEACLTableNotSet = errors.New("eACL table not set")
errorMissingAnnouncements = errors.New("missing announcements")
errorZeroRangeLength = errors.New("zero range length")
errorMissingRanges = errors.New("missing ranges")
errorZeroEpoch = errors.New("zero epoch")
errorMissingTrusts = errors.New("missing trusts")
errorTrustNotSet = errors.New("current trust value not set")
)
// groups all the details required to send a single request and process a response to it.

View file

@ -77,7 +77,7 @@ func (x ResContainerPut) ID() cid.ID {
//
// Success can be verified by reading by identifier (see ResContainerPut.ID).
//
// Immediately panics if parameters are set incorrectly (see PrmContainerPut docs).
// Returns an error if parameters are set incorrectly (see PrmContainerPut docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return statuses:
@ -86,9 +86,9 @@ func (c *Client) ContainerPut(ctx context.Context, prm PrmContainerPut) (*ResCon
// check parameters
switch {
case ctx == nil:
panic(panicMsgMissingContext)
return nil, errorMissingContext
case !prm.cnrSet:
panic(panicMsgMissingContainer)
return nil, errorMissingContainer
}
// TODO: check private key is set before forming the request
@ -204,7 +204,7 @@ func (x ResContainerGet) Container() container.Container {
// FrostFS status codes are returned as `error`, otherwise, are included
// in the returned result structure.
//
// Immediately panics if parameters are set incorrectly (see PrmContainerGet docs).
// Returns an error if parameters are set incorrectly (see PrmContainerGet docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return statuses:
@ -213,9 +213,9 @@ func (x ResContainerGet) Container() container.Container {
func (c *Client) ContainerGet(ctx context.Context, prm PrmContainerGet) (*ResContainerGet, error) {
switch {
case ctx == nil:
panic(panicMsgMissingContext)
return nil, errorMissingContext
case !prm.idSet:
panic(panicMsgMissingContainer)
return nil, errorMissingContainer
}
var cidV2 refs.ContainerID
@ -304,7 +304,7 @@ func (x ResContainerList) Containers() []cid.ID {
// FrostFS status codes are returned as `error`, otherwise, are included
// in the returned result structure.
//
// Immediately panics if parameters are set incorrectly (see PrmContainerList docs).
// Returns an error if parameters are set incorrectly (see PrmContainerList docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return statuses:
@ -313,9 +313,9 @@ func (c *Client) ContainerList(ctx context.Context, prm PrmContainerList) (*ResC
// check parameters
switch {
case ctx == nil:
panic(panicMsgMissingContext)
return nil, errorMissingContext
case !prm.ownerSet:
panic("account not set")
return nil, errorAccountNotSet
}
// form request body
@ -413,7 +413,7 @@ type ResContainerDelete struct {
//
// Success can be verified by reading by identifier (see GetContainer).
//
// Immediately panics if parameters are set incorrectly (see PrmContainerDelete docs).
// Returns an error if parameters are set incorrectly (see PrmContainerDelete docs).
// Context is required and must not be nil. It is used for network communication.
//
// Exactly one return value is non-nil. Server status return is returned in ResContainerDelete.
@ -425,9 +425,9 @@ func (c *Client) ContainerDelete(ctx context.Context, prm PrmContainerDelete) (*
// check parameters
switch {
case ctx == nil:
panic(panicMsgMissingContext)
return nil, errorMissingContext
case !prm.idSet:
panic(panicMsgMissingContainer)
return nil, errorMissingContainer
}
// sign container ID
@ -528,7 +528,7 @@ func (x ResContainerEACL) Table() eacl.Table {
// FrostFS status codes are returned as `error`, otherwise, are included
// in the returned result structure.
//
// Immediately panics if parameters are set incorrectly (see PrmContainerEACL docs).
// Returns an error if parameters are set incorrectly (see PrmContainerEACL docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return statuses:
@ -539,9 +539,9 @@ func (c *Client) ContainerEACL(ctx context.Context, prm PrmContainerEACL) (*ResC
// check parameters
switch {
case ctx == nil:
panic(panicMsgMissingContext)
return nil, errorMissingContext
case !prm.idSet:
panic(panicMsgMissingContainer)
return nil, errorMissingContainer
}
var cidV2 refs.ContainerID
@ -642,7 +642,7 @@ type ResContainerSetEACL struct {
//
// Success can be verified by reading by identifier (see EACL).
//
// Immediately panics if parameters are set incorrectly (see PrmContainerSetEACL docs).
// Returns an error if parameters are set incorrectly (see PrmContainerSetEACL docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return statuses:
@ -651,9 +651,9 @@ func (c *Client) ContainerSetEACL(ctx context.Context, prm PrmContainerSetEACL)
// check parameters
switch {
case ctx == nil:
panic(panicMsgMissingContext)
return nil, errorMissingContext
case !prm.tableSet:
panic("eACL table not set")
return nil, errorEACLTableNotSet
}
// sign the eACL table
@ -747,7 +747,7 @@ type ResAnnounceSpace struct {
//
// At this moment success can not be checked.
//
// Immediately panics if parameters are set incorrectly (see PrmAnnounceSpace docs).
// Returns an error if parameters are set incorrectly (see PrmAnnounceSpace docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return statuses:
@ -756,9 +756,9 @@ func (c *Client) ContainerAnnounceUsedSpace(ctx context.Context, prm PrmAnnounce
// check parameters
switch {
case ctx == nil:
panic(panicMsgMissingContext)
return nil, errorMissingContext
case len(prm.announcements) == 0:
panic("missing announcements")
return nil, errorMissingAnnouncements
}
// convert list of SDK announcement structures into FrostFS-API v2 list

View file

@ -47,7 +47,7 @@ func (x ResEndpointInfo) NodeInfo() netmap.NodeInfo {
// FrostFS status codes are returned as `error`, otherwise, are included
// in the returned result structure.
//
// Immediately panics if parameters are set incorrectly (see PrmEndpointInfo docs).
// Returns an error if parameters are set incorrectly (see PrmEndpointInfo docs).
// Context is required and must not be nil. It is used for network communication.
//
// Exactly one return value is non-nil. Server status return is returned in ResEndpointInfo.
@ -58,7 +58,7 @@ func (x ResEndpointInfo) NodeInfo() netmap.NodeInfo {
func (c *Client) EndpointInfo(ctx context.Context, prm PrmEndpointInfo) (*ResEndpointInfo, error) {
// check context
if ctx == nil {
panic(panicMsgMissingContext)
return nil, errorMissingContext
}
// form request
@ -144,7 +144,7 @@ func (x ResNetworkInfo) Info() netmap.NetworkInfo {
// FrostFS status codes are returned as `error`, otherwise, are included
// in the returned result structure.
//
// Immediately panics if parameters are set incorrectly (see PrmNetworkInfo docs).
// Returns an error if parameters are set incorrectly (see PrmNetworkInfo docs).
// Context is required and must not be nil. It is used for network communication.
//
// Exactly one return value is non-nil. Server status return is returned in ResNetworkInfo.
@ -155,7 +155,7 @@ func (x ResNetworkInfo) Info() netmap.NetworkInfo {
func (c *Client) NetworkInfo(ctx context.Context, prm PrmNetworkInfo) (*ResNetworkInfo, error) {
// check context
if ctx == nil {
panic(panicMsgMissingContext)
return nil, errorMissingContext
}
// form request
@ -224,6 +224,7 @@ func (x ResNetMapSnapshot) NetMap() netmap.NetMap {
// FrostFS status codes are returned as `error`, otherwise, are included
// in the returned result structure.
//
// Returns an error if parameters are set incorrectly.
// Context is required and MUST NOT be nil. It is used for network communication.
//
// Exactly one return value is non-nil. Server status return is returned in ResNetMapSnapshot.
@ -234,7 +235,7 @@ func (x ResNetMapSnapshot) NetMap() netmap.NetMap {
func (c *Client) NetMapSnapshot(ctx context.Context, _ PrmNetMapSnapshot) (*ResNetMapSnapshot, error) {
// check context
if ctx == nil {
panic(panicMsgMissingContext)
return nil, errorMissingContext
}
// form request body

View file

@ -70,10 +70,9 @@ func TestClient_NetMapSnapshot(t *testing.T) {
ctx := context.Background()
// missing context
require.PanicsWithValue(t, panicMsgMissingContext, func() {
//nolint:staticcheck
_, _ = c.NetMapSnapshot(nil, prm)
})
//nolint:staticcheck
_, err = c.NetMapSnapshot(nil, prm)
require.ErrorIs(t, err, errorMissingContext, "")
// request signature
srv.errTransport = errors.New("any error")

View file

@ -114,7 +114,7 @@ func (x ResObjectDelete) Tombstone() oid.ID {
// FrostFS status codes are returned as `error`, otherwise, are included
// in the returned result structure.
//
// Immediately panics if parameters are set incorrectly (see PrmObjectDelete docs).
// Returns an error if parameters are set incorrectly (see PrmObjectDelete docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return statuses:
@ -126,11 +126,11 @@ func (x ResObjectDelete) Tombstone() oid.ID {
func (c *Client) ObjectDelete(ctx context.Context, prm PrmObjectDelete) (*ResObjectDelete, error) {
switch {
case ctx == nil:
panic(panicMsgMissingContext)
return nil, errorMissingContext
case prm.addr.GetContainerID() == nil:
panic(panicMsgMissingContainer)
return nil, errorMissingContainer
case prm.addr.GetObjectID() == nil:
panic(panicMsgMissingObject)
return nil, errorMissingObject
}
// form request body

View file

@ -296,17 +296,17 @@ 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).
// Returns an error if parameters are set incorrectly (see PrmObjectGet docs).
// Context is required and must not be nil. It is used for network communication.
func (c *Client) ObjectGetInit(ctx context.Context, prm PrmObjectGet) (*ObjectReader, error) {
// check parameters
switch {
case ctx == nil:
panic(panicMsgMissingContext)
return nil, errorMissingContext
case prm.addr.GetContainerID() == nil:
panic(panicMsgMissingContainer)
return nil, errorMissingContainer
case prm.addr.GetObjectID() == nil:
panic(panicMsgMissingObject)
return nil, errorMissingObject
}
// form request body
@ -400,7 +400,7 @@ func (x *ResObjectHead) ReadHeader(dst *object.Object) bool {
// FrostFS status codes are returned as `error`, otherwise, are included
// in the returned result structure.
//
// Immediately panics if parameters are set incorrectly (see PrmObjectHead docs).
// Returns an error if parameters are set incorrectly (see PrmObjectHead docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return errors:
@ -417,11 +417,11 @@ func (x *ResObjectHead) ReadHeader(dst *object.Object) bool {
func (c *Client) ObjectHead(ctx context.Context, prm PrmObjectHead) (*ResObjectHead, error) {
switch {
case ctx == nil:
panic(panicMsgMissingContext)
return nil, errorMissingContext
case prm.addr.GetContainerID() == nil:
panic(panicMsgMissingContainer)
return nil, errorMissingContainer
case prm.addr.GetObjectID() == nil:
panic(panicMsgMissingObject)
return nil, errorMissingObject
}
var body v2object.HeadRequestBody
@ -663,19 +663,19 @@ 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).
// Returns an error if parameters are set incorrectly (see PrmObjectRange docs).
// Context is required and must not be nil. It is used for network communication.
func (c *Client) ObjectRangeInit(ctx context.Context, prm PrmObjectRange) (*ObjectRangeReader, error) {
// check parameters
switch {
case ctx == nil:
panic(panicMsgMissingContext)
return nil, errorMissingContext
case prm.addr.GetContainerID() == nil:
panic(panicMsgMissingContainer)
return nil, errorMissingContainer
case prm.addr.GetObjectID() == nil:
panic(panicMsgMissingObject)
return nil, errorMissingObject
case prm.rng.GetLength() == 0:
panic("zero range length")
return nil, errorZeroRangeLength
}
// form request body

View file

@ -154,7 +154,7 @@ func (x ResObjectHash) Checksums() [][]byte {
// FrostFS status codes are returned as `error`, otherwise, are included
// in the returned result structure.
//
// Immediately panics if parameters are set incorrectly (see PrmObjectHash docs).
// Returns an error if parameters are set incorrectly (see PrmObjectHash docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return statuses:
@ -167,13 +167,13 @@ func (x ResObjectHash) Checksums() [][]byte {
func (c *Client) ObjectHash(ctx context.Context, prm PrmObjectHash) (*ResObjectHash, error) {
switch {
case ctx == nil:
panic(panicMsgMissingContext)
return nil, errorMissingContext
case prm.addr.GetContainerID() == nil:
panic(panicMsgMissingContainer)
return nil, errorMissingContainer
case prm.addr.GetObjectID() == nil:
panic(panicMsgMissingObject)
return nil, errorMissingObject
case len(prm.body.GetRanges()) == 0:
panic("missing ranges")
return nil, errorMissingRanges
}
prm.body.SetAddress(&prm.addr)

View file

@ -235,11 +235,12 @@ func (x *ObjectWriter) Close() (*ResObjectPut, error) {
// The call only opens the transmission channel, explicit recording is done using the ObjectWriter.
// Exactly one return value is non-nil. Resulting writer must be finally closed.
//
// Returns an error if parameters are set incorrectly.
// Context is required and must not be nil. It is used for network communication.
func (c *Client) ObjectPutInit(ctx context.Context, prm PrmObjectPutInit) (*ObjectWriter, error) {
// check parameters
if ctx == nil {
panic(panicMsgMissingContext)
return nil, errorMissingContext
}
var w ObjectWriter

View file

@ -218,15 +218,15 @@ func (x *ObjectListReader) Close() (*ResObjectSearch, 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).
// Returns an error if parameters are set incorrectly (see PrmObjectSearch docs).
// Context is required and must not be nil. It is used for network communication.
func (c *Client) ObjectSearchInit(ctx context.Context, prm PrmObjectSearch) (*ObjectListReader, error) {
// check parameters
switch {
case ctx == nil:
panic(panicMsgMissingContext)
return nil, errorMissingContext
case !prm.cnrSet:
panic(panicMsgMissingContainer)
return nil, errorMissingContainer
}
var cidV2 v2refs.ContainerID

View file

@ -45,7 +45,7 @@ type ResAnnounceLocalTrust struct {
// FrostFS status codes are returned as `error`, otherwise, are included
// in the returned result structure.
//
// Immediately panics if parameters are set incorrectly (see PrmAnnounceLocalTrust docs).
// Returns an error if parameters are set incorrectly (see PrmAnnounceLocalTrust docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return statuses:
@ -54,11 +54,11 @@ func (c *Client) AnnounceLocalTrust(ctx context.Context, prm PrmAnnounceLocalTru
// check parameters
switch {
case ctx == nil:
panic(panicMsgMissingContext)
return nil, errorMissingContext
case prm.epoch == 0:
panic("zero epoch")
return nil, errorZeroEpoch
case len(prm.trusts) == 0:
panic("missing trusts")
return nil, errorMissingTrusts
}
// form request body
@ -146,7 +146,7 @@ type ResAnnounceIntermediateTrust struct {
// FrostFS status codes are returned as `error`, otherwise, are included
// in the returned result structure.
//
// Immediately panics if parameters are set incorrectly (see PrmAnnounceIntermediateTrust docs).
// Returns an error if parameters are set incorrectly (see PrmAnnounceIntermediateTrust docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return statuses:
@ -155,11 +155,11 @@ func (c *Client) AnnounceIntermediateTrust(ctx context.Context, prm PrmAnnounceI
// check parameters
switch {
case ctx == nil:
panic(panicMsgMissingContext)
return nil, errorMissingContext
case prm.epoch == 0:
panic("zero epoch")
return nil, errorZeroEpoch
case !prm.trustSet:
panic("current trust value not set")
return nil, errorTrustNotSet
}
var trust v2reputation.PeerToPeerTrust

View file

@ -72,7 +72,7 @@ func (x ResSessionCreate) PublicKey() []byte {
// FrostFS status codes are returned as `error`, otherwise, are included
// in the returned result structure.
//
// Immediately panics if parameters are set incorrectly (see PrmSessionCreate docs).
// Returns an error if parameters are set incorrectly (see PrmSessionCreate docs).
// Context is required and must not be nil. It is used for network communication.
//
// Return statuses:
@ -80,7 +80,7 @@ func (x ResSessionCreate) PublicKey() []byte {
func (c *Client) SessionCreate(ctx context.Context, prm PrmSessionCreate) (*ResSessionCreate, error) {
// check context
if ctx == nil {
panic(panicMsgMissingContext)
return nil, errorMissingContext
}
ownerKey := c.prm.key.PublicKey