diff --git a/cmd/neofs-node/object.go b/cmd/neofs-node/object.go index 54614cbec9..c101442ad0 100644 --- a/cmd/neofs-node/object.go +++ b/cmd/neofs-node/object.go @@ -569,6 +569,14 @@ func newFSChainForObjects(placementSvc *placement.Service, isLocalPubKey func([] } } +// ResetContainer drops cached container, if any, so that next Get fetches it +// from the FS chain. +func (x *fsChainForObjects) ResetContainer(id cid.ID) { + if r, ok := x.Source.(interface{ resetContainer(cid.ID) }); ok { + r.resetContainer(id) + } +} + // InContainerInLastTwoEpochs checks whether given public key belongs to any SN // from the referenced container either in the current or the previous NeoFS // epoch. diff --git a/pkg/services/object/common.go b/pkg/services/object/common.go index 9385c59ca3..a3a0fd6c76 100644 --- a/pkg/services/object/common.go +++ b/pkg/services/object/common.go @@ -211,6 +211,16 @@ func (s *Server) checkContainerRevision(clientCnrRev uint64, cID cid.ID) error { return fmt.Errorf("fetching container from FS chain: %w", err) } + if clientCnrRev > cnr.Revision() { + // server's data may be outdated, try to fetch the newer one + if r, ok := s.fsChain.(interface{ ResetContainer(cid.ID) }); ok { + r.ResetContainer(cID) + if cnr, err = s.fsChain.Get(cID); err != nil { + return fmt.Errorf("fetching container from FS chain: %w", err) + } + } + } + if srvCnrRev := cnr.Revision(); clientCnrRev != srvCnrRev { return apistatus.NewContainerRevisionMismatch(fmt.Sprintf( "container revision does not match: requested: %d, server's: %d", clientCnrRev, srvCnrRev))