forked from TrueCloudLab/frostfs-node
[#811] service/container: Hide cache invalidation logic in Writer interface
Signed-off-by: Alex Vanin <alexey@nspcc.ru>
This commit is contained in:
parent
49b6b5b49d
commit
01df4ffa61
2 changed files with 64 additions and 67 deletions
|
@ -58,7 +58,10 @@ func initContainerService(c *cfg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
cnrRdr := new(morphContainerReader)
|
cnrRdr := new(morphContainerReader)
|
||||||
cnrInvalidator := new(morphContainerInvalidator)
|
|
||||||
|
cnrWrt := &morphContainerWriter{
|
||||||
|
neoClient: wrap,
|
||||||
|
}
|
||||||
|
|
||||||
if c.cfgMorph.disableCache {
|
if c.cfgMorph.disableCache {
|
||||||
c.cfgObject.eaclSource = eACLFetcher
|
c.cfgObject.eaclSource = eACLFetcher
|
||||||
|
@ -79,9 +82,10 @@ func initContainerService(c *cfg) {
|
||||||
cnrRdr.eacl = c.cfgObject.eaclSource
|
cnrRdr.eacl = c.cfgObject.eaclSource
|
||||||
cnrRdr.get = c.cfgObject.cnrSource
|
cnrRdr.get = c.cfgObject.cnrSource
|
||||||
|
|
||||||
cnrInvalidator.lists = cachedContainerLister
|
cnrWrt.cacheEnabled = true
|
||||||
cnrInvalidator.eacls = cachedEACLStorage
|
cnrWrt.lists = cachedContainerLister
|
||||||
cnrInvalidator.containers = cachedContainerStorage
|
cnrWrt.eacls = cachedEACLStorage
|
||||||
|
cnrWrt.containers = cachedContainerStorage
|
||||||
}
|
}
|
||||||
|
|
||||||
localMetrics := &localStorageLoad{
|
localMetrics := &localStorageLoad{
|
||||||
|
@ -152,7 +156,7 @@ func initContainerService(c *cfg) {
|
||||||
&c.key.PrivateKey,
|
&c.key.PrivateKey,
|
||||||
containerService.NewResponseService(
|
containerService.NewResponseService(
|
||||||
&usedSpaceService{
|
&usedSpaceService{
|
||||||
Server: containerService.NewExecutionService(containerMorph.NewExecutor(wrap, cnrRdr, cnrInvalidator)),
|
Server: containerService.NewExecutionService(containerMorph.NewExecutor(cnrRdr, cnrWrt)),
|
||||||
loadWriterProvider: loadRouter,
|
loadWriterProvider: loadRouter,
|
||||||
loadPlacementBuilder: loadPlacementBuilder,
|
loadPlacementBuilder: loadPlacementBuilder,
|
||||||
routeBuilder: routeBuilder,
|
routeBuilder: routeBuilder,
|
||||||
|
@ -539,41 +543,56 @@ func (x *morphContainerReader) List(id *owner.ID) ([]*cid.ID, error) {
|
||||||
return x.lister.List(id)
|
return x.lister.List(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
type morphContainerInvalidator struct {
|
type morphContainerWriter struct {
|
||||||
containers interface {
|
neoClient *wrapper.Wrapper
|
||||||
InvalidateContainer(*cid.ID)
|
|
||||||
}
|
|
||||||
|
|
||||||
eacls interface {
|
cacheEnabled bool
|
||||||
InvalidateEACL(*cid.ID)
|
containers *ttlContainerStorage
|
||||||
}
|
eacls *ttlEACLStorage
|
||||||
|
lists *ttlContainerLister
|
||||||
lists interface {
|
|
||||||
InvalidateContainerList(*owner.ID)
|
|
||||||
InvalidateContainerListByCID(*cid.ID)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *morphContainerInvalidator) InvalidateContainer(id *cid.ID) {
|
func (m morphContainerWriter) Put(cnr *containerSDK.Container) (*cid.ID, error) {
|
||||||
if x.containers != nil {
|
containerID, err := wrapper.Put(m.neoClient, cnr)
|
||||||
x.containers.InvalidateContainer(id)
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if m.cacheEnabled {
|
||||||
|
m.lists.InvalidateContainerList(cnr.OwnerID())
|
||||||
|
}
|
||||||
|
|
||||||
|
return containerID, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *morphContainerInvalidator) InvalidateEACL(id *cid.ID) {
|
func (m morphContainerWriter) Delete(witness containerCore.RemovalWitness) error {
|
||||||
if x.eacls != nil {
|
err := wrapper.Delete(m.neoClient, witness)
|
||||||
x.eacls.InvalidateEACL(id)
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if m.cacheEnabled {
|
||||||
|
containerID := witness.ContainerID()
|
||||||
|
|
||||||
|
m.containers.InvalidateContainer(containerID)
|
||||||
|
m.eacls.InvalidateEACL(containerID)
|
||||||
|
// it is faster to use slower invalidation by CID than making separate
|
||||||
|
// network request to fetch owner ID of the container.
|
||||||
|
m.lists.InvalidateContainerListByCID(containerID)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *morphContainerInvalidator) InvalidateContainerList(id *owner.ID) {
|
func (m morphContainerWriter) PutEACL(table *eaclSDK.Table) error {
|
||||||
if x.lists != nil {
|
err := wrapper.PutEACL(m.neoClient, table)
|
||||||
x.lists.InvalidateContainerList(id)
|
if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func (x *morphContainerInvalidator) InvalidateContainerListByCID(id *cid.ID) {
|
if m.cacheEnabled {
|
||||||
if x.lists != nil {
|
m.eacls.InvalidateEACL(table.CID())
|
||||||
x.lists.InvalidateContainerListByCID(id)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,17 +12,13 @@ import (
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/container"
|
"github.com/nspcc-dev/neofs-api-go/v2/container"
|
||||||
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
"github.com/nspcc-dev/neofs-api-go/v2/refs"
|
||||||
containercore "github.com/nspcc-dev/neofs-node/pkg/core/container"
|
containercore "github.com/nspcc-dev/neofs-node/pkg/core/container"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/morph/client/container/wrapper"
|
|
||||||
containerSvc "github.com/nspcc-dev/neofs-node/pkg/services/container"
|
containerSvc "github.com/nspcc-dev/neofs-node/pkg/services/container"
|
||||||
"github.com/nspcc-dev/neofs-node/pkg/services/object/acl/eacl"
|
"github.com/nspcc-dev/neofs-node/pkg/services/object/acl/eacl"
|
||||||
)
|
)
|
||||||
|
|
||||||
type morphExecutor struct {
|
type morphExecutor struct {
|
||||||
wrapper *wrapper.Wrapper
|
|
||||||
|
|
||||||
rdr Reader
|
rdr Reader
|
||||||
|
wrt Writer
|
||||||
invalidator Invalidator
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reader is an interface of read-only container storage.
|
// Reader is an interface of read-only container storage.
|
||||||
|
@ -36,27 +32,20 @@ type Reader interface {
|
||||||
List(*owner.ID) ([]*cid.ID, error)
|
List(*owner.ID) ([]*cid.ID, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidator is an interface of local cache invalidator. It removes cached
|
// Writer is an interface of container storage updater.
|
||||||
// values in order to synchronize updated data in the side chain faster.
|
type Writer interface {
|
||||||
type Invalidator interface {
|
// Put stores specified container in the side chain.
|
||||||
// InvalidateContainer from the local container cache if it exists.
|
Put(*containerSDK.Container) (*cid.ID, error)
|
||||||
InvalidateContainer(*cid.ID)
|
// Delete removes specified container from the side chain.
|
||||||
// InvalidateEACL from the local eACL cache if it exists.
|
Delete(containercore.RemovalWitness) error
|
||||||
InvalidateEACL(*cid.ID)
|
// PutEACL updates extended ACL table of specified container in the side chain.
|
||||||
// InvalidateContainerList from the local cache of container list results
|
PutEACL(*eaclSDK.Table) error
|
||||||
// if it exists.
|
|
||||||
InvalidateContainerList(*owner.ID)
|
|
||||||
// InvalidateContainerListByCID from the local cache of container list
|
|
||||||
// results if it exists. Container list source uses owner.ID as a key,
|
|
||||||
// so invalidating cache record by the value requires different approach.
|
|
||||||
InvalidateContainerListByCID(*cid.ID)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewExecutor(w *wrapper.Wrapper, rdr Reader, i Invalidator) containerSvc.ServiceExecutor {
|
func NewExecutor(rdr Reader, wrt Writer) containerSvc.ServiceExecutor {
|
||||||
return &morphExecutor{
|
return &morphExecutor{
|
||||||
wrapper: w,
|
rdr: rdr,
|
||||||
rdr: rdr,
|
wrt: wrt,
|
||||||
invalidator: i,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,13 +60,11 @@ func (s *morphExecutor) Put(ctx containerSvc.ContextWithToken, body *container.P
|
||||||
session.NewTokenFromV2(ctx.SessionToken),
|
session.NewTokenFromV2(ctx.SessionToken),
|
||||||
)
|
)
|
||||||
|
|
||||||
cid, err := wrapper.Put(s.wrapper, cnr)
|
cid, err := s.wrt.Put(cnr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.invalidator.InvalidateContainerList(cnr.OwnerID())
|
|
||||||
|
|
||||||
res := new(container.PutResponseBody)
|
res := new(container.PutResponseBody)
|
||||||
res.SetContainerID(cid.ToV2())
|
res.SetContainerID(cid.ToV2())
|
||||||
|
|
||||||
|
@ -95,18 +82,11 @@ func (s *morphExecutor) Delete(ctx containerSvc.ContextWithToken, body *containe
|
||||||
rmWitness.SetSignature(sig)
|
rmWitness.SetSignature(sig)
|
||||||
rmWitness.SetSessionToken(tok)
|
rmWitness.SetSessionToken(tok)
|
||||||
|
|
||||||
err := wrapper.Delete(s.wrapper, rmWitness)
|
err := s.wrt.Delete(rmWitness)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.invalidator.InvalidateContainer(id)
|
|
||||||
s.invalidator.InvalidateEACL(id)
|
|
||||||
|
|
||||||
// it is faster to use slower invalidation by CID than making separate
|
|
||||||
// network request to fetch owner ID of the container.
|
|
||||||
s.invalidator.InvalidateContainerListByCID(id)
|
|
||||||
|
|
||||||
return new(container.DeleteResponseBody), nil
|
return new(container.DeleteResponseBody), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,13 +135,11 @@ func (s *morphExecutor) SetExtendedACL(ctx containerSvc.ContextWithToken, body *
|
||||||
session.NewTokenFromV2(ctx.SessionToken),
|
session.NewTokenFromV2(ctx.SessionToken),
|
||||||
)
|
)
|
||||||
|
|
||||||
err := wrapper.PutEACL(s.wrapper, table)
|
err := s.wrt.PutEACL(table)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.invalidator.InvalidateEACL(table.CID())
|
|
||||||
|
|
||||||
return new(container.SetExtendedACLResponseBody), nil
|
return new(container.SetExtendedACLResponseBody), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue