Files
sendico/api/pkg/db/internal/mongo/archivable/archivable.go
Stephan D 62a6631b9a
All checks were successful
ci/woodpecker/push/db Pipeline was successful
ci/woodpecker/push/nats Pipeline was successful
service backend
2025-11-07 18:35:26 +01:00

100 lines
3.1 KiB
Go

package archivable
import (
"context"
"github.com/tech/sendico/pkg/db/repository"
"github.com/tech/sendico/pkg/db/storable"
"github.com/tech/sendico/pkg/mlogger"
"github.com/tech/sendico/pkg/model"
"github.com/tech/sendico/pkg/mutil/mzap"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.uber.org/zap"
)
// ArchivableDB implements archive management for entities with model.Archivable embedded
type ArchivableDB[T storable.Storable] struct {
repo repository.Repository
logger mlogger.Logger
createEmpty func() T
getArchivable func(T) model.Archivable
}
// NewArchivableDB creates a new ArchivableDB instance
func NewArchivableDB[T storable.Storable](
repo repository.Repository,
logger mlogger.Logger,
createEmpty func() T,
getArchivable func(T) model.Archivable,
) *ArchivableDB[T] {
return &ArchivableDB[T]{
repo: repo,
logger: logger,
createEmpty: createEmpty,
getArchivable: getArchivable,
}
}
// SetArchived sets the archived status of an entity
func (db *ArchivableDB[T]) SetArchived(ctx context.Context, objectRef primitive.ObjectID, archived bool) error {
// Get current object to check current archived status
obj := db.createEmpty()
if err := db.repo.Get(ctx, objectRef, obj); err != nil {
db.logger.Warn("Failed to get object for setting archived status",
zap.Error(err),
mzap.ObjRef("object_ref", objectRef),
zap.Bool("archived", archived))
return err
}
// Extract archivable from the object
archivable := db.getArchivable(obj)
currentArchived := archivable.IsArchived()
if currentArchived == archived {
db.logger.Debug("No change needed - same archived status",
mzap.ObjRef("object_ref", objectRef),
zap.Bool("archived", archived))
return nil // No change needed
}
// Set the archived status
patch := repository.Patch().Set(repository.IsArchivedField(), archived)
if err := db.repo.Patch(ctx, objectRef, patch); err != nil {
db.logger.Warn("Failed to set archived status on object",
zap.Error(err),
mzap.ObjRef("object_ref", objectRef),
zap.Bool("archived", archived))
return err
}
db.logger.Debug("Successfully set archived status on object",
mzap.ObjRef("object_ref", objectRef),
zap.Bool("archived", archived))
return nil
}
// IsArchived checks if an entity is archived
func (db *ArchivableDB[T]) IsArchived(ctx context.Context, objectRef primitive.ObjectID) (bool, error) {
obj := db.createEmpty()
if err := db.repo.Get(ctx, objectRef, obj); err != nil {
db.logger.Warn("Failed to get object for checking archived status",
zap.Error(err),
mzap.ObjRef("object_ref", objectRef))
return false, err
}
archivable := db.getArchivable(obj)
return archivable.IsArchived(), nil
}
// Archive archives an entity (sets archived to true)
func (db *ArchivableDB[T]) Archive(ctx context.Context, objectRef primitive.ObjectID) error {
return db.SetArchived(ctx, objectRef, true)
}
// Unarchive unarchives an entity (sets archived to false)
func (db *ArchivableDB[T]) Unarchive(ctx context.Context, objectRef primitive.ObjectID) error {
return db.SetArchived(ctx, objectRef, false)
}