package deletesvc import ( "context" objectSDK "github.com/nspcc-dev/neofs-api-go/pkg/object" "github.com/nspcc-dev/neofs-api-go/pkg/owner" "github.com/nspcc-dev/neofs-node/pkg/core/object" headsvc "github.com/nspcc-dev/neofs-node/pkg/services/object/head" putsvc "github.com/nspcc-dev/neofs-node/pkg/services/object/put" objutil "github.com/nspcc-dev/neofs-node/pkg/services/object/util" "github.com/pkg/errors" ) type Service struct { *cfg } type Option func(*cfg) type RelationHeader interface { HeadRelation(context.Context, *objectSDK.Address) (*object.Object, error) } type cfg struct { ownerID *owner.ID keyStorage *objutil.KeyStorage putSvc *putsvc.Service headSvc *headsvc.Service hdrLinking RelationHeader } func defaultCfg() *cfg { return new(cfg) } func NewService(opts ...Option) *Service { c := defaultCfg() for i := range opts { opts[i](c) } return &Service{ cfg: c, } } func (s *Service) Delete(ctx context.Context, prm *Prm) (*Response, error) { ownerID := s.ownerID if token := prm.common.SessionToken(); token != nil { ownerID = token.OwnerID() } if ownerID == nil { return nil, errors.Errorf("(%T) missing owner identifier", s) } tool := &deleteTool{ ctx: ctx, putSvc: s.putSvc, obj: newTombstone(ownerID, prm.addr.GetContainerID()), addr: prm.addr, commonPrm: prm.common, } if linking, err := s.hdrLinking.HeadRelation(ctx, prm.addr); err != nil { if err := s.deleteAll(tool); err != nil { return nil, errors.Wrapf(err, "(%T) could not delete all object relations", s) } } else { if err := tool.delete(prm.addr.GetObjectID()); err != nil { return nil, errors.Wrapf(err, "(%T) could not delete object", s) } for _, child := range linking.GetChildren() { if err := tool.delete(child); err != nil { return nil, errors.Wrapf(err, "(%T) could not delete child object", s) } } if err := tool.delete(linking.GetID()); err != nil { return nil, errors.Wrapf(err, "(%T) could not delete linking object", s) } } return new(Response), nil } func (s *Service) deleteAll(tool *deleteTool) error { headResult, err := s.headSvc.Head(tool.ctx, new(headsvc.Prm). WithAddress(tool.addr). WithCommonPrm(tool.commonPrm), ) if err != nil { return errors.Wrapf(err, "(%T) could not receive Head result", s) } hdr := headResult.Header() if err := tool.delete(hdr.GetID()); err != nil { return errors.Wrapf(err, "(%T) could not remove object", s) } prevID := hdr.GetPreviousID() if rightChild := headResult.RightChild(); rightChild != nil { if err := tool.delete(rightChild.GetID()); err != nil { return errors.Wrapf(err, "(%T) could not remove right child", s) } prevID = rightChild.GetPreviousID() } if prevID != nil { tool.addr.SetObjectID(prevID) return s.deleteAll(tool) } return nil } func WithOwnerID(v *owner.ID) Option { return func(c *cfg) { c.ownerID = v } } func WithKeyStorage(v *objutil.KeyStorage) Option { return func(c *cfg) { c.keyStorage = v } } func WithPutService(v *putsvc.Service) Option { return func(c *cfg) { c.putSvc = v } } func WitHeadService(v *headsvc.Service) Option { return func(c *cfg) { c.headSvc = v } } func WithLinkingHeader(v RelationHeader) Option { return func(c *cfg) { c.hdrLinking = v } }