[#38] Add retrying when session token error

Signed-off-by: Denis Kirillov <denis@nspcc.ru>
This commit is contained in:
Denis Kirillov 2021-11-03 17:34:02 +03:00 committed by Alex Vanin
parent e08e3d6c00
commit 1d546711e5
2 changed files with 76 additions and 21 deletions

View file

@ -93,6 +93,11 @@ type Pool interface {
WaitForContainerPresence(context.Context, *cid.ID, *ContainerPollingParams) error WaitForContainerPresence(context.Context, *cid.ID, *ContainerPollingParams) error
Close() Close()
ClientParam
}
// ClientParam is analogue client.Object, client.Container but uses session token cache.
type ClientParam interface {
PutObjectParam(ctx context.Context, params *client.PutObjectParams, callParam *CallParam) (*object.ID, error) PutObjectParam(ctx context.Context, params *client.PutObjectParams, callParam *CallParam) (*object.ID, error)
DeleteObjectParam(ctx context.Context, params *client.DeleteObjectParams, callParam *CallParam) error DeleteObjectParam(ctx context.Context, params *client.DeleteObjectParams, callParam *CallParam) error
GetObjectParam(ctx context.Context, params *client.GetObjectParams, callParam *CallParam) (*object.Object, error) GetObjectParam(ctx context.Context, params *client.GetObjectParams, callParam *CallParam) (*object.Object, error)
@ -117,6 +122,7 @@ type clientPack struct {
} }
type CallParam struct { type CallParam struct {
isRetry bool
Key *ecdsa.PrivateKey Key *ecdsa.PrivateKey
Options []client.CallOption Options []client.CallOption
@ -464,14 +470,17 @@ func (p *pool) AnnounceContainerUsedSpace(ctx context.Context, announce []contai
return conn.AnnounceContainerUsedSpace(ctx, announce, options...) return conn.AnnounceContainerUsedSpace(ctx, announce, options...)
} }
func (p *pool) checkSessionTokenErr(err error, address string) { func (p *pool) checkSessionTokenErr(err error, address string) bool {
if err == nil { if err == nil {
return return false
} }
if strings.Contains(err.Error(), "session token does not exist") { if strings.Contains(err.Error(), "session token does not exist") {
p.cache.DeleteByPrefix(address) p.cache.DeleteByPrefix(address)
return true
} }
return false
} }
func (p *pool) PutObjectParam(ctx context.Context, params *client.PutObjectParams, callParam *CallParam) (*object.ID, error) { func (p *pool) PutObjectParam(ctx context.Context, params *client.PutObjectParams, callParam *CallParam) (*object.ID, error) {
@ -480,7 +489,10 @@ func (p *pool) PutObjectParam(ctx context.Context, params *client.PutObjectParam
return nil, err return nil, err
} }
res, err := cp.client.PutObject(ctx, params, options...) res, err := cp.client.PutObject(ctx, params, options...)
p.checkSessionTokenErr(err, cp.address) if p.checkSessionTokenErr(err, cp.address) && !callParam.isRetry {
callParam.isRetry = true
return p.PutObjectParam(ctx, params, callParam)
}
return res, err return res, err
} }
@ -490,7 +502,10 @@ func (p *pool) DeleteObjectParam(ctx context.Context, params *client.DeleteObjec
return err return err
} }
err = cp.client.DeleteObject(ctx, params, options...) err = cp.client.DeleteObject(ctx, params, options...)
p.checkSessionTokenErr(err, cp.address) if p.checkSessionTokenErr(err, cp.address) && !callParam.isRetry {
callParam.isRetry = true
return p.DeleteObjectParam(ctx, params, callParam)
}
return err return err
} }
@ -500,7 +515,10 @@ func (p *pool) GetObjectParam(ctx context.Context, params *client.GetObjectParam
return nil, err return nil, err
} }
res, err := cp.client.GetObject(ctx, params, options...) res, err := cp.client.GetObject(ctx, params, options...)
p.checkSessionTokenErr(err, cp.address) if p.checkSessionTokenErr(err, cp.address) && !callParam.isRetry {
callParam.isRetry = true
return p.GetObjectParam(ctx, params, callParam)
}
return res, err return res, err
} }
@ -510,7 +528,10 @@ func (p *pool) GetObjectHeaderParam(ctx context.Context, params *client.ObjectHe
return nil, err return nil, err
} }
res, err := cp.client.GetObjectHeader(ctx, params, options...) res, err := cp.client.GetObjectHeader(ctx, params, options...)
p.checkSessionTokenErr(err, cp.address) if p.checkSessionTokenErr(err, cp.address) && !callParam.isRetry {
callParam.isRetry = true
return p.GetObjectHeaderParam(ctx, params, callParam)
}
return res, err return res, err
} }
@ -520,7 +541,10 @@ func (p *pool) ObjectPayloadRangeDataParam(ctx context.Context, params *client.R
return nil, err return nil, err
} }
res, err := cp.client.ObjectPayloadRangeData(ctx, params, options...) res, err := cp.client.ObjectPayloadRangeData(ctx, params, options...)
p.checkSessionTokenErr(err, cp.address) if p.checkSessionTokenErr(err, cp.address) && !callParam.isRetry {
callParam.isRetry = true
return p.ObjectPayloadRangeDataParam(ctx, params, callParam)
}
return res, err return res, err
} }
@ -530,7 +554,10 @@ func (p *pool) ObjectPayloadRangeSHA256Param(ctx context.Context, params *client
return nil, err return nil, err
} }
res, err := cp.client.ObjectPayloadRangeSHA256(ctx, params, options...) res, err := cp.client.ObjectPayloadRangeSHA256(ctx, params, options...)
p.checkSessionTokenErr(err, cp.address) if p.checkSessionTokenErr(err, cp.address) && !callParam.isRetry {
callParam.isRetry = true
return p.ObjectPayloadRangeSHA256Param(ctx, params, callParam)
}
return res, err return res, err
} }
@ -540,7 +567,10 @@ func (p *pool) ObjectPayloadRangeTZParam(ctx context.Context, params *client.Ran
return nil, err return nil, err
} }
res, err := cp.client.ObjectPayloadRangeTZ(ctx, params, options...) res, err := cp.client.ObjectPayloadRangeTZ(ctx, params, options...)
p.checkSessionTokenErr(err, cp.address) if p.checkSessionTokenErr(err, cp.address) && !callParam.isRetry {
callParam.isRetry = true
return p.ObjectPayloadRangeTZParam(ctx, params, callParam)
}
return res, err return res, err
} }
@ -550,7 +580,10 @@ func (p *pool) SearchObjectParam(ctx context.Context, params *client.SearchObjec
return nil, err return nil, err
} }
res, err := cp.client.SearchObject(ctx, params, options...) res, err := cp.client.SearchObject(ctx, params, options...)
p.checkSessionTokenErr(err, cp.address) if p.checkSessionTokenErr(err, cp.address) && !callParam.isRetry {
callParam.isRetry = true
return p.SearchObjectParam(ctx, params, callParam)
}
return res, err return res, err
} }
@ -560,7 +593,10 @@ func (p *pool) PutContainerParam(ctx context.Context, cnr *container.Container,
return nil, err return nil, err
} }
res, err := cp.client.PutContainer(ctx, cnr, options...) res, err := cp.client.PutContainer(ctx, cnr, options...)
p.checkSessionTokenErr(err, cp.address) if p.checkSessionTokenErr(err, cp.address) && !callParam.isRetry {
callParam.isRetry = true
return p.PutContainerParam(ctx, cnr, callParam)
}
return res, err return res, err
} }
@ -570,7 +606,10 @@ func (p *pool) GetContainerParam(ctx context.Context, cid *cid.ID, callParam *Ca
return nil, err return nil, err
} }
res, err := cp.client.GetContainer(ctx, cid, options...) res, err := cp.client.GetContainer(ctx, cid, options...)
p.checkSessionTokenErr(err, cp.address) if p.checkSessionTokenErr(err, cp.address) && !callParam.isRetry {
callParam.isRetry = true
return p.GetContainerParam(ctx, cid, callParam)
}
return res, err return res, err
} }
@ -580,7 +619,10 @@ func (p *pool) ListContainersParam(ctx context.Context, ownerID *owner.ID, callP
return nil, err return nil, err
} }
res, err := cp.client.ListContainers(ctx, ownerID, options...) res, err := cp.client.ListContainers(ctx, ownerID, options...)
p.checkSessionTokenErr(err, cp.address) if p.checkSessionTokenErr(err, cp.address) && !callParam.isRetry {
callParam.isRetry = true
return p.ListContainersParam(ctx, ownerID, callParam)
}
return res, err return res, err
} }
@ -590,7 +632,10 @@ func (p *pool) DeleteContainerParam(ctx context.Context, cid *cid.ID, callParam
return err return err
} }
err = cp.client.DeleteContainer(ctx, cid, options...) err = cp.client.DeleteContainer(ctx, cid, options...)
p.checkSessionTokenErr(err, cp.address) if p.checkSessionTokenErr(err, cp.address) && !callParam.isRetry {
callParam.isRetry = true
return p.DeleteContainerParam(ctx, cid, callParam)
}
return err return err
} }
@ -600,7 +645,10 @@ func (p *pool) GetEACLParam(ctx context.Context, cid *cid.ID, callParam *CallPar
return nil, err return nil, err
} }
res, err := cp.client.GetEACL(ctx, cid, options...) res, err := cp.client.GetEACL(ctx, cid, options...)
p.checkSessionTokenErr(err, cp.address) if p.checkSessionTokenErr(err, cp.address) && !callParam.isRetry {
callParam.isRetry = true
return p.GetEACLParam(ctx, cid, callParam)
}
return res, err return res, err
} }
@ -610,7 +658,10 @@ func (p *pool) SetEACLParam(ctx context.Context, table *eacl.Table, callParam *C
return err return err
} }
err = cp.client.SetEACL(ctx, table, options...) err = cp.client.SetEACL(ctx, table, options...)
p.checkSessionTokenErr(err, cp.address) if p.checkSessionTokenErr(err, cp.address) && !callParam.isRetry {
callParam.isRetry = true
return p.SetEACLParam(ctx, table, callParam)
}
return err return err
} }
@ -620,7 +671,10 @@ func (p *pool) AnnounceContainerUsedSpaceParam(ctx context.Context, announce []c
return err return err
} }
err = cp.client.AnnounceContainerUsedSpace(ctx, announce, options...) err = cp.client.AnnounceContainerUsedSpace(ctx, announce, options...)
p.checkSessionTokenErr(err, cp.address) if p.checkSessionTokenErr(err, cp.address) && !callParam.isRetry {
callParam.isRetry = true
return p.AnnounceContainerUsedSpaceParam(ctx, announce, callParam)
}
return err return err
} }

View file

@ -321,10 +321,11 @@ func TestSessionCache(t *testing.T) {
tok.SetID(uid) tok.SetID(uid)
tokens = append(tokens, tok) tokens = append(tokens, tok)
return tok, err return tok, err
}).MaxTimes(2) }).MaxTimes(3)
mockClient.EXPECT().GetObject(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, fmt.Errorf("session token does not exist")) mockClient.EXPECT().GetObject(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, fmt.Errorf("session token does not exist"))
mockClient.EXPECT().PutObject(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil) mockClient.EXPECT().PutObject(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, fmt.Errorf("session token does not exist"))
mockClient.EXPECT().PutObject(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, nil)
return mockClient, nil return mockClient, nil
} }
@ -351,7 +352,7 @@ func TestSessionCache(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Contains(t, tokens, st) require.Contains(t, tokens, st)
_, err = pool.GetObjectParam(ctx, nil, &CallParam{}) _, err = pool.GetObjectParam(ctx, nil, &CallParam{isRetry: true})
require.Error(t, err) require.Error(t, err)
// cache must not contain session token // cache must not contain session token