persistence

package
v0.1.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 19, 2026 License: GPL-3.0 Imports: 18 Imported by: 0

Documentation

Index

Constants

View Source
const (
	KindBeaconState              = "beacon_state"
	KindBeaconBlock              = "beacon_block"
	KindExecutionPayloadEnvelope = "execution_payload_envelope"
	KindBeaconBadBlock           = "beacon_bad_block"
	KindBeaconBadBlob            = "beacon_bad_blob"
	KindExecutionBlockTrace      = "execution_block_trace"
	KindExecutionBadBlock        = "execution_bad_block"
)

Artifact kinds. The vocabulary is the store's data-type vocabulary verbatim so that a kind read out of a blob row can be handed straight to the store without translation.

View Source
const (
	// BlobStateReady marks a blob whose object is present and may be linked.
	BlobStateReady = "ready"
	// BlobStateDeleting marks a blob that has been tombstoned for collection. It must
	// never be linked, and its object may already be gone.
	BlobStateDeleting = "deleting"
)
View Source
const (
	KeyNode                    = "node"
	KeyBlockRoot               = "block_root"
	KeyBlockHash               = "block_hash"
	KeyBlockNumber             = "block_number"
	KeyExecutionImplementation = "execution_implementation"
	KeyNetwork                 = "network"
	KeySlot                    = "slot"
	KeyEpoch                   = "epoch"
	KeyStateRoot               = "state_root"
	KeyContentEncoding         = "content_encoding"
	KeyNodeVersion             = "node_version"
	KeyLocation                = "location"
	KeyFetchedAt               = "fetched_at"
	KeyBeaconImplementation    = "beacon_implementation"
	KeyIndex                   = "index"
	KeyBlockExtraData          = "block_extra_data"
)
View Source
const (
	// DefaultPageLimit is used when a caller supplies no limit of its own.
	DefaultPageLimit = 100
	// MaxPageLimit is the hard ceiling on rows a single list query may return. Retention
	// asks for exactly this many, so it must not be lowered without changing that caller.
	MaxPageLimit = 10000
)

Variables

View Source
var ErrBlobNotFound = errors.New("blob not found")

ErrBlobNotFound is returned when no linkable blob exists for a dedupe key. A tombstoned blob is reported as not found: it cannot be linked and the caller must re-upload.

View Source
var ErrPermanentBlockNotFound = errors.New("permanent block not found")

ErrPermanentBlockNotFound is returned when no row records the artifact. It is an ordinary answer on the archive path - almost every artifact is new - so callers must be able to tell it apart from a database failure.

Functions

func DedupKeyFor added in v0.1.0

func DedupKeyFor(kind string, row *ExpiringArtifact) string

DedupKeyFor builds the dedupe key for the kinds whose key is derivable from the row itself. Execution block traces are not: their key carries the agent's trace parameters, which are deliberately not columns on the artifact table, so their blob is resolved by content hash instead.

Types

type ArtifactInsertOutcome added in v0.1.0

type ArtifactInsertOutcome int

ArtifactInsertOutcome is what an insert did, which decides both the RPC status and whether the caller still owes the store a HEAD request.

const (
	// ArtifactInsertDuplicate means the unique index already held an identical observation.
	ArtifactInsertDuplicate ArtifactInsertOutcome = iota
	// ArtifactInsertLinked means the row was inserted and took a reference on a ready blob.
	ArtifactInsertLinked
	// ArtifactInsertUnlinked means the row was inserted and owns its object outright: a
	// bad_* kind, or a divergent copy stored beside the canonical blob.
	ArtifactInsertUnlinked
	// ArtifactInsertUnlinkable means the row claimed a payload that is not linkable — no blob
	// for the dedupe key, or one that is already being collected. Nothing was inserted.
	ArtifactInsertUnlinkable
)

type BasicMetrics

type BasicMetrics struct {
	// contains filtered or unexported fields
}

func NewBasicMetrics

func NewBasicMetrics(namespace, driverName string, enabled bool) *BasicMetrics

func (*BasicMetrics) ObserveOperation

func (m *BasicMetrics) ObserveOperation(operation Operation)

func (*BasicMetrics) ObserveOperationError

func (m *BasicMetrics) ObserveOperationError(operation Operation)

type BeaconBadBlob added in v0.0.16

type BeaconBadBlob struct {
	ID   string `gorm:"primaryKey"`
	Node string `` /* 137-byte string literal not displayed */
	// We have to use int64 here as SQLite doesn't support uint64. This sucks
	// but slot 9223372036854775808 is probably around the heat death
	// of the universe so we should be OK.
	Slot                 int64     `gorm:"not null;default:0;uniqueIndex:ux_beacon_bad_blobs_dedupe,priority:2"`
	Epoch                int64     `gorm:"not null;default:0"`
	BlockRoot            string    `gorm:"not null;default:'';uniqueIndex:ux_beacon_bad_blobs_dedupe,priority:3"`
	FetchedAt            time.Time `` /* 169-byte string literal not displayed */
	BeaconImplementation string    `gorm:"not null;default:''"`
	NodeVersion          string    `gorm:"not null;default:''"`
	ContentEncoding      string    `gorm:"not null;default:''"`
	Location             string    `gorm:"not null;default:''"`
	ContentHash          string    `gorm:"not null;default:'';size:64"`
	// VerifiedAt is set when these bytes were read and hashed from this node.
	VerifiedAt *time.Time
	// ContentMatchedAt is set when the hash was compared against an existing
	// payload and matched. Bad blobs are never linked, so it stays null.
	ContentMatchedAt *time.Time
	Network          string `` /* 193-byte string literal not displayed */
	Index            int64  `gorm:"not null;default:0;uniqueIndex:ux_beacon_bad_blobs_dedupe,priority:4"`
}

func (*BeaconBadBlob) BeforeSave added in v0.1.0

func (a *BeaconBadBlob) BeforeSave(*gorm.DB) error

BeforeSave keeps every stored timestamp in UTC. The drivers render a time.Time in the zone the value itself carries, so a row written by a process in another zone would neither order nor compare against the rest of the table.

type BeaconBadBlobFilter added in v0.0.16

type BeaconBadBlobFilter struct {
	ID                   *string
	Node                 *string
	Before               *time.Time
	After                *time.Time
	Slot                 *uint64
	Epoch                *uint64
	BlockRoot            *string
	NodeVersion          *string
	Location             *string
	Network              *string
	BeaconImplementation *string
	Index                *uint64
}

func (*BeaconBadBlobFilter) AddAfter added in v0.0.16

func (f *BeaconBadBlobFilter) AddAfter(after time.Time)

func (*BeaconBadBlobFilter) AddBeaconImplementation added in v0.0.16

func (f *BeaconBadBlobFilter) AddBeaconImplementation(beaconImplementation string)

func (*BeaconBadBlobFilter) AddBefore added in v0.0.16

func (f *BeaconBadBlobFilter) AddBefore(before time.Time)

func (*BeaconBadBlobFilter) AddBlockRoot added in v0.0.16

func (f *BeaconBadBlobFilter) AddBlockRoot(blockRoot string)

func (*BeaconBadBlobFilter) AddEpoch added in v0.0.16

func (f *BeaconBadBlobFilter) AddEpoch(epoch uint64)

func (*BeaconBadBlobFilter) AddID added in v0.0.16

func (f *BeaconBadBlobFilter) AddID(id string)

func (*BeaconBadBlobFilter) AddIndex added in v0.0.16

func (f *BeaconBadBlobFilter) AddIndex(index uint64)

func (*BeaconBadBlobFilter) AddLocation added in v0.0.16

func (f *BeaconBadBlobFilter) AddLocation(location string)

func (*BeaconBadBlobFilter) AddNetwork added in v0.0.16

func (f *BeaconBadBlobFilter) AddNetwork(network string)

func (*BeaconBadBlobFilter) AddNode added in v0.0.16

func (f *BeaconBadBlobFilter) AddNode(node string)

func (*BeaconBadBlobFilter) AddNodeVersion added in v0.0.16

func (f *BeaconBadBlobFilter) AddNodeVersion(nodeVersion string)

func (*BeaconBadBlobFilter) AddSlot added in v0.0.16

func (f *BeaconBadBlobFilter) AddSlot(slot uint64)

func (*BeaconBadBlobFilter) ApplyToQuery added in v0.0.16

func (f *BeaconBadBlobFilter) ApplyToQuery(query *gorm.DB) (*gorm.DB, error)

type BeaconBadBlock added in v0.0.16

type BeaconBadBlock struct {
	ID   string `gorm:"primaryKey"`
	Node string `` /* 139-byte string literal not displayed */
	// We have to use int64 here as SQLite doesn't support uint64. This sucks
	// but slot 9223372036854775808 is probably around the heat death
	// of the universe so we should be OK.
	Slot                 int64     `gorm:"not null;default:0;uniqueIndex:ux_beacon_bad_blocks_dedupe,priority:2"`
	Epoch                int64     `gorm:"not null;default:0"`
	BlockRoot            string    `gorm:"not null;default:'';uniqueIndex:ux_beacon_bad_blocks_dedupe,priority:3"`
	FetchedAt            time.Time `` /* 172-byte string literal not displayed */
	BeaconImplementation string    `gorm:"not null;default:''"`
	NodeVersion          string    `gorm:"not null;default:''"`
	ContentEncoding      string    `gorm:"not null;default:''"`
	Location             string    `gorm:"not null;default:''"`
	ContentHash          string    `gorm:"not null;default:'';size:64"`
	// VerifiedAt is set when these bytes were read and hashed from this node.
	VerifiedAt *time.Time
	// ContentMatchedAt is set when the hash was compared against an existing
	// payload and matched. Bad blocks are never linked, so it stays null.
	ContentMatchedAt *time.Time
	Network          string `` /* 196-byte string literal not displayed */
}

func (*BeaconBadBlock) BeforeSave added in v0.1.0

func (a *BeaconBadBlock) BeforeSave(*gorm.DB) error

BeforeSave keeps every stored timestamp in UTC. The drivers render a time.Time in the zone the value itself carries, so a row written by a process in another zone would neither order nor compare against the rest of the table.

type BeaconBadBlockFilter added in v0.0.16

type BeaconBadBlockFilter struct {
	ID                   *string
	Node                 *string
	Before               *time.Time
	After                *time.Time
	Slot                 *uint64
	Epoch                *uint64
	BlockRoot            *string
	NodeVersion          *string
	Location             *string
	Network              *string
	BeaconImplementation *string
}

func (*BeaconBadBlockFilter) AddAfter added in v0.0.16

func (f *BeaconBadBlockFilter) AddAfter(after time.Time)

func (*BeaconBadBlockFilter) AddBeaconImplementation added in v0.0.16

func (f *BeaconBadBlockFilter) AddBeaconImplementation(beaconImplementation string)

func (*BeaconBadBlockFilter) AddBefore added in v0.0.16

func (f *BeaconBadBlockFilter) AddBefore(before time.Time)

func (*BeaconBadBlockFilter) AddBlockRoot added in v0.0.16

func (f *BeaconBadBlockFilter) AddBlockRoot(blockRoot string)

func (*BeaconBadBlockFilter) AddEpoch added in v0.0.16

func (f *BeaconBadBlockFilter) AddEpoch(epoch uint64)

func (*BeaconBadBlockFilter) AddID added in v0.0.16

func (f *BeaconBadBlockFilter) AddID(id string)

func (*BeaconBadBlockFilter) AddLocation added in v0.0.16

func (f *BeaconBadBlockFilter) AddLocation(location string)

func (*BeaconBadBlockFilter) AddNetwork added in v0.0.16

func (f *BeaconBadBlockFilter) AddNetwork(network string)

func (*BeaconBadBlockFilter) AddNode added in v0.0.16

func (f *BeaconBadBlockFilter) AddNode(node string)

func (*BeaconBadBlockFilter) AddNodeVersion added in v0.0.16

func (f *BeaconBadBlockFilter) AddNodeVersion(nodeVersion string)

func (*BeaconBadBlockFilter) AddSlot added in v0.0.16

func (f *BeaconBadBlockFilter) AddSlot(slot uint64)

func (*BeaconBadBlockFilter) ApplyToQuery added in v0.0.16

func (f *BeaconBadBlockFilter) ApplyToQuery(query *gorm.DB) (*gorm.DB, error)

type BeaconBlock added in v0.0.16

type BeaconBlock struct {
	ID   string `gorm:"primaryKey"`
	Node string `` /* 131-byte string literal not displayed */
	// We have to use int64 here as SQLite doesn't support uint64. This sucks
	// but slot 9223372036854775808 is probably around the heat death
	// of the universe so we should be OK.
	Slot int64 `gorm:"not null;default:0;uniqueIndex:ux_beacon_blocks_dedupe,priority:2"`
	// The promotion service walks the index one (network, epoch) at a time,
	// so this pair is indexed; an unindexed epoch turns each of those
	// listings into a full table scan.
	Epoch                int64     `gorm:"not null;default:0;index:ix_beacon_blocks_network_epoch,priority:2"`
	BlockRoot            string    `gorm:"not null;default:'';uniqueIndex:ux_beacon_blocks_dedupe,priority:3"`
	FetchedAt            time.Time `` /* 160-byte string literal not displayed */
	BeaconImplementation string    `gorm:"not null;default:''"`
	NodeVersion          string    `gorm:"not null;default:''"`
	ContentEncoding      string    `gorm:"not null;default:''"`
	Location             string    `gorm:"not null;default:''"`
	ContentHash          string    `gorm:"not null;default:'';size:64"`
	// VerifiedAt is set when these bytes were read and hashed from this node.
	VerifiedAt *time.Time
	// ContentMatchedAt is set when the hash was compared against an existing
	// payload and matched.
	ContentMatchedAt *time.Time
	Network          string `` /* 232-byte string literal not displayed */
}

func (*BeaconBlock) BeforeSave added in v0.1.0

func (a *BeaconBlock) BeforeSave(*gorm.DB) error

BeforeSave keeps every stored timestamp in UTC. The drivers render a time.Time in the zone the value itself carries, so a row written by a process in another zone would neither order nor compare against the rest of the table.

type BeaconBlockFilter added in v0.0.16

type BeaconBlockFilter struct {
	ID                   *string
	Node                 *string
	Before               *time.Time
	After                *time.Time
	Slot                 *uint64
	Epoch                *uint64
	BlockRoot            *string
	NodeVersion          *string
	Location             *string
	Network              *string
	BeaconImplementation *string
}

func (*BeaconBlockFilter) AddAfter added in v0.0.16

func (f *BeaconBlockFilter) AddAfter(after time.Time)

func (*BeaconBlockFilter) AddBeaconImplementation added in v0.0.16

func (f *BeaconBlockFilter) AddBeaconImplementation(beaconImplementation string)

func (*BeaconBlockFilter) AddBefore added in v0.0.16

func (f *BeaconBlockFilter) AddBefore(before time.Time)

func (*BeaconBlockFilter) AddBlockRoot added in v0.0.16

func (f *BeaconBlockFilter) AddBlockRoot(blockRoot string)

func (*BeaconBlockFilter) AddEpoch added in v0.0.16

func (f *BeaconBlockFilter) AddEpoch(epoch uint64)

func (*BeaconBlockFilter) AddID added in v0.0.16

func (f *BeaconBlockFilter) AddID(id string)

func (*BeaconBlockFilter) AddLocation added in v0.0.16

func (f *BeaconBlockFilter) AddLocation(location string)

func (*BeaconBlockFilter) AddNetwork added in v0.0.16

func (f *BeaconBlockFilter) AddNetwork(network string)

func (*BeaconBlockFilter) AddNode added in v0.0.16

func (f *BeaconBlockFilter) AddNode(node string)

func (*BeaconBlockFilter) AddNodeVersion added in v0.0.16

func (f *BeaconBlockFilter) AddNodeVersion(nodeVersion string)

func (*BeaconBlockFilter) AddSlot added in v0.0.16

func (f *BeaconBlockFilter) AddSlot(slot uint64)

func (*BeaconBlockFilter) ApplyToQuery added in v0.0.16

func (f *BeaconBlockFilter) ApplyToQuery(query *gorm.DB) (*gorm.DB, error)

type BeaconState

type BeaconState struct {
	ID   string `gorm:"primaryKey"`
	Node string `` /* 131-byte string literal not displayed */
	// We have to use int64 here as SQLite doesn't support uint64. This sucks
	// but slot 9223372036854775808 is probably around the heat death
	// of the universe so we should be OK.
	Slot                 int64     `gorm:"not null;default:0;uniqueIndex:ux_beacon_states_dedupe,priority:2"`
	Epoch                int64     `gorm:"not null;default:0"`
	StateRoot            string    `gorm:"not null;default:'';uniqueIndex:ux_beacon_states_dedupe,priority:3"`
	FetchedAt            time.Time `` /* 160-byte string literal not displayed */
	BeaconImplementation string    `gorm:"not null;default:''"`
	NodeVersion          string    `gorm:"not null;default:''"`
	ContentEncoding      string    `gorm:"not null;default:''"`
	Location             string    `gorm:"not null;default:''"`
	ContentHash          string    `gorm:"not null;default:'';size:64"`
	// VerifiedAt is set when these bytes were read and hashed from this node.
	VerifiedAt *time.Time
	// ContentMatchedAt is set when the hash was compared against an existing
	// payload and matched.
	ContentMatchedAt *time.Time
	Network          string `` /* 184-byte string literal not displayed */
}

func (*BeaconState) BeforeSave added in v0.1.0

func (a *BeaconState) BeforeSave(*gorm.DB) error

BeforeSave keeps every stored timestamp in UTC. The drivers render a time.Time in the zone the value itself carries, so a row written by a process in another zone would neither order nor compare against the rest of the table.

type BeaconStateFilter

type BeaconStateFilter struct {
	ID                   *string
	Node                 *string
	Before               *time.Time
	After                *time.Time
	Slot                 *uint64
	Epoch                *uint64
	StateRoot            *string
	NodeVersion          *string
	Location             *string
	Network              *string
	BeaconImplementation *string
}

func (*BeaconStateFilter) AddAfter

func (f *BeaconStateFilter) AddAfter(after time.Time)

func (*BeaconStateFilter) AddBeaconImplementation

func (f *BeaconStateFilter) AddBeaconImplementation(beaconImplementation string)

func (*BeaconStateFilter) AddBefore

func (f *BeaconStateFilter) AddBefore(before time.Time)

func (*BeaconStateFilter) AddEpoch

func (f *BeaconStateFilter) AddEpoch(epoch uint64)

func (*BeaconStateFilter) AddID

func (f *BeaconStateFilter) AddID(id string)

func (*BeaconStateFilter) AddLocation

func (f *BeaconStateFilter) AddLocation(location string)

func (*BeaconStateFilter) AddNetwork

func (f *BeaconStateFilter) AddNetwork(network string)

func (*BeaconStateFilter) AddNode

func (f *BeaconStateFilter) AddNode(node string)

func (*BeaconStateFilter) AddNodeVersion

func (f *BeaconStateFilter) AddNodeVersion(nodeVersion string)

func (*BeaconStateFilter) AddSlot

func (f *BeaconStateFilter) AddSlot(slot uint64)

func (*BeaconStateFilter) AddStateRoot

func (f *BeaconStateFilter) AddStateRoot(stateRoot string)

func (*BeaconStateFilter) ApplyToQuery

func (f *BeaconStateFilter) ApplyToQuery(query *gorm.DB) (*gorm.DB, error)

type Blob added in v0.1.0

type Blob struct {
	// The content-hash index carries kind and network ahead of the hash: retention resolves a
	// trace's payload by hash within a (kind, network), and neither planner can combine those
	// equalities with a hash-only index, so a narrower one degrades to a full scan.
	Kind     string `gorm:"primaryKey;size:32;index:ix_blobs_kind_network_content_hash,priority:1"`
	Network  string `gorm:"primaryKey;index:ix_blobs_kind_network_content_hash,priority:2"`
	DedupKey string `gorm:"primaryKey"`

	ContentHash     string `gorm:"not null;default:'';size:64;index:ix_blobs_kind_network_content_hash,priority:3"`
	Location        string `gorm:"not null;default:''"`
	ContentEncoding string `gorm:"not null;default:''"`
	RawSize         int64  `gorm:"not null;default:0"`
	CompressedSize  int64  `gorm:"not null;default:0"`
	RefCount        int64  `gorm:"not null;default:0"`

	// State is the tombstone marker and Generation the resurrect counter: a blob that
	// re-enters use while a delete is pending gets a new generation so the pending delete
	// cannot claim the fresh object.
	State      string `gorm:"not null;default:'ready';size:16;index:ix_blobs_state_created_at,priority:1"`
	Generation int64  `gorm:"not null;default:0"`

	CreatedAt time.Time `gorm:"not null;index:ix_blobs_state_created_at,priority:2"`
}

Blob is the deduplicated payload. Keyed on what the lookup actually asks for: the dedup key is known before the fetch, the content hash is not.

func (*Blob) BeforeSave added in v0.1.0

func (b *Blob) BeforeSave(*gorm.DB) error

BeforeSave keeps created_at in UTC, which is what the collector's grace-period cutoff is compared against.

type BlobCandidate added in v0.1.0

type BlobCandidate struct {
	Kind       string
	Network    string
	DedupKey   string
	Location   string
	Generation int64
	State      string
}

BlobCandidate is a blob that looks collectable: no references, old enough that no agent can still be mid-upload against it. State distinguishes a blob that still needs tombstoning from one tombstoned on an earlier pass whose object delete failed and is owed another attempt.

type BlobLink struct {
	DedupKey string
	Location string
}

BlobLink is the linkage evidence for one artifact row: which blob it belongs to and where that blob's object actually lives.

type BlobRefDecrement added in v0.1.0

type BlobRefDecrement struct {
	Kind     string
	Network  string
	DedupKey string
	Count    int64
}

BlobRefDecrement is a reference release: one blob, and how many of its referencing rows are going away in this batch.

type BlobTombstoneOutcome added in v0.1.0

type BlobTombstoneOutcome int

BlobTombstoneOutcome is what the tombstone attempt decided.

const (
	// BlobTombstoneMarked means the blob is now in the deleting state and its object is the
	// caller's to remove.
	BlobTombstoneMarked BlobTombstoneOutcome = iota
	// BlobTombstoneReferenced means artifact rows still reference the blob. The counter had
	// drifted and has been repaired from the rows themselves.
	BlobTombstoneReferenced
	// BlobTombstoneRaced means the blob changed under the candidate scan — resurrected,
	// already tombstoned, or referenced again — and must be left alone this pass.
	BlobTombstoneRaced
)

type Config

type Config struct {
	DSN        string `yaml:"dsn"`
	DriverName string `yaml:"driver_name"`
}

func (*Config) Validate

func (c *Config) Validate() error

type DistinctBeaconBadBlobValueResults added in v0.0.16

type DistinctBeaconBadBlobValueResults struct {
	Node                 []string
	Slot                 []uint64
	Epoch                []uint64
	BlockRoot            []string
	NodeVersion          []string
	Location             []string
	Network              []string
	BeaconImplementation []string
	Index                []uint64
}

type DistinctBeaconBadBlockValueResults added in v0.0.16

type DistinctBeaconBadBlockValueResults struct {
	Node                 []string
	Slot                 []uint64
	Epoch                []uint64
	BlockRoot            []string
	NodeVersion          []string
	Location             []string
	Network              []string
	BeaconImplementation []string
}

type DistinctBeaconBlockValueResults added in v0.0.16

type DistinctBeaconBlockValueResults struct {
	Node                 []string
	Slot                 []uint64
	Epoch                []uint64
	BlockRoot            []string
	NodeVersion          []string
	Location             []string
	Network              []string
	BeaconImplementation []string
}

type DistinctBeaconStateValueResults

type DistinctBeaconStateValueResults struct {
	Node                 []string
	Slot                 []uint64
	Epoch                []uint64
	StateRoot            []string
	NodeVersion          []string
	Location             []string
	Network              []string
	BeaconImplementation []string
}

type DistinctExecutionBadBlockValueResults

type DistinctExecutionBadBlockValueResults struct {
	Node                    []string
	BlockHash               []string
	BlockNumber             []int64
	Location                []string
	Network                 []string
	ExecutionImplementation []string
	NodeVersion             []string
	BlockExtraData          []string
}

type DistinctExecutionBlockTraceValueResults

type DistinctExecutionBlockTraceValueResults struct {
	Node                    []string
	BlockHash               []string
	BlockNumber             []int64
	Location                []string
	Network                 []string
	ExecutionImplementation []string
	NodeVersion             []string
}

type DistinctExecutionPayloadEnvelopeValueResults added in v0.1.0

type DistinctExecutionPayloadEnvelopeValueResults struct {
	Node                 []string
	Slot                 []uint64
	Epoch                []uint64
	BlockRoot            []string
	NodeVersion          []string
	Location             []string
	Network              []string
	BeaconImplementation []string
}

type DistinctPermanentBlockValues added in v0.0.28

type DistinctPermanentBlockValues struct {
	Slot      []uint64
	BlockRoot []string
	Network   []string
}

DistinctPermanentBlockValues returns distinct values for permanent blocks.

type DistributedLock added in v0.0.27

type DistributedLock struct {
	Key       string    `gorm:"primaryKey"`
	Owner     string    `gorm:"not null;default:''"`
	ExpiresAt time.Time `gorm:"not null;index:ix_distributed_locks_expires_at"`
}

DistributedLock is acquired by a single atomic conditional upsert. There is no soft delete: a released lock is a deleted row.

func (*DistributedLock) BeforeSave added in v0.1.0

func (l *DistributedLock) BeforeSave(*gorm.DB) error

BeforeSave keeps the lease in UTC, so a lock taken by one process is honoured by another whatever zone either of them runs in.

type ExecutionBadBlock

type ExecutionBadBlock struct {
	ID                      string    `gorm:"primaryKey"`
	Node                    string    `` /* 145-byte string literal not displayed */
	FetchedAt               time.Time `` /* 181-byte string literal not displayed */
	ExecutionImplementation string    `gorm:"not null;default:''"`
	NodeVersion             string    `gorm:"not null;default:''"`
	ContentEncoding         string    `gorm:"not null;default:''"`
	Location                string    `gorm:"not null;default:''"`
	ContentHash             string    `gorm:"not null;default:'';size:64"`
	// VerifiedAt is set when these bytes were read and hashed from this node.
	VerifiedAt *time.Time
	// ContentMatchedAt is set when the hash was compared against an existing
	// payload and matched. Bad blocks are never linked, so it stays null.
	ContentMatchedAt *time.Time
	Network          string `` /* 205-byte string literal not displayed */
	BlockHash        string `gorm:"not null;default:'';uniqueIndex:ux_execution_bad_blocks_dedupe,priority:2"`
	BlockNumber      sql.NullInt64
	BlockExtraData   sql.NullString
}

func (*ExecutionBadBlock) BeforeSave added in v0.1.0

func (a *ExecutionBadBlock) BeforeSave(*gorm.DB) error

BeforeSave keeps every stored timestamp in UTC. The drivers render a time.Time in the zone the value itself carries, so a row written by a process in another zone would neither order nor compare against the rest of the table.

type ExecutionBadBlockFilter

type ExecutionBadBlockFilter struct {
	ID                      *string
	Node                    *string
	Before                  *time.Time
	After                   *time.Time
	NodeVersion             *string
	Location                *string
	Network                 *string
	ExecutionImplementation *string
	BlockHash               *string
	BlockNumber             *int64
	BlockExtraData          *string
}

func (*ExecutionBadBlockFilter) AddAfter

func (f *ExecutionBadBlockFilter) AddAfter(after time.Time)

func (*ExecutionBadBlockFilter) AddBefore

func (f *ExecutionBadBlockFilter) AddBefore(before time.Time)

func (*ExecutionBadBlockFilter) AddBlockExtraData

func (f *ExecutionBadBlockFilter) AddBlockExtraData(data string)

func (*ExecutionBadBlockFilter) AddBlockHash

func (f *ExecutionBadBlockFilter) AddBlockHash(hash string)

func (*ExecutionBadBlockFilter) AddBlockNumber

func (f *ExecutionBadBlockFilter) AddBlockNumber(number int64)

func (*ExecutionBadBlockFilter) AddExecutionImplementation

func (f *ExecutionBadBlockFilter) AddExecutionImplementation(impl string)

func (*ExecutionBadBlockFilter) AddID

func (f *ExecutionBadBlockFilter) AddID(id string)

func (*ExecutionBadBlockFilter) AddLocation

func (f *ExecutionBadBlockFilter) AddLocation(location string)

func (*ExecutionBadBlockFilter) AddNetwork

func (f *ExecutionBadBlockFilter) AddNetwork(network string)

func (*ExecutionBadBlockFilter) AddNode

func (f *ExecutionBadBlockFilter) AddNode(node string)

func (*ExecutionBadBlockFilter) AddNodeVersion

func (f *ExecutionBadBlockFilter) AddNodeVersion(nodeVersion string)

func (*ExecutionBadBlockFilter) ApplyToQuery

func (f *ExecutionBadBlockFilter) ApplyToQuery(query *gorm.DB) (*gorm.DB, error)

type ExecutionBlockTrace

type ExecutionBlockTrace struct {
	ID                      string    `gorm:"primaryKey"`
	Node                    string    `` /* 149-byte string literal not displayed */
	FetchedAt               time.Time `` /* 187-byte string literal not displayed */
	ExecutionImplementation string    `gorm:"not null;default:''"`
	NodeVersion             string    `gorm:"not null;default:''"`
	ContentEncoding         string    `gorm:"not null;default:''"`
	Location                string    `gorm:"not null;default:''"`
	ContentHash             string    `gorm:"not null;default:'';size:64"`
	// VerifiedAt is set when these bytes were read and hashed from this node.
	VerifiedAt *time.Time
	// ContentMatchedAt is set when the hash was compared against an existing
	// payload and matched.
	ContentMatchedAt *time.Time
	Network          string `` /* 211-byte string literal not displayed */
	BlockHash        string `gorm:"not null;default:'';uniqueIndex:ux_execution_block_traces_dedupe,priority:2"`
	BlockNumber      int64  `gorm:"not null;default:0"`
}

func (*ExecutionBlockTrace) BeforeSave added in v0.1.0

func (a *ExecutionBlockTrace) BeforeSave(*gorm.DB) error

BeforeSave keeps every stored timestamp in UTC. The drivers render a time.Time in the zone the value itself carries, so a row written by a process in another zone would neither order nor compare against the rest of the table.

type ExecutionBlockTraceFilter

type ExecutionBlockTraceFilter struct {
	ID                      *string
	Node                    *string
	Before                  *time.Time
	After                   *time.Time
	NodeVersion             *string
	Location                *string
	Network                 *string
	ExecutionImplementation *string
	BlockHash               *string
	BlockNumber             *int64
}

func (*ExecutionBlockTraceFilter) AddAfter

func (f *ExecutionBlockTraceFilter) AddAfter(after time.Time)

func (*ExecutionBlockTraceFilter) AddBefore

func (f *ExecutionBlockTraceFilter) AddBefore(before time.Time)

func (*ExecutionBlockTraceFilter) AddBlockHash

func (f *ExecutionBlockTraceFilter) AddBlockHash(hash string)

func (*ExecutionBlockTraceFilter) AddBlockNumber

func (f *ExecutionBlockTraceFilter) AddBlockNumber(number int64)

func (*ExecutionBlockTraceFilter) AddExecutionImplementation

func (f *ExecutionBlockTraceFilter) AddExecutionImplementation(impl string)

func (*ExecutionBlockTraceFilter) AddID

func (f *ExecutionBlockTraceFilter) AddID(id string)

func (*ExecutionBlockTraceFilter) AddLocation

func (f *ExecutionBlockTraceFilter) AddLocation(location string)

func (*ExecutionBlockTraceFilter) AddNetwork

func (f *ExecutionBlockTraceFilter) AddNetwork(network string)

func (*ExecutionBlockTraceFilter) AddNode

func (f *ExecutionBlockTraceFilter) AddNode(node string)

func (*ExecutionBlockTraceFilter) AddNodeVersion

func (f *ExecutionBlockTraceFilter) AddNodeVersion(nodeVersion string)

func (*ExecutionBlockTraceFilter) ApplyToQuery

func (f *ExecutionBlockTraceFilter) ApplyToQuery(query *gorm.DB) (*gorm.DB, error)

type ExecutionPayloadEnvelope added in v0.1.0

type ExecutionPayloadEnvelope struct {
	ID   string `gorm:"primaryKey"`
	Node string `` /* 159-byte string literal not displayed */
	// We have to use int64 here as SQLite doesn't support uint64. This sucks
	// but slot 9223372036854775808 is probably around the heat death
	// of the universe so we should be OK.
	Slot                 int64     `gorm:"not null;default:0;uniqueIndex:ux_execution_payload_envelopes_dedupe,priority:2"`
	Epoch                int64     `gorm:"not null;default:0"`
	BlockRoot            string    `gorm:"not null;default:'';uniqueIndex:ux_execution_payload_envelopes_dedupe,priority:3"`
	FetchedAt            time.Time `` /* 202-byte string literal not displayed */
	BeaconImplementation string    `gorm:"not null;default:''"`
	NodeVersion          string    `gorm:"not null;default:''"`
	ContentEncoding      string    `gorm:"not null;default:''"`
	Location             string    `gorm:"not null;default:''"`
	ContentHash          string    `gorm:"not null;default:'';size:64"`
	// VerifiedAt is set when these bytes were read and hashed from this node.
	VerifiedAt *time.Time
	// ContentMatchedAt is set when the hash was compared against an existing
	// payload and matched.
	ContentMatchedAt *time.Time
	Network          string `` /* 226-byte string literal not displayed */
}

func (*ExecutionPayloadEnvelope) BeforeSave added in v0.1.0

func (a *ExecutionPayloadEnvelope) BeforeSave(*gorm.DB) error

BeforeSave keeps every stored timestamp in UTC. The drivers render a time.Time in the zone the value itself carries, so a row written by a process in another zone would neither order nor compare against the rest of the table.

type ExecutionPayloadEnvelopeFilter added in v0.1.0

type ExecutionPayloadEnvelopeFilter struct {
	ID                   *string
	Node                 *string
	Before               *time.Time
	After                *time.Time
	Slot                 *uint64
	Epoch                *uint64
	BlockRoot            *string
	NodeVersion          *string
	Location             *string
	Network              *string
	BeaconImplementation *string
}

func (*ExecutionPayloadEnvelopeFilter) AddAfter added in v0.1.0

func (f *ExecutionPayloadEnvelopeFilter) AddAfter(after time.Time)

func (*ExecutionPayloadEnvelopeFilter) AddBeaconImplementation added in v0.1.0

func (f *ExecutionPayloadEnvelopeFilter) AddBeaconImplementation(beaconImplementation string)

func (*ExecutionPayloadEnvelopeFilter) AddBefore added in v0.1.0

func (f *ExecutionPayloadEnvelopeFilter) AddBefore(before time.Time)

func (*ExecutionPayloadEnvelopeFilter) AddBlockRoot added in v0.1.0

func (f *ExecutionPayloadEnvelopeFilter) AddBlockRoot(blockRoot string)

func (*ExecutionPayloadEnvelopeFilter) AddEpoch added in v0.1.0

func (f *ExecutionPayloadEnvelopeFilter) AddEpoch(epoch uint64)

func (*ExecutionPayloadEnvelopeFilter) AddID added in v0.1.0

func (*ExecutionPayloadEnvelopeFilter) AddLocation added in v0.1.0

func (f *ExecutionPayloadEnvelopeFilter) AddLocation(location string)

func (*ExecutionPayloadEnvelopeFilter) AddNetwork added in v0.1.0

func (f *ExecutionPayloadEnvelopeFilter) AddNetwork(network string)

func (*ExecutionPayloadEnvelopeFilter) AddNode added in v0.1.0

func (f *ExecutionPayloadEnvelopeFilter) AddNode(node string)

func (*ExecutionPayloadEnvelopeFilter) AddNodeVersion added in v0.1.0

func (f *ExecutionPayloadEnvelopeFilter) AddNodeVersion(nodeVersion string)

func (*ExecutionPayloadEnvelopeFilter) AddSlot added in v0.1.0

func (f *ExecutionPayloadEnvelopeFilter) AddSlot(slot uint64)

func (*ExecutionPayloadEnvelopeFilter) ApplyToQuery added in v0.1.0

func (f *ExecutionPayloadEnvelopeFilter) ApplyToQuery(query *gorm.DB) (*gorm.DB, error)

type ExpiringArtifact added in v0.1.0

type ExpiringArtifact struct {
	ID          string
	Location    string
	ContentHash string
	Network     string
	Slot        int64
	// Identifier is the root or hash that completes the dedupe key: state_root, block_root
	// or block_hash depending on the kind.
	Identifier  string
	BlockNumber int64
}

ExpiringArtifact is the narrow projection retention needs: enough to identify the row, find its object and work out which blob it references. Deliberately not the whole row.

type Indexer

type Indexer struct {
	// contains filtered or unexported fields
}

func NewIndexer

func NewIndexer(namespace string, log logrus.FieldLogger, config Config, opts *Options) (*Indexer, error)

func NewMockIndexer added in v0.0.15

func NewMockIndexer() (*Indexer, sqlmock.Sqlmock, error)

func (*Indexer) AcquireLock added in v0.0.27

func (i *Indexer) AcquireLock(ctx context.Context, key, owner string, ttl time.Duration) (bool, error)

AcquireLock attempts to acquire the lock with the given key, taking it over when the current holder's lease has expired and extending it when the caller already owns it. A lock held by someone else is reported as (false, nil), not an error.

func (*Indexer) AgreementCountsByLocation added in v0.1.0

func (i *Indexer) AgreementCountsByLocation(ctx context.Context, kind, network string, locations []string) (map[string]int64, error)

AgreementCountsByLocation returns, per blob location, how many rows currently reference the ready blob stored there — the number of nodes whose verified payload agrees. A linked row carries its blob's location, so the location is the row→blob join that stays inside one dedupe key: grouping by content hash instead would merge blobs that happen to share bytes across keys — routine for traces, where an empty trace is identical JSON on every client build, yet the count is presented per build. A location with no ready blob is absent from the map: its agreement is unknown, not zero, and the caller must not dress it up as either.

func (*Indexer) BlobLinksByDedupKey added in v0.1.0

func (i *Indexer) BlobLinksByDedupKey(ctx context.Context, kind, network string, dedupKeys []string) (map[string]string, error)

BlobLinksByDedupKey resolves blobs by their primary key. Tombstoned blobs are included: a row still counts as linked to a blob that is being collected, and must not delete the object out from under the collector.

func (*Indexer) BlobLinksByLocation added in v0.1.0

func (i *Indexer) BlobLinksByLocation(ctx context.Context, kind, network string, contentHashes []string) (map[string]string, error)

BlobLinksByLocation resolves blobs for kinds whose dedupe key cannot be rebuilt from the artifact row. The content hash index narrows the search and the location decides the match, which is the same linkage rule stated the other way round.

func (*Indexer) CleanupExpiredLocks added in v0.1.0

func (i *Indexer) CleanupExpiredLocks(ctx context.Context) error

CleanupExpiredLocks removes lock rows whose lease has run out. Acquisition does not depend on it; it only keeps abandoned rows from accumulating.

func (*Indexer) CountBeaconBadBlob added in v0.0.16

func (i *Indexer) CountBeaconBadBlob(ctx context.Context, filter *BeaconBadBlobFilter) (int64, error)

func (*Indexer) CountBeaconBadBlock added in v0.0.16

func (i *Indexer) CountBeaconBadBlock(ctx context.Context, filter *BeaconBadBlockFilter) (int64, error)

func (*Indexer) CountBeaconBlock added in v0.0.16

func (i *Indexer) CountBeaconBlock(ctx context.Context, filter *BeaconBlockFilter) (int64, error)

func (*Indexer) CountBeaconState

func (i *Indexer) CountBeaconState(ctx context.Context, filter *BeaconStateFilter) (int64, error)

func (*Indexer) CountExecutionBadBlock

func (i *Indexer) CountExecutionBadBlock(ctx context.Context, filter *ExecutionBadBlockFilter) (int64, error)

func (*Indexer) CountExecutionBlockTrace

func (i *Indexer) CountExecutionBlockTrace(ctx context.Context, filter *ExecutionBlockTraceFilter) (int64, error)

func (*Indexer) CountExecutionPayloadEnvelope added in v0.1.0

func (i *Indexer) CountExecutionPayloadEnvelope(ctx context.Context, filter *ExecutionPayloadEnvelopeFilter) (int64, error)

func (*Indexer) CountExpiring added in v0.1.0

func (i *Indexer) CountExpiring(ctx context.Context, kind string, before time.Time) (int64, error)

CountExpiring reports how many rows are still past their retention cutoff. It is the purge backlog, and it is a plain indexed count so it can be sampled every cycle.

func (*Indexer) CountExpiringPayloadDivergences added in v0.1.0

func (i *Indexer) CountExpiringPayloadDivergences(ctx context.Context, before time.Time) (int64, error)

CountExpiringPayloadDivergences reports how many divergence records are past the cutoff.

func (*Indexer) CountPermanentBlock added in v0.0.28

func (i *Indexer) CountPermanentBlock(ctx context.Context, filter *PermanentBlockFilter) (int64, error)

CountPermanentBlock counts permanent blocks based on the filter.

func (*Indexer) DeleteArtifacts added in v0.1.0

func (i *Indexer) DeleteArtifacts(ctx context.Context, kind string, ids []string, decrements []BlobRefDecrement) (int64, error)

DeleteArtifacts removes a batch of rows and releases the references they held, in one transaction. Rows go first and objects follow, so a crash between the two leaves an orphaned object — recoverable — rather than a row pointing at nothing.

func (*Indexer) DeleteBeaconBadBlob added in v0.0.16

func (i *Indexer) DeleteBeaconBadBlob(ctx context.Context, id string) error

func (*Indexer) DeleteBeaconBadBlock added in v0.0.16

func (i *Indexer) DeleteBeaconBadBlock(ctx context.Context, id string) error

func (*Indexer) DeleteBeaconBlock added in v0.0.16

func (i *Indexer) DeleteBeaconBlock(ctx context.Context, id string) error

func (*Indexer) DeleteBeaconState

func (i *Indexer) DeleteBeaconState(ctx context.Context, id string) error

func (*Indexer) DeleteExecutionBadBlock

func (i *Indexer) DeleteExecutionBadBlock(ctx context.Context, id string) error

func (*Indexer) DeleteExecutionBlockTrace

func (i *Indexer) DeleteExecutionBlockTrace(ctx context.Context, id string) error

func (*Indexer) DeleteExecutionPayloadEnvelope added in v0.1.0

func (i *Indexer) DeleteExecutionPayloadEnvelope(ctx context.Context, id string) error

func (*Indexer) DeleteExpiredPayloadDivergences added in v0.1.0

func (i *Indexer) DeleteExpiredPayloadDivergences(ctx context.Context, before time.Time, limit int) (int64, error)

DeleteExpiredPayloadDivergences removes divergence records older than the cutoff, a bounded page at a time. Divergences are written by every node on every mismatch, so a client bug or a fork turns this into a high-rate stream that would otherwise never be trimmed.

The ids are collected first because a delete with a limit is not portable.

func (*Indexer) DeleteTombstonedBlob added in v0.1.0

func (i *Indexer) DeleteTombstonedBlob(ctx context.Context, c *BlobCandidate) (bool, error)

DeleteTombstonedBlob removes the row once its object is gone. The generation predicate is what keeps a resurrected blob alive: a blob that came back has a new generation and a new object, and this delete simply does not match it.

func (*Indexer) DistinctBeaconBadBlobValues added in v0.0.16

func (i *Indexer) DistinctBeaconBadBlobValues(ctx context.Context, fields []string, network string) (*DistinctBeaconBadBlobValueResults, error)

func (*Indexer) DistinctBeaconBadBlockValues added in v0.0.16

func (i *Indexer) DistinctBeaconBadBlockValues(ctx context.Context, fields []string, network string) (*DistinctBeaconBadBlockValueResults, error)

func (*Indexer) DistinctBeaconBlockValues added in v0.0.16

func (i *Indexer) DistinctBeaconBlockValues(ctx context.Context, fields []string, network string) (*DistinctBeaconBlockValueResults, error)

func (*Indexer) DistinctBeaconStateValues

func (i *Indexer) DistinctBeaconStateValues(ctx context.Context, fields []string, network string) (*DistinctBeaconStateValueResults, error)

func (*Indexer) DistinctExecutionBadBlockValues

func (i *Indexer) DistinctExecutionBadBlockValues(ctx context.Context, fields []string, network string) (*DistinctExecutionBadBlockValueResults, error)

func (*Indexer) DistinctExecutionBlockTraceValues

func (i *Indexer) DistinctExecutionBlockTraceValues(ctx context.Context, fields []string, network string) (*DistinctExecutionBlockTraceValueResults, error)

func (*Indexer) DistinctExecutionPayloadEnvelopeValues added in v0.1.0

func (i *Indexer) DistinctExecutionPayloadEnvelopeValues(ctx context.Context, fields []string, network string) (*DistinctExecutionPayloadEnvelopeValueResults, error)

func (*Indexer) DistinctPermanentBlockValues added in v0.0.28

func (i *Indexer) DistinctPermanentBlockValues(ctx context.Context, fields []string) (*DistinctPermanentBlockValues, error)

DistinctPermanentBlockValues gets distinct values for permanent blocks.

func (*Indexer) FindRootDisagreements added in v0.1.0

func (i *Indexer) FindRootDisagreements(ctx context.Context, kind string, slotWindow int64) ([]*RootDisagreement, error)

FindRootDisagreements reports slots within the recent window where the network did not agree on a single root. The group rides the leading columns of the dedupe index.

func (*Indexer) GetBlob added in v0.1.0

func (i *Indexer) GetBlob(ctx context.Context, kind, network, dedupKey string) (*Blob, error)

GetBlob returns the linkable blob for a dedupe key. Only a blob in the ready state is a hit; anything else yields ErrBlobNotFound.

func (*Indexer) GetPermanentBlockByBlockRoot added in v0.0.28

func (i *Indexer) GetPermanentBlockByBlockRoot(ctx context.Context, kind, blockRoot, network string) (*PermanentBlock, error)

GetPermanentBlockByBlockRoot retrieves a permanent artifact by kind, block root and network. A row that is not there returns ErrPermanentBlockNotFound, which is the normal answer and not a database error.

func (*Indexer) InsertArtifact added in v0.1.0

InsertArtifact inserts one artifact row and, when the row references a blob, takes the reference in the same transaction. The unique index is the arbiter of duplication; the conditional reference bump is the arbiter of linkage. Nothing here reads before it writes.

func (*Indexer) InsertBeaconBadBlob added in v0.0.16

func (i *Indexer) InsertBeaconBadBlob(ctx context.Context, blob *BeaconBadBlob) error

func (*Indexer) InsertBeaconBadBlock added in v0.0.16

func (i *Indexer) InsertBeaconBadBlock(ctx context.Context, block *BeaconBadBlock) error

func (*Indexer) InsertBeaconBlock added in v0.0.16

func (i *Indexer) InsertBeaconBlock(ctx context.Context, block *BeaconBlock) error

func (*Indexer) InsertBeaconState

func (i *Indexer) InsertBeaconState(ctx context.Context, state *BeaconState) error

func (*Indexer) InsertBlob added in v0.1.0

func (i *Indexer) InsertBlob(ctx context.Context, blob *Blob) (*Blob, error)

InsertBlob inserts a blob and returns the row that won: the freshly inserted one, the one that was already there, or a tombstoned one brought back to life. A caller that lost the race compares the winner's hash and location against its own and acts on the difference.

func (*Indexer) InsertExecutionBadBlock

func (i *Indexer) InsertExecutionBadBlock(ctx context.Context, trace *ExecutionBadBlock) error

func (*Indexer) InsertExecutionBlockTrace

func (i *Indexer) InsertExecutionBlockTrace(ctx context.Context, trace *ExecutionBlockTrace) error

func (*Indexer) InsertExecutionPayloadEnvelope added in v0.1.0

func (i *Indexer) InsertExecutionPayloadEnvelope(ctx context.Context, envelope *ExecutionPayloadEnvelope) error

func (*Indexer) InsertPayloadDivergence added in v0.1.0

func (i *Indexer) InsertPayloadDivergence(ctx context.Context, divergence *PayloadDivergence) error

InsertPayloadDivergence records a divergence observation.

func (*Indexer) InsertPermanentBlock added in v0.0.28

func (i *Indexer) InsertPermanentBlock(ctx context.Context, block *PermanentBlock) error

InsertPermanentBlock inserts a permanent block record. A record that already exists is left alone rather than erroring: two replicas racing past the distributed lock both believe they inserted, and both are right.

func (*Indexer) ListBeaconBadBlob added in v0.0.16

func (i *Indexer) ListBeaconBadBlob(ctx context.Context, filter *BeaconBadBlobFilter, page *PaginationCursor) ([]*BeaconBadBlob, error)

func (*Indexer) ListBeaconBadBlock added in v0.0.16

func (i *Indexer) ListBeaconBadBlock(ctx context.Context, filter *BeaconBadBlockFilter, page *PaginationCursor) ([]*BeaconBadBlock, error)

func (*Indexer) ListBeaconBlock added in v0.0.16

func (i *Indexer) ListBeaconBlock(ctx context.Context, filter *BeaconBlockFilter, page *PaginationCursor) ([]*BeaconBlock, error)

func (*Indexer) ListBeaconState

func (i *Indexer) ListBeaconState(ctx context.Context, filter *BeaconStateFilter, page *PaginationCursor) ([]*BeaconState, error)

func (*Indexer) ListCollectableBlobs added in v0.1.0

func (i *Indexer) ListCollectableBlobs(ctx context.Context, createdBefore time.Time, limit, offset int) ([]*BlobCandidate, error)

ListCollectableBlobs returns blobs whose reference count has reached zero and that are older than the grace period. The count is only a hint: every candidate is re-checked against the artifact tables before anything is deleted.

Tombstoned blobs past the cutoff are candidates too: a blob whose object delete failed after tombstoning has nothing else left to drive a retry, and a resurrected blob re-enters with a fresh created_at and generation, so neither the grace period nor the generation guard is weakened by offering them again.

The offset is how the caller steps over candidates it has already decided it cannot collect. The order is oldest first and a candidate that is not collected does not go away, so without it a single unevaluable row would occupy the head of every page for ever and nothing behind it would ever be reached.

func (*Indexer) ListExecutionBadBlock

func (i *Indexer) ListExecutionBadBlock(ctx context.Context, filter *ExecutionBadBlockFilter, page *PaginationCursor) ([]*ExecutionBadBlock, error)

func (*Indexer) ListExecutionBlockTrace

func (i *Indexer) ListExecutionBlockTrace(ctx context.Context, filter *ExecutionBlockTraceFilter, page *PaginationCursor) ([]*ExecutionBlockTrace, error)

func (*Indexer) ListExecutionPayloadEnvelope added in v0.1.0

func (i *Indexer) ListExecutionPayloadEnvelope(ctx context.Context, filter *ExecutionPayloadEnvelopeFilter, page *PaginationCursor) ([]*ExecutionPayloadEnvelope, error)

func (*Indexer) ListExpiringBeaconBadBlobs added in v0.1.0

func (i *Indexer) ListExpiringBeaconBadBlobs(ctx context.Context, before time.Time, limit, offset int) ([]*ExpiringArtifact, error)

func (*Indexer) ListExpiringBeaconBadBlocks added in v0.1.0

func (i *Indexer) ListExpiringBeaconBadBlocks(ctx context.Context, before time.Time, limit, offset int) ([]*ExpiringArtifact, error)

func (*Indexer) ListExpiringBeaconBlocks added in v0.1.0

func (i *Indexer) ListExpiringBeaconBlocks(ctx context.Context, before time.Time, limit, offset int) ([]*ExpiringArtifact, error)

func (*Indexer) ListExpiringBeaconStates added in v0.1.0

func (i *Indexer) ListExpiringBeaconStates(ctx context.Context, before time.Time, limit, offset int) ([]*ExpiringArtifact, error)

func (*Indexer) ListExpiringExecutionBadBlocks added in v0.1.0

func (i *Indexer) ListExpiringExecutionBadBlocks(ctx context.Context, before time.Time, limit, offset int) ([]*ExpiringArtifact, error)

func (*Indexer) ListExpiringExecutionBlockTraces added in v0.1.0

func (i *Indexer) ListExpiringExecutionBlockTraces(ctx context.Context, before time.Time, limit, offset int) ([]*ExpiringArtifact, error)

func (*Indexer) ListExpiringExecutionPayloadEnvelopes added in v0.1.0

func (i *Indexer) ListExpiringExecutionPayloadEnvelopes(ctx context.Context, before time.Time, limit, offset int) ([]*ExpiringArtifact, error)

func (*Indexer) ListPayloadDivergence added in v0.1.0

func (i *Indexer) ListPayloadDivergence(ctx context.Context, filter *PayloadDivergenceFilter, page *PaginationCursor) ([]*PayloadDivergence, error)

ListPayloadDivergence lists divergences newest first unless the cursor orders otherwise.

func (*Indexer) ListPermanentBlock added in v0.0.28

func (i *Indexer) ListPermanentBlock(ctx context.Context, filter *PermanentBlockFilter, pagination *PaginationCursor) ([]*PermanentBlock, error)

ListPermanentBlock lists permanent blocks based on the filter.

func (*Indexer) LocationsStillReferenced added in v0.1.0

func (i *Indexer) LocationsStillReferenced(ctx context.Context, kind string, locations []string) (map[string]struct{}, error)

LocationsStillReferenced narrows a set of locations to the ones rows of this kind still point at.

An unlinked row usually owns its object outright, but not always: a copy stored because it disagreed with the canonical payload is addressed by its content alone, with no node in the path, so every node that served those same bytes wrote the same object and every one of their rows is unlinked. Deleting on the strength of one page would empty a location the rest of that group still advertises.

func (*Indexer) ReleaseLock added in v0.0.27

func (i *Indexer) ReleaseLock(ctx context.Context, key, owner string) error

ReleaseLock releases a lock with the given key if it's owned by the given owner.

func (*Indexer) RemoveBeaconBadBlob added in v0.0.16

func (i *Indexer) RemoveBeaconBadBlob(ctx context.Context, id string) error

func (*Indexer) RemoveBeaconBadBlock added in v0.0.16

func (i *Indexer) RemoveBeaconBadBlock(ctx context.Context, id string) error

func (*Indexer) RemoveBeaconBlock added in v0.0.16

func (i *Indexer) RemoveBeaconBlock(ctx context.Context, id string) error

func (*Indexer) RemoveBeaconState

func (i *Indexer) RemoveBeaconState(ctx context.Context, id string) error

func (*Indexer) RemoveExecutionPayloadEnvelope added in v0.1.0

func (i *Indexer) RemoveExecutionPayloadEnvelope(ctx context.Context, id string) error

func (*Indexer) SlotsWithDivergence added in v0.1.0

func (i *Indexer) SlotsWithDivergence(ctx context.Context, network, kind string, fromSlot int64) (map[int64]struct{}, error)

SlotsWithDivergence returns the slots inside a window for which some node served bytes that disagreed with the canonical payload. It is the evidence that separates a slot two nodes disagree about because the chain reorganised from one they disagree about because a node is serving something wrong.

func (*Indexer) Start

func (i *Indexer) Start(ctx context.Context) error

func (*Indexer) Stop

func (i *Indexer) Stop(ctx context.Context) error

func (*Indexer) TombstoneBlob added in v0.1.0

func (i *Indexer) TombstoneBlob(ctx context.Context, c *BlobCandidate) (BlobTombstoneOutcome, error)

TombstoneBlob moves a candidate to the deleting state after confirming against the artifact tables that nothing references it. Both halves run in one transaction so a create that lands between the check and the mark loses the race cleanly rather than losing its payload.

type InsertArtifactParams added in v0.1.0

type InsertArtifactParams struct {
	// Row is the model to insert; ConflictColumns must name that table's unique index
	// exactly, as a set.
	Row             any
	ConflictColumns []string

	// Kind, Network and DedupKey identify the blob the row may reference. An empty DedupKey
	// or ContentHash means the row references no blob at all.
	Kind        string
	Network     string
	DedupKey    string
	ContentHash string

	// Location is where the row's own bytes live. A reference is only taken when the blob
	// agrees on it: the same dedupe key stored at a different location is a divergent copy,
	// not a second reference.
	Location string
}

InsertArtifactParams describes one artifact write.

type Operation

type Operation string
const (
	OperationDistinctValues Operation = "distinct_values"

	OperationInsertBeaconState Operation = "insert_beacon_state_metadata"
	OperationDeleteBeaconState Operation = "delete_beacon_state_metadata"
	OperationCountBeaconState  Operation = "count_beacon_state_metadata"
	OperationListBeaconState   Operation = "list_beacon_state_metadata"

	OperationInsertBeaconBlock Operation = "insert_beacon_block_metadata"
	OperationDeleteBeaconBlock Operation = "delete_beacon_block_metadata"
	OperationCountBeaconBlock  Operation = "count_beacon_block_metadata"
	OperationListBeaconBlock   Operation = "list_beacon_block_metadata"

	OperationInsertExecutionPayloadEnvelope Operation = "insert_execution_payload_envelope_metadata"
	OperationDeleteExecutionPayloadEnvelope Operation = "delete_execution_payload_envelope_metadata"
	OperationCountExecutionPayloadEnvelope  Operation = "count_execution_payload_envelope_metadata"
	OperationListExecutionPayloadEnvelope   Operation = "list_execution_payload_envelope_metadata"

	OperationInsertBeaconBadBlock Operation = "insert_beacon_bad_block_metadata"
	OperationDeleteBeaconBadBlock Operation = "delete_beacon_bad_block_metadata"
	OperationCountBeaconBadBlock  Operation = "count_beacon_bad_block_metadata"
	OperationListBeaconBadBlock   Operation = "list_beacon_bad_block_metadata"

	OperationInsertBeaconBadBlob Operation = "insert_beacon_bad_blob_metadata"
	OperationDeleteBeaconBadBlob Operation = "delete_beacon_bad_blob_metadata"
	OperationCountBeaconBadBlob  Operation = "count_beacon_bad_blob_metadata"
	OperationListBeaconBadBlob   Operation = "list_beacon_bad_blob_metadata"

	OperationInsertExecutionBlockTrace Operation = "insert_execution_block_trace"
	OperationDeleteExecutionBlockTrace Operation = "delete_execution_block_trace"
	OperationCountExecutionBlockTrace  Operation = "count_execution_block_trace"
	OperationListExecutionBlockTrace   Operation = "list_execution_block_trace"

	OperationInsertExecutionBadBlock Operation = "insert_execution_bad_block"
	OperationDeleteExecutionBadBlock Operation = "delete_execution_bad_block"
	OperationCountExecutionBadBlock  Operation = "count_execution_bad_block"
	OperationListExecutionBadBlock   Operation = "list_execution_bad_block"

	OperationGetBlob    Operation = "get_blob"
	OperationInsertBlob Operation = "insert_blob"

	OperationInsertPayloadDivergence Operation = "insert_payload_divergence"
	OperationListPayloadDivergence   Operation = "list_payload_divergence"

	OperationInsertPermanentBlock Operation = "insert_permanent_block"
	OperationGetPermanentBlock    Operation = "get_permanent_block"
	OperationCountPermanentBlock  Operation = "count_permanent_block"
	OperationListPermanentBlock   Operation = "list_permanent_block"
)

type Options added in v0.0.15

type Options struct {
	MetricsEnabled bool
}

func DefaultOptions added in v0.0.15

func DefaultOptions() *Options

func (*Options) SetMetricsEnabled added in v0.0.15

func (o *Options) SetMetricsEnabled(enabled bool) *Options

func (*Options) Validate added in v0.0.15

func (o *Options) Validate() error

func (*Options) WithMetricsDisabled added in v0.0.15

func (o *Options) WithMetricsDisabled() *Options

func (*Options) WithMetricsEnabled added in v0.0.15

func (o *Options) WithMetricsEnabled() *Options

type PaginationCursor

type PaginationCursor struct {
	// The cursor to start from.
	Offset int `json:"offset"`
	// The number of items to return.
	Limit int `json:"limit"`
	// OrderBy is the column to order by.
	OrderBy string `json:"order_by"`
}

func (*PaginationCursor) ApplyOffsetLimit

func (p *PaginationCursor) ApplyOffsetLimit(query *gorm.DB) *gorm.DB

func (*PaginationCursor) ApplyOrderBy

func (p *PaginationCursor) ApplyOrderBy(query *gorm.DB) (*gorm.DB, error)

func (*PaginationCursor) Validate

func (p *PaginationCursor) Validate() error

type PayloadDivergence added in v0.1.0

type PayloadDivergence struct {
	ID string `gorm:"primaryKey"`

	ObservedAt time.Time `gorm:"not null;index:ix_payload_divergences_observed_at;index:ix_payload_divergences_network_kind_observed_at,priority:3"`
	Network    string    `` /* 154-byte string literal not displayed */
	Kind       string    `` /* 162-byte string literal not displayed */
	Node       string    `gorm:"not null;default:''"`

	DedupKey string `gorm:"not null;default:'';index:ix_payload_divergences_network_kind_dedup_key,priority:3"`

	ExpectedHash string `gorm:"not null;default:'';size:64"` // the recorded blob's content_hash
	ActualHash   string `gorm:"not null;default:'';size:64"` // what this node served

	// Human/UI-facing identity. Slot is 0 for the execution kinds.
	Slot       int64  `gorm:"not null;default:0"`
	Identifier string `gorm:"not null;default:''"` // state_root / block_root / block_hash

	// 1 = first observation, 2 = the single re-fetch.
	Attempt int32 `gorm:"not null;default:1"`
	// "alarm" for states/blocks/envelopes, "notice" for traces.
	Severity string `gorm:"not null;default:'';size:16"`
	// Location of the divergent copy, empty when the re-fetch failed or the window closed.
	Location string `gorm:"not null;default:''"`
}

PayloadDivergence records that a node served bytes whose hash did not match the canonical blob for the same dedup key. The record is the finding; the divergent payload may or may not have been re-fetched.

func (*PayloadDivergence) BeforeSave added in v0.1.0

func (d *PayloadDivergence) BeforeSave(*gorm.DB) error

BeforeSave keeps observed_at in UTC. Half these rows arrive with a timestamp from the agent and half are stamped here; both have to compare against the same cutoff.

type PayloadDivergenceFilter added in v0.1.0

type PayloadDivergenceFilter struct {
	Network  *string
	Kind     *string
	DedupKey *string
	Before   *time.Time
	After    *time.Time
}

func (*PayloadDivergenceFilter) AddAfter added in v0.1.0

func (f *PayloadDivergenceFilter) AddAfter(after time.Time)

func (*PayloadDivergenceFilter) AddBefore added in v0.1.0

func (f *PayloadDivergenceFilter) AddBefore(before time.Time)

func (*PayloadDivergenceFilter) AddDedupKey added in v0.1.0

func (f *PayloadDivergenceFilter) AddDedupKey(dedupKey string)

func (*PayloadDivergenceFilter) AddKind added in v0.1.0

func (f *PayloadDivergenceFilter) AddKind(kind string)

func (*PayloadDivergenceFilter) AddNetwork added in v0.1.0

func (f *PayloadDivergenceFilter) AddNetwork(network string)

func (*PayloadDivergenceFilter) ApplyToQuery added in v0.1.0

func (f *PayloadDivergenceFilter) ApplyToQuery(query *gorm.DB) (*gorm.DB, error)

type PermanentBlock added in v0.0.28

type PermanentBlock struct {
	ID uint `gorm:"primaryKey"`
	// We have to use int64 here as SQLite doesn't support uint64
	Slot      int64  `gorm:"not null;default:0"`
	Kind      string `gorm:"not null;default:'beacon_block';uniqueIndex:ux_permanent_blocks_kind_block_root_network,priority:1"`
	BlockRoot string `gorm:"not null;default:'';uniqueIndex:ux_permanent_blocks_kind_block_root_network,priority:2"`
	Network   string `gorm:"not null;default:'';uniqueIndex:ux_permanent_blocks_kind_block_root_network,priority:3"`
}

PermanentBlock represents a permanently stored artifact in the database. This provides a mapping between kind, slot, block_root, and network for artifacts that have been copied to permanent storage.

It has no retention on purpose: it is the index of what was kept for ever, so a row that expired would leave a permanent object nothing points at.

Kind is part of the identity, not decoration. Gloas splits a slot across two artifacts - the block and its execution payload envelope - which share a block root, so without kind the second one to arrive would collide with the first and never be archived.

The only production lookup is by (kind, block_root, network), so that triple carries the one index, and unique makes it the integrity guarantee the get-before-insert flow in the permanent store otherwise only approximates.

type PermanentBlockFilter added in v0.0.28

type PermanentBlockFilter struct {
	Slot      *int64
	Kind      *string
	BlockRoot *string
	Network   *string
}

func (*PermanentBlockFilter) AddBlockRoot added in v0.0.28

func (f *PermanentBlockFilter) AddBlockRoot(blockRoot string)

func (*PermanentBlockFilter) AddKind added in v0.1.0

func (f *PermanentBlockFilter) AddKind(kind string)

func (*PermanentBlockFilter) AddNetwork added in v0.0.28

func (f *PermanentBlockFilter) AddNetwork(network string)

func (*PermanentBlockFilter) AddSlot added in v0.0.28

func (f *PermanentBlockFilter) AddSlot(slot int64)

func (*PermanentBlockFilter) ApplyToQuery added in v0.0.28

func (f *PermanentBlockFilter) ApplyToQuery(query *gorm.DB) (*gorm.DB, error)

type RootDisagreement added in v0.1.0

type RootDisagreement struct {
	Network string
	Slot    int64
	Roots   int64
}

RootDisagreement is one slot on which nodes reported more than one root.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL