publish

package
v0.167.0 Latest Latest
Warning

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

Go to latest
Published: Jul 11, 2026 License: MIT Imports: 15 Imported by: 0

Documentation

Overview

Package publish carries approved queue decisions into the BIBFRAME grain store: editorial quads written under ETag optimistic concurrency, the advisory ingest lease, and the downstream rebuild trigger. The write discipline (read -> patch -> conditional put -> retry-from-fresh) is safe against concurrent editors and re-ingest because editorial statements are independent IRI-based quads and canonicalization dedups.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrGrainStore    = errors.New("grain store unavailable")
	ErrGrainConflict = errors.New("the record kept changing while it was being edited")
)

ErrGrainStore and ErrGrainConflict classify the ways MutateGrain can fail that are not the caller's own doing.

MutateGrain has three error sources -- the store's read, the caller's mutate closure, and the store's write -- and used to return all three the same way. A caller could not tell "no such work", which is the user's answer and safe to show them, from an *os.PathError naming the blob root, which is neither (tasks/272). Store errors now wrap ErrGrainStore, CAS exhaustion is ErrGrainConflict, and the closure's error passes through untouched, so errors.Is sorts the three without matching on strings.

The store's own sentinel survives the wrap (blob.ErrReadOnly, and so on): callers that must tell a read-only deployment from a broken one still can, which is the discipline tasks/260 settled for the single-record route.

View Source
var ErrIngestActive = errors.New("publish: ingest lease held; publish deferred")

ErrIngestActive reports that the ingest lease is held: approvals stay queued (durable) and publishing retries after the lease expires.

Functions

func MutateGrain

func MutateGrain(ctx context.Context, st blob.Store, path string, mutate func(old []byte) ([]byte, error)) (etag string, err error)

MutateGrain applies mutate to the grain at path under ETag optimistic concurrency: read, transform, conditional put, retry from fresh on conflict. The exported CAS primitive record editing (tasks/037) and store-backed ingest share.

Errors sort three ways, and callers that answer a request must tell them apart before showing anything to a person (see ErrGrainStore):

  • the store's read or write failed -- wraps ErrGrainStore, and the store's own sentinel too, so blob.ErrReadOnly stays reachable.
  • the retries ran out -- ErrGrainConflict. It names no path: the caller knows the path and can log it; a client has no use for it.
  • anything else came from mutate, unwrapped. It is the caller's own error, phrased for whoever asked.

Types

type IndexUpdater added in v0.53.0

type IndexUpdater interface {
	Apply(grainPath, etag string, grain []byte)
	AppendFeed(ctx context.Context, paths ...string) error
}

IndexUpdater is the workindex.Index surface publish writes keep exact: Apply folds one written grain in, AppendFeed publishes the changed paths so other containers read-their-writes (mirrors batch.IndexUpdater).

type Lease

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

Lease is the advisory ingest lease: feed re-ingest holds it (identity resolution is single-flight), and the publisher defers -- never drops -- approved changes while it is held. Expiry is carried in the record body, not store TTL, because DynamoDB expires lazily.

func NewLease

func NewLease(db store.Store, name string, ttl time.Duration) *Lease

NewLease wires the lease with the given hold duration.

func (*Lease) Acquire

func (l *Lease) Acquire(ctx context.Context, holder string) (bool, error)

Acquire attempts to take the lease for holder. It returns false when another holder has it un-expired. Re-acquiring one's own live lease extends it.

func (*Lease) Heartbeat

func (l *Lease) Heartbeat(ctx context.Context, holder string) error

Heartbeat extends the holder's live lease.

func (*Lease) Held

func (l *Lease) Held(ctx context.Context) (string, bool, error)

Held reports the current live holder, if any.

func (*Lease) Release

func (l *Lease) Release(ctx context.Context, holder string) error

Release drops the lease if holder still owns it.

func (*Lease) SetClock

func (l *Lease) SetClock(now func() time.Time)

SetClock overrides the clock (tests).

type Publisher

type Publisher struct {
	Blob  blob.Store
	Queue *suggest.Service
	Vocab *vocab.Index
	// Trigger receives one grains-changed event per successful run
	// (nil = no notification).
	Trigger trigger.Notifier
	// Lease, when set, defers publishing while ingest holds it.
	Lease *Lease
	// Prefix is the grain tree root in the blob store ("" = repo-layout
	// paths straight from bibframe.GrainPath).
	Prefix string
	// Summaries, when set, is the shared maintained summary source
	// (workindex, tasks/109) tag promotion scans instead of a per-run
	// corpus walk; nil falls back to ScanSummaries.
	Summaries ingest.SummarySource
	// Index, when set, is kept exact for this publisher's own grain writes
	// -- the read-your-writes contract the single-record and batch paths
	// hold (tasks/195, tasks/203). Without it, tag promotions and approved
	// publishes wait out the workindex refresh TTL: invisible to work
	// search for up to 30s, and batch selections resolve against the
	// stale index meanwhile.
	Index  IndexUpdater
	Logger *slog.Logger
}

Publisher drains approved-unpublished queue items into grains.

func (*Publisher) PromoteTag

func (p *Publisher) PromoteTag(ctx context.Context, promo suggest.Promotion, actor string) (int, error)

PromoteTag executes an approved tag promotion (tasks/044): every Work carrying the tag gains the controlled subject (with its authority labels and hierarchy), its editorial lcat:tag is retracted, and the alias grain records lcat:tagAlias so the projector suppresses the residual feed tag where the term is present and future entries auto-suggest the term. Returns the number of Works rewritten.

func (*Publisher) PublishApproved

func (p *Publisher) PublishApproved(ctx context.Context, actor string) (Result, error)

PublishApproved drains the approved-unpublished worklist: per Work, all its approved terms land in one grain mutation; each mutation stamps the queue items with the resulting grain ETag and writes an audit entry.

type Result

type Result struct {
	Published int      `json:"published"`
	Skipped   int      `json:"skipped"`
	Paths     []string `json:"paths,omitempty"`
}

Result summarizes one publish run.

Jump to

Keyboard shortcuts

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