Files
drive/apps/backend/internal/virtualfs/hierarchical_key_resolver.go

80 lines
2.2 KiB
Go
Raw Normal View History

2025-11-30 01:16:44 +00:00
package virtualfs
import (
"context"
"fmt"
2025-11-30 01:16:44 +00:00
"github.com/get-drexa/drexa/internal/blob"
"github.com/google/uuid"
2025-11-30 01:16:44 +00:00
"github.com/uptrace/bun"
)
type HierarchicalKeyResolver struct {
db *bun.DB
}
var _ BlobKeyResolver = &HierarchicalKeyResolver{}
func NewHierarchicalKeyResolver(db *bun.DB) *HierarchicalKeyResolver {
return &HierarchicalKeyResolver{db: db}
}
func (r *HierarchicalKeyResolver) ShouldPersistKey() bool {
return false
2025-11-30 01:16:44 +00:00
}
2025-12-02 22:08:50 +00:00
func (r *HierarchicalKeyResolver) Resolve(ctx context.Context, db bun.IDB, node *Node) (blob.Key, error) {
path, err := buildNodeAbsolutePathString(ctx, db, node)
2025-11-30 01:16:44 +00:00
if err != nil {
return "", err
}
2026-01-01 18:29:52 +00:00
return blob.Key(fmt.Sprintf("%s/%s", node.DriveID, path)), nil
2025-11-30 01:16:44 +00:00
}
func (r *HierarchicalKeyResolver) ResolveDeletionKeys(ctx context.Context, node *Node, allKeys []blob.Key) (*DeletionPlan, error) {
path, err := buildNodeAbsolutePathString(ctx, r.db, node)
2025-11-30 01:16:44 +00:00
if err != nil {
return nil, err
}
2026-01-01 18:29:52 +00:00
return &DeletionPlan{Prefix: blob.Key(fmt.Sprintf("%s/%s", node.DriveID, path))}, nil
2025-11-30 01:16:44 +00:00
}
// ResolveBulkMoveOps computes blob move operations for nodes being moved to a new parent.
// This implementation optimizes by computing parent paths only once (2 queries total),
// rather than computing the full path for each node individually (N queries).
func (r *HierarchicalKeyResolver) ResolveBulkMoveOps(ctx context.Context, db bun.IDB, nodes []*Node, newParentID uuid.UUID) ([]BlobMoveOp, error) {
if len(nodes) == 0 {
return nil, nil
}
2026-01-01 18:29:52 +00:00
driveID := nodes[0].DriveID
oldParentID := nodes[0].ParentID
for _, node := range nodes[1:] {
if node.ParentID != oldParentID {
return nil, ErrUnsupportedOperation
}
}
oldParentPath, err := buildPathFromNodeID(ctx, db, oldParentID)
if err != nil {
return nil, err
}
newParentPath, err := buildPathFromNodeID(ctx, db, newParentID)
if err != nil {
return nil, err
}
// For each node, construct old and new keys using the precomputed parent paths
ops := make([]BlobMoveOp, len(nodes))
for i, node := range nodes {
2026-01-01 18:29:52 +00:00
oldKey := blob.Key(fmt.Sprintf("%s/%s/%s", driveID, oldParentPath, node.Name))
newKey := blob.Key(fmt.Sprintf("%s/%s/%s", driveID, newParentPath, node.Name))
ops[i] = BlobMoveOp{Node: node, OldKey: oldKey, NewKey: newKey}
}
return ops, nil
}