diff --git a/pkg/services/container/morph/executor.go b/pkg/services/container/morph/executor.go index 3a9eacd4..fc342f8e 100644 --- a/pkg/services/container/morph/executor.go +++ b/pkg/services/container/morph/executor.go @@ -21,6 +21,8 @@ type morphExecutor struct { wrapper *wrapper.Wrapper rdr Reader + + invalidator Invalidator } // Reader is an interface of read-only container storage. @@ -34,10 +36,27 @@ type Reader interface { List(*owner.ID) ([]*cid.ID, error) } -func NewExecutor(w *wrapper.Wrapper, rdr Reader) containerSvc.ServiceExecutor { +// Invalidator is an interface of local cache invalidator. It removes cached +// values in order to synchronize updated data in the side chain faster. +type Invalidator interface { + // InvalidateContainer from the local container cache if it exists. + InvalidateContainer(*cid.ID) + // InvalidateEACL from the local eACL cache if it exists. + InvalidateEACL(*cid.ID) + // InvalidateContainerList from the local cache of container list results + // 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 { return &morphExecutor{ - wrapper: w, - rdr: rdr, + wrapper: w, + rdr: rdr, + invalidator: i, } } @@ -57,6 +76,8 @@ func (s *morphExecutor) Put(ctx containerSvc.ContextWithToken, body *container.P return nil, err } + s.invalidator.InvalidateContainerList(cnr.OwnerID()) + res := new(container.PutResponseBody) res.SetContainerID(cid.ToV2()) @@ -79,6 +100,13 @@ func (s *morphExecutor) Delete(ctx containerSvc.ContextWithToken, body *containe 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 } @@ -128,8 +156,13 @@ func (s *morphExecutor) SetExtendedACL(ctx containerSvc.ContextWithToken, body * ) err := wrapper.PutEACL(s.wrapper, table) + if err != nil { + return nil, err + } - return new(container.SetExtendedACLResponseBody), err + s.invalidator.InvalidateEACL(table.CID()) + + return new(container.SetExtendedACLResponseBody), nil } func (s *morphExecutor) GetExtendedACL(ctx context.Context, body *container.GetExtendedACLRequestBody) (*container.GetExtendedACLResponseBody, error) {