Documentation
¶
Overview ¶
Package block_gc implements garbage collection for Hydra block stores.
The ref graph tracks reference edges using a single gc/ref predicate stored in a KVtx store. Nodes that lose all incoming gc/ref edges are marked unreferenced. The Collector sweeps unreferenced nodes, removing their outgoing edges (which may cascade further orphans), calling the onSwept callback, and physically deleting block-backed nodes via the underlying store.
Content-addressed blocks cannot have reference cycles (hash depends on content which includes refs), so reference counting is sufficient.
Index ¶
- Constants
- Variables
- func BlockIRI(ref *block.BlockRef) string
- func BucketFlushTask() string
- func BucketIRI(bucketID string) string
- func IsPermanentRoot(iri string) bool
- func ObjectIRI(key string) string
- func ParseBlockIRI(iri string) (*block.BlockRef, bool)
- func ParseBucketIRI(iri string) (string, bool)
- func RefBatchRemainder(err error) ([]RefEdge, []RefEdge, bool)
- func RegisterEntityChain(ctx context.Context, rg RefGraphOps, nodes ...string) error
- func WorldFlushTask() string
- type AtomicSweepStore
- type Collector
- type CollectorGraph
- type Color
- type GCStoreOps
- func NewGCStoreOps(store block.StoreOps, refGraph RefGraphOps) *GCStoreOps
- func NewGCStoreOpsWithParent(store block.StoreOps, refGraph RefGraphOps, parentIRI string) *GCStoreOps
- func NewGCStoreOpsWithParentAndTraceTask(store block.StoreOps, refGraph RefGraphOps, parentIRI, flushTask string) *GCStoreOps
- func NewGCStoreOpsWithTraceTask(store block.StoreOps, refGraph RefGraphOps, flushTask string) *GCStoreOps
- func (g *GCStoreOps) AddGCRef(ctx context.Context, subject, object string) error
- func (g *GCStoreOps) BeginDeferFlush()
- func (g *GCStoreOps) BeginReadOperation(ctx context.Context) (block.StoreOps, func(), error)
- func (g *GCStoreOps) EndDeferFlush(ctx context.Context) error
- func (g *GCStoreOps) FlushPending(ctx context.Context) error
- func (g *GCStoreOps) GetBlock(ctx context.Context, ref *block.BlockRef) ([]byte, bool, error)
- func (g *GCStoreOps) GetBlockExists(ctx context.Context, ref *block.BlockRef) (bool, error)
- func (g *GCStoreOps) GetBlockExistsBatch(ctx context.Context, refs []*block.BlockRef) ([]bool, error)
- func (g *GCStoreOps) GetHashType() hash.HashType
- func (g *GCStoreOps) GetRefGraph() RefGraphOps
- func (g *GCStoreOps) GetStore() block.StoreOps
- func (g *GCStoreOps) GetStoredBlock(ctx context.Context, ref *block.BlockRef) (*block.StoredBlock, error)
- func (g *GCStoreOps) GetSupportedFeatures() block.StoreFeature
- func (g *GCStoreOps) HasWALAppender() bool
- func (g *GCStoreOps) MarkRootsComplete(ctx context.Context, roots []*block.BlockRef) error
- func (g *GCStoreOps) PinRoot(ctx context.Context, ref *block.BlockRef) (func(), error)
- func (g *GCStoreOps) PutBlock(ctx context.Context, data []byte, opts *block.PutOpts) (*block.BlockRef, bool, error)
- func (g *GCStoreOps) PutBlockBatch(ctx context.Context, entries []*block.PutBatchEntry) error
- func (g *GCStoreOps) ReleaseRoots(ctx context.Context, refs []*block.BlockRef) error
- func (g *GCStoreOps) RemoveGCRef(ctx context.Context, subject, object string) error
- func (g *GCStoreOps) RmBlock(ctx context.Context, ref *block.BlockRef) error
- func (g *GCStoreOps) RootComplete(ctx context.Context, ref *block.BlockRef) (bool, error)
- func (g *GCStoreOps) SetRetainedRoot(ctx context.Context, name string, ref *block.BlockRef) error
- func (g *GCStoreOps) SetWALAppender(wal WALAppender)
- func (g *GCStoreOps) StatBlock(ctx context.Context, ref *block.BlockRef) (*block.BlockStat, error)
- func (g *GCStoreOps) SupportsRootRetention() bool
- func (g *GCStoreOps) Sync(ctx context.Context) (bool, error)
- type Manager
- type ManagerConfig
- type ManagerHooks
- type Marker
- type RefBatchRemainderError
- type RefEdge
- type RefGraph
- func (rg *RefGraph) AddBlockRef(ctx context.Context, source, target *block.BlockRef) error
- func (rg *RefGraph) AddObjectRoot(ctx context.Context, objectKey string, ref *block.BlockRef) error
- func (rg *RefGraph) AddRef(ctx context.Context, subject, object string) error
- func (rg *RefGraph) ApplyRefBatch(ctx context.Context, adds, removes []RefEdge) error
- func (rg *RefGraph) Close() error
- func (rg *RefGraph) GetIncomingRefs(ctx context.Context, node string) ([]string, error)
- func (rg *RefGraph) GetOutgoingRefs(ctx context.Context, node string) ([]string, error)
- func (rg *RefGraph) GetUnreferencedNodes(ctx context.Context) ([]string, error)
- func (rg *RefGraph) HasIncomingRefs(ctx context.Context, node string) (bool, error)
- func (rg *RefGraph) HasIncomingRefsExcluding(ctx context.Context, node string, excluded ...string) (bool, error)
- func (rg *RefGraph) RemoveNodeRefs(ctx context.Context, node string, markOrphaned bool) ([]string, error)
- func (rg *RefGraph) RemoveObjectRoot(ctx context.Context, objectKey string, ref *block.BlockRef) error
- func (rg *RefGraph) RemoveRef(ctx context.Context, subject, object string) error
- type RefGraphOps
- type STWLockFunc
- type Stats
- type SweepConfig
- type SweepResult
- type SweepTarget
- type WALAppender
- type WALReplayFunc
Constants ¶
const ( NodeGCRoot = "gcroot" NodeUnreferenced = "unreferenced" )
Well-known node IRIs (permanent roots).
const PredGCRef = "gc/ref"
PredGCRef is the single predicate for all GC reference edges.
Variables ¶
var ErrAtomicSweepUnsupported = errors.New("atomic sweep unsupported")
ErrAtomicSweepUnsupported rejects a sweep outside the store's atomic ownership domain before graph or block mutation.
Functions ¶
func BucketFlushTask ¶
func BucketFlushTask() string
BucketFlushTask returns the runtime trace task name for bucket-level GC flushes.
func IsPermanentRoot ¶
IsPermanentRoot returns true if the IRI is a well-known permanent root.
func ParseBlockIRI ¶
ParseBlockIRI parses a "block:{b58}" IRI back to a BlockRef. Returns nil, false if not a valid block IRI.
func ParseBucketIRI ¶
ParseBucketIRI parses a "bucket:{id}" IRI back to a bucket ID. Returns the bucket ID and true if valid.
func RefBatchRemainder ¶ added in v0.57.0
RefBatchRemainder returns the uncommitted suffix carried by err.
func RegisterEntityChain ¶
func RegisterEntityChain(ctx context.Context, rg RefGraphOps, nodes ...string) error
RegisterEntityChain registers a chain of gc/ref edges between nodes. Each adjacent pair gets an AddRef call: nodes[0]->nodes[1], nodes[1]->nodes[2], etc. At least 2 nodes required. Idempotent (Cayley ignore_duplicate).
func WorldFlushTask ¶
func WorldFlushTask() string
WorldFlushTask returns the runtime trace task name for world-local GC flushes.
Types ¶
type AtomicSweepStore ¶
type AtomicSweepStore interface {
SweepUnreferenced(ctx context.Context, graph RefGraphOps, nodes []string) ([]string, error)
}
AtomicSweepStore rechecks current ownership and removes still-orphaned nodes and their physical blocks in one transaction, serialized with publication. A candidate snapshot alone never authorizes deletion. The graph argument binds this operation to the collector's reachability scope. It returns the nodes it removed; a failed transaction removes none.
type Collector ¶
type Collector struct {
// contains filtered or unexported fields
}
Collector sweeps unreferenced nodes from the ref graph.
Nodes are marked unreferenced by GCStoreOps when they lose all incoming references. Collect iterates unreferenced nodes and deletes them. Deletion cascades: removing a node may orphan its children, which get marked unreferenced for the next iteration.
func NewCollector ¶
func NewCollector( refGraph RefGraphOps, store block.StoreOps, onSwept func(context.Context, string) error, ) *Collector
NewCollector constructs a new GC collector. The store is the underlying physical store for block deletion. The onSwept callback is optional; if non-nil it is called for each node before physical deletion. Without atomic sweeping, the caller must serialize collection with reference publication for this graph and store.
type CollectorGraph ¶
type CollectorGraph interface {
RefGraphOps
// IterateNodes returns all node IRIs in the node inventory.
IterateNodes(ctx context.Context) ([]string, error)
// GetRootNodes returns all node IRIs in the root set.
GetRootNodes(ctx context.Context) ([]string, error)
// RemoveRoot removes a node from the root set.
RemoveRoot(ctx context.Context, iri string) error
// RemoveNode removes a node from the node inventory.
RemoveNode(ctx context.Context, iri string) error
}
CollectorGraph is the interface required by the marker and sweep for graph traversal. It extends RefGraphOps with node inventory, root set, and cleanup operations.
type GCStoreOps ¶
type GCStoreOps struct {
// contains filtered or unexported fields
}
GCStoreOps wraps a StoreOps with GC ref graph tracking.
PutBlock is called from Transaction.Write's concurrent worker goroutines. Since the RefGraph shares the block cursor's mutex, writing to the RefGraph inside those goroutines would deadlock. Instead, GCStoreOps buffers the operations and they are flushed via FlushPending after Transaction.Write returns.
When parentIRI is set, new blocks are tracked under parentIRI instead of the "unreferenced" staging node. This allows bucket-level ownership of blocks.
func NewGCStoreOps ¶
func NewGCStoreOps(store block.StoreOps, refGraph RefGraphOps) *GCStoreOps
NewGCStoreOps wraps a StoreOps with GC ref graph tracking. New blocks are added under the "unreferenced" staging node.
func NewGCStoreOpsWithParent ¶
func NewGCStoreOpsWithParent(store block.StoreOps, refGraph RefGraphOps, parentIRI string) *GCStoreOps
NewGCStoreOpsWithParent wraps a StoreOps with GC ref graph tracking using a specific parent IRI. New blocks are tracked under parentIRI instead of the "unreferenced" staging node.
func NewGCStoreOpsWithParentAndTraceTask ¶
func NewGCStoreOpsWithParentAndTraceTask(store block.StoreOps, refGraph RefGraphOps, parentIRI, flushTask string) *GCStoreOps
NewGCStoreOpsWithParentAndTraceTask wraps a StoreOps with GC ref graph tracking and a specific runtime trace task name for FlushPending.
func NewGCStoreOpsWithTraceTask ¶
func NewGCStoreOpsWithTraceTask(store block.StoreOps, refGraph RefGraphOps, flushTask string) *GCStoreOps
NewGCStoreOpsWithTraceTask wraps a StoreOps with GC ref graph tracking and a specific runtime trace task name for FlushPending.
func (*GCStoreOps) AddGCRef ¶
func (g *GCStoreOps) AddGCRef(ctx context.Context, subject, object string) error
AddGCRef adds a gc/ref edge from subject to object and removes the unreferenced edge from the object (it now has a real reference).
func (*GCStoreOps) BeginDeferFlush ¶
func (g *GCStoreOps) BeginDeferFlush()
BeginDeferFlush enters a deferred-flush scope. While deferred, FlushPending returns immediately without flushing; pending operations accumulate in the buffer. Supports nesting. Also forwards to the inner store so nested GC layers (e.g. bucket-level gcOps inside bucketHandle) are also deferred.
func (*GCStoreOps) BeginReadOperation ¶ added in v0.51.7
BeginReadOperation opens a read scope on the inner store.
func (*GCStoreOps) EndDeferFlush ¶
func (g *GCStoreOps) EndDeferFlush(ctx context.Context) error
EndDeferFlush exits a deferred-flush scope. When the outermost scope ends, calls FlushPending to flush all accumulated operations in one batch. Also forwards to the inner store.
func (*GCStoreOps) FlushPending ¶
func (g *GCStoreOps) FlushPending(ctx context.Context) error
FlushPending writes all buffered PutBlock operations to the RefGraph, using batched ref graph updates when the implementation supports them. Must be called after Transaction.Write completes and the cursor mutex is no longer held.
When a deferred-flush scope is active (via BeginDeferFlush), returns nil without flushing. The pending operations accumulate and are flushed when EndDeferFlush closes the outermost scope.
func (*GCStoreOps) GetBlockExists ¶
GetBlockExists checks if a block exists.
func (*GCStoreOps) GetBlockExistsBatch ¶
func (g *GCStoreOps) GetBlockExistsBatch(ctx context.Context, refs []*block.BlockRef) ([]bool, error)
GetBlockExistsBatch checks whether each block exists.
func (*GCStoreOps) GetHashType ¶
func (g *GCStoreOps) GetHashType() hash.HashType
GetHashType returns the preferred hash type for the store.
func (*GCStoreOps) GetRefGraph ¶
func (g *GCStoreOps) GetRefGraph() RefGraphOps
GetRefGraph returns the underlying ref graph.
func (*GCStoreOps) GetStore ¶
func (g *GCStoreOps) GetStore() block.StoreOps
GetStore returns the underlying store.
func (*GCStoreOps) GetStoredBlock ¶
func (g *GCStoreOps) GetStoredBlock(ctx context.Context, ref *block.BlockRef) (*block.StoredBlock, error)
GetStoredBlock reads a block and its outgoing block edges. The edges come from the ref graph, the journal edges it has not applied, and the edges this store has buffered but not flushed. Blocks are immutable, so an edge once recorded stays valid for the life of the block.
func (*GCStoreOps) GetSupportedFeatures ¶
func (g *GCStoreOps) GetSupportedFeatures() block.StoreFeature
GetSupportedFeatures returns the native feature bitmask for the store.
func (*GCStoreOps) HasWALAppender ¶ added in v0.51.7
func (g *GCStoreOps) HasWALAppender() bool
HasWALAppender returns whether this GC store writes flushes to a WAL.
func (*GCStoreOps) MarkRootsComplete ¶
MarkRootsComplete forwards the durable World proof.
func (*GCStoreOps) PutBlock ¶
func (g *GCStoreOps) PutBlock(ctx context.Context, data []byte, opts *block.PutOpts) (*block.BlockRef, bool, error)
PutBlock puts a block into the store and buffers a gc/ref edge for later flush. A parent owns every non-empty block it writes. Without a parent, only new blocks are staged under unreferenced.
func (*GCStoreOps) PutBlockBatch ¶
func (g *GCStoreOps) PutBlockBatch(ctx context.Context, entries []*block.PutBatchEntry) error
PutBlockBatch writes a batch of blocks through the inner store and buffers GC ref edges for all non-tombstone blocks. The inner store decides whether the batch flows through a native path or an internal fallback.
Tombstone entries release parent ownership through GCStoreOps.RmBlock. The collector owns outgoing edges and physical deletion. Existing entries skip unreferenced staging; a configured parent owns every block it writes.
func (*GCStoreOps) ReleaseRoots ¶
ReleaseRoots forwards staging release to the underlying store.
func (*GCStoreOps) RemoveGCRef ¶
func (g *GCStoreOps) RemoveGCRef(ctx context.Context, subject, object string) error
RemoveGCRef removes a gc/ref edge from subject to object and marks the object as orphaned if it has no remaining incoming references.
func (*GCStoreOps) RmBlock ¶
RmBlock buffers release of this store's parent ownership. Outgoing edges belong to the immutable block and remain until the collector sweeps it. FlushPending delivers the release. An unparented store owns no reference to release; its staging mark remains.
func (*GCStoreOps) RootComplete ¶
RootComplete checks the underlying World proof.
func (*GCStoreOps) SetRetainedRoot ¶
SetRetainedRoot forwards durable root ownership to the underlying store.
func (*GCStoreOps) SetWALAppender ¶
func (g *GCStoreOps) SetWALAppender(wal WALAppender)
SetWALAppender sets the WAL appender for deferred ref graph updates. When set, FlushPending writes to the WAL instead of calling ApplyRefBatch on the RefGraph directly. Configure it before concurrent use.
func (*GCStoreOps) StatBlock ¶
StatBlock returns metadata about a block without reading its data. Returns nil, nil if the block does not exist.
func (*GCStoreOps) SupportsRootRetention ¶
func (g *GCStoreOps) SupportsRootRetention() bool
SupportsRootRetention reports the underlying ownership capability.
func (*GCStoreOps) Sync ¶ added in v0.52.0
func (g *GCStoreOps) Sync(ctx context.Context) (bool, error)
Sync forwards the durability barrier to the inner store. Applying buffered ref-graph edges stays an explicit FlushPending call, not a Sync side effect, because FlushPending must run with the cursor mutex released.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager owns the GC graph store and sweep executor lifecycle. It runs startup WAL replay and periodic sweep cycles.
func NewManager ¶
func NewManager(cfg ManagerConfig) *Manager
NewManager creates a GC manager with the given configuration.
type ManagerConfig ¶
type ManagerConfig struct {
SweepConfig
// SweepInterval is the periodic sweep interval. Default 30s.
SweepInterval time.Duration
// Maintenance runs after a successful sweep cycle, inside the same
// maintenance lifecycle.
Maintenance func(context.Context) error
}
ManagerConfig holds the configuration for a GC manager.
type ManagerHooks ¶
type ManagerHooks struct {
Graph CollectorGraph
ReplayWAL WALReplayFunc
AcquireSTW STWLockFunc
Maintenance func(context.Context) error
}
ManagerHooks are the GC manager dependencies supplied by a storage backend. The controller/runtime provides the sweep target and interval.
type Marker ¶
type Marker struct {
// contains filtered or unexported fields
}
Marker performs an in-memory tri-color mark traversal over a CollectorGraph.
func NewMarker ¶
func NewMarker(graph CollectorGraph) *Marker
NewMarker creates a Marker for the given graph backend.
func (*Marker) Mark ¶
func (m *Marker) Mark(ctx context.Context) (sweepCandidates []string, colors map[string]Color, err error)
Mark runs the tri-color mark phase and returns the set of white (unreachable) nodes as sweep candidates. The colors map contains the final state of all nodes for inspection.
type RefBatchRemainderError ¶ added in v0.57.0
RefBatchRemainderError reports the uncommitted suffix of an ownership transition. The slices retain their original add-before-remove order.
type RefEdge ¶
type RefEdge struct {
Subject, Object string
}
RefEdge is a subject -> object edge in the GC ref graph.
type RefGraph ¶
type RefGraph struct {
// contains filtered or unexported fields
}
RefGraph is a unified reference graph for garbage collection backed by Cayley. The durable graph is the only representation of the edge set. Membership and owner queries read the store's own indexes, so opening a RefGraph costs nothing proportional to how many edges it holds and neither does keeping one open.
func NewRefGraph ¶
NewRefGraph constructs a RefGraph backed by the given kvtx store. prefix is prepended to all keys (e.g., "gc/" for space context).
func (*RefGraph) AddBlockRef ¶
AddBlockRef adds gc/ref from source block to target block.
func (*RefGraph) AddObjectRoot ¶
AddObjectRoot adds gc/ref from object:{key} to block.
func (*RefGraph) ApplyRefBatch ¶
ApplyRefBatch serializes one bounded ownership transition under writeMu. It applies additions before removals, treats missing exact removals as no-ops, and derives orphan marks from the resulting owner set. Preparation and application are bounded together so each slice commits before preparation of the next slice begins.
func (*RefGraph) GetIncomingRefs ¶
GetIncomingRefs returns all sources that have gc/ref edges pointing to the given node.
func (*RefGraph) GetOutgoingRefs ¶
GetOutgoingRefs returns all targets of gc/ref edges from the given node.
func (*RefGraph) GetUnreferencedNodes ¶
GetUnreferencedNodes returns all nodes that have a gc/ref from "unreferenced".
func (*RefGraph) HasIncomingRefs ¶
HasIncomingRefs checks if a node has any incoming gc/ref edges. Excludes edges from "unreferenced" (those don't count as real refs).
func (*RefGraph) HasIncomingRefsExcluding ¶
func (rg *RefGraph) HasIncomingRefsExcluding( ctx context.Context, node string, excluded ...string, ) (bool, error)
HasIncomingRefsExcluding checks if a node has any incoming gc/ref edges. Excludes edges from "unreferenced" and the specified source nodes.
func (*RefGraph) RemoveNodeRefs ¶
func (rg *RefGraph) RemoveNodeRefs(ctx context.Context, node string, markOrphaned bool) ([]string, error)
RemoveNodeRefs removes ALL outgoing gc/ref edges for a node. Returns the list of target IRIs that lost an incoming edge. If markOrphaned is true, targets that have no remaining incoming refs (excluding from "unreferenced") get an unreferenced edge.
type RefGraphOps ¶
type RefGraphOps interface {
// AddRef adds a gc/ref edge from subject to object. Idempotent.
AddRef(ctx context.Context, subject, object string) error
// RemoveRef removes a single gc/ref edge from subject to object.
RemoveRef(ctx context.Context, subject, object string) error
// ApplyRefBatch serializes one bounded ownership transition. Every
// addition is applied before any removal; an exact removal whose edge is
// absent is a no-op. If orphan marking is enabled by the implementation,
// it is derived from the owner set after this transition. Implementations
// may return a wrapped remainder error when only a prefix was committed.
ApplyRefBatch(ctx context.Context, adds, removes []RefEdge) error
// RemoveNodeRefs removes all outgoing gc/ref edges for a node.
// Returns the list of target IRIs that lost an incoming edge.
// If markOrphaned is true, targets with no remaining incoming
// refs get an unreferenced edge.
RemoveNodeRefs(ctx context.Context, node string, markOrphaned bool) ([]string, error)
// HasIncomingRefs checks if a node has any incoming gc/ref edges.
// Excludes edges from "unreferenced".
HasIncomingRefs(ctx context.Context, node string) (bool, error)
// HasIncomingRefsExcluding checks if a node has any incoming gc/ref edges
// excluding edges from "unreferenced" and the specified source nodes.
HasIncomingRefsExcluding(ctx context.Context, node string, excluded ...string) (bool, error)
// GetOutgoingRefs returns all targets of gc/ref edges from a node.
GetOutgoingRefs(ctx context.Context, node string) ([]string, error)
// GetIncomingRefs returns all sources with gc/ref edges to a node.
GetIncomingRefs(ctx context.Context, node string) ([]string, error)
// GetUnreferencedNodes returns all nodes linked from "unreferenced".
GetUnreferencedNodes(ctx context.Context) ([]string, error)
// AddBlockRef adds gc/ref from source block to target block.
AddBlockRef(ctx context.Context, source, target *block.BlockRef) error
// AddObjectRoot adds gc/ref from object:{key} to block.
AddObjectRoot(ctx context.Context, objectKey string, ref *block.BlockRef) error
// RemoveObjectRoot removes gc/ref from object:{key} to block.
RemoveObjectRoot(ctx context.Context, objectKey string, ref *block.BlockRef) error
// Close closes the ref graph.
Close() error
}
RefGraphOps is the interface for GC reference graph ownership transitions.
type STWLockFunc ¶
type STWLockFunc func() (release func(), err error)
STWLockFunc acquires the STW lock in exclusive mode and returns a release function.
type Stats ¶
type Stats struct {
// AtomicSweepCount and AtomicSweepDuration include atomic ownership rechecks.
AtomicSweepCount int
AtomicSweepDuration time.Duration
// NodesSwept is the number of nodes swept.
NodesSwept int
// UnreferencedNodeCount is the number of unreferenced node entries read.
UnreferencedNodeCount int
// RemoveNodeRefsCount is the number of nodes whose outgoing refs were removed.
RemoveNodeRefsCount int
// RemoveUnreferencedEdgeCount is the number of unreferenced marker edges removed.
RemoveUnreferencedEdgeCount int
// OnSweptCount is the number of onSwept callbacks run.
OnSweptCount int
// RemoveBlockCount is the number of physical block deletes attempted.
RemoveBlockCount int
// Duration is how long the GC cycle took.
Duration time.Duration
// UnreferencedScanDuration is time spent listing unreferenced nodes.
UnreferencedScanDuration time.Duration
// RemoveNodeRefsDuration is time spent removing outgoing node refs.
RemoveNodeRefsDuration time.Duration
// RemoveUnreferencedEdgeDuration is time spent removing unreferenced markers.
RemoveUnreferencedEdgeDuration time.Duration
// OnSweptDuration is time spent in onSwept callbacks.
OnSweptDuration time.Duration
// RemoveBlockDuration is time spent physically deleting block-backed nodes.
RemoveBlockDuration time.Duration
}
Stats holds GC cycle statistics.
type SweepConfig ¶
type SweepConfig struct {
Graph CollectorGraph
Target SweepTarget
ReplayWAL WALReplayFunc
AcquireSTW STWLockFunc
}
SweepConfig holds the dependencies for a sweep cycle.
type SweepResult ¶
type SweepResult struct {
WALEntriesPhase1 int
WALEntriesPhase2 int
SweepCandidates int
Rescued int
Swept int
}
SweepResult holds statistics from a completed sweep cycle.
func SweepCycle ¶
func SweepCycle(ctx context.Context, cfg SweepConfig) (*SweepResult, error)
SweepCycle runs the full two-phase GC sweep protocol.
Phase 1 (no lock): replay WAL entries into the graph, then run the tri-color marker to get sweep candidates.
Phase 2 (exclusive STW lock): process remaining WAL entries with transitive rescue, then delete sweep candidates from the backend.
type SweepTarget ¶
type SweepTarget interface {
// DeleteBlock deletes a block from the block store by its IRI.
DeleteBlock(ctx context.Context, iri string) error
// DeleteObject deletes an object key from the object store by its IRI.
DeleteObject(ctx context.Context, iri string) error
}
SweepTarget provides backend-specific deletion for swept nodes.
type WALAppender ¶
type WALAppender interface {
// Append durably journals one batch of edge additions and removals.
Append(ctx context.Context, adds, removes []RefEdge) error
// GetPendingOutgoingRefs returns the targets of journaled edges from node
// that the ref graph has not applied yet, net of journaled removals.
GetPendingOutgoingRefs(ctx context.Context, node string) ([]string, error)
}
WALAppender appends batched ref graph edge operations to a write-ahead log. When set on GCStoreOps, FlushPending writes to the WAL instead of calling ApplyRefBatch on the RefGraph directly.
type WALReplayFunc ¶
type WALReplayFunc func(ctx context.Context, graph CollectorGraph) (int, error)
WALReplayFunc reads and applies WAL entries to the graph, returning the count of entries processed. Entries should be deleted eagerly after apply.