Documentation
¶
Overview ¶
Package flow provides event-driven, durable, distributed work on PostgreSQL.
Core model ¶
Flow has a small set of foundational concepts:
- Command is an immutable, typed definition of work. Its argument and result types are part of the Go API, while its stable name and version are part of durable identity.
- A worker, registered with Handle, implements one command definition. Each invocation receives a fresh Work: the attempt-local scope for one claimed command, containing typed arguments, durable identity, event inputs, and the decision being built. Work is neither the whole Run nor the immutable Command definition.
- Event is an immutable, typed definition of a durable fact. An event name describes the fact kind; its key carries domain and generation identity.
- Run is one durable command graph and its consistency boundary. It owns the root command, staged descendants, exact event inputs, attempts, and ordered journal.
- Runtime is both a Client for durable operations and, when passed to Runtime.Run, a processor for locally registered workers.
The usual shape is:
Command definition --Enqueue--> Run Runtime.Run -----------claim----> attempt-local Work Work ----------------Enqueue----> staged child command Work -----------------Emit------> staged application event Event + WaitFor ----------------> runnable command
Root run starts are durable and asynchronous: Enqueue always enqueues rather than calling a worker inline. Inside a worker, Enqueue and Emit build one typed decision in memory. That decision, the worker result, and an optional short same-database WithCommit callback settle atomically after the attempt fence is rechecked.
Exact event gates provide durable sequencing and all-of joins without consuming a worker or database connection while waiting. Matching is scoped to one run and uses the tuple (event name, event key). Values for the current command's declared gates are materialized before invocation and read from memory with GetEventValue.
Definitions, clients, and processing ¶
Definitions are immutable values and registration is runtime-local; Flow keeps no process-global registry. A Client is a sealed durable-operation capability implemented by Runtime and its transaction-scoped client. New validates the explicitly migrated schema and starts no goroutines, so a Runtime that is not passed to Run remains a lightweight client for API and publisher processes.
Runtime.Run processes compatible commands with bounded concurrency, renewable leases, settlement fencing, and anonymous takeover across replicas. Renewal calls are internally time-bounded and skip rows held by another Flow transaction so one settlement cannot delay unrelated attempts. A process-local watchdog conservatively cancels attempts whose last known lease window expires; PostgreSQL attempt ID and lease-token fencing remains the durable ownership authority.
Handler invocation is at-least-once. Durable PostgreSQL progression is fenced so that only the current attempt can settle. Application handlers should therefore use stable idempotency keys for remote effects rather than interpreting fenced settlement as exactly-once handler invocation.
Run identity and history ¶
A stable non-empty run key is permanently idempotent by default. WithLiveKey instead gives at most one non-terminal run for a command definition and key; after that run becomes terminal, a new generation may start with the same key. GetCurrentRun resolves the current non-terminal generation when an external caller knows the domain key but not its exact RunID. Terminal generations remain durable history.
Flow retains journal, payload, and terminal data indefinitely and exposes no pruning API. Inspection, history, and trace APIs read durable state without invoking application code. GetResult reads one typed successful command result by run and command key directly from its projection, without replaying the run journal.
Choosing command boundaries ¶
A command should mark an independent retry, side-effect, isolation, queue, timeout, external-wait, or parallelism boundary—not every deterministic business-logic step. Keep causally related commands in one run, but use separate runs for independent bulk items because one run is a serialized semantic aggregate.
Large fan-outs should be chunked into bounded command batches and large all-of inputs reduced through hierarchical joins. Parent-produced data belongs directly in child arguments; large or sensitive values should stay in application storage behind stable references.
Transactions, events, and operations ¶
WithCommit is intended for short same-database writes and must not contain remote calls. Caller-owned transactions should also be short because a run lock remains held until the caller commits or rolls back. Create exactly one TransactionClient with Runtime.InTx for each caller transaction, perform Flow writes first, call TransactionClient.BeginApplicationWrites, and then perform application row locks/writes. The client is non-concurrent, does not own the transaction, and must not outlive it.
External callers record run-scoped events with Event.Deliver, which provides deliberately detached ingress to a known run, including from an active worker; passing Runtime.InTx joins it to caller-owned application writes. Same-run worker events should normally use staged Emit so they commit atomically with the worker result. External code that knows a domain key rather than an exact run ID may compose GetCurrentRun with Event.Deliver, handling the ordinary race in which the selected run settles before delivery. Event definitions should name stable fact kinds; deterministic keys should carry entity and generation identity.
Command.ReplaceCurrentRun atomically cancels an exact expected live-key generation and creates a distinct successor. Retries can rediscover a declaration-equivalent successor only after the current run ID differs from the expected predecessor.
Positive fractional public durations are rounded upward to a whole millisecond before durable fingerprints or rows are produced. Stored and decoded durations remain strictly exact milliseconds.
Observer delivery is bounded and best-effort. Observers must return promptly and should honor context cancellation; a blocked or failed observer never changes durable run correctness or prevents runtime shutdown.
The current v0.x line supports Go 1.26 and PostgreSQL 17 and 18. Published migrations are immutable and upgrades are forward-only. During v0.x, intentional Go API changes may be described in release notes.
Index ¶
- Constants
- Variables
- func CancelCommand(ctx context.Context, c Client, id CommandID, reason string) error
- func CancelRun(ctx context.Context, c Client, id RunID, reason string) error
- func Emit[W, T any](work *Work[W], event Event[T], key string, payload T) error
- func GetEventValue[W, T any](work *Work[W], event Event[T], key string) (T, bool, error)
- func GetResult[A, R any](ctx context.Context, c Client, id RunID, key string, cmd Command[A, R]) (R, bool, error)
- func Migrate(ctx context.Context, db *pgkit.DB, opts ...MigrateOption) error
- func MigrationFS(opts ...MigrateOption) (fs.FS, error)
- func Permanent(err error) error
- func ResultOf[A, R any](trace RunTrace, key string, cmd Command[A, R]) (R, error)
- func RetryAfter(delay time.Duration, err error) error
- func WithSchema(schema string) schemaOption
- type AttemptID
- type Client
- type Command
- func (cmd Command[A, R]) Enqueue(ctx context.Context, client Client, key string, args A, opts ...RunOption) (Run, error)
- func (c Command[A, R]) Name() string
- func (c Command[A, R]) Queue() string
- func (cmd Command[A, R]) ReplaceCurrentRun(ctx context.Context, client Client, expected RunID, key string, args A, ...) (ReplaceRunResult, error)
- func (c Command[A, R]) Version() int
- type CommandFailure
- type CommandID
- type CommandInfo
- type CommandOption
- type CommandStatus
- type Commit
- type Error
- type Event
- type EventID
- type EventRef
- type Failure
- type HistoryEntry
- type HistoryKind
- type HistoryOption
- type JournalEntryID
- type JournalPosition
- type KeyScope
- type KeyedHistoryEntry
- type KeyedHistoryFilter
- type KeyedHistoryPage
- type LiveWork
- type LiveWorkFilter
- type LiveWorkPage
- type MigrateOption
- type Node
- type None
- type NopObserver
- type Observation
- type ObservationKind
- type Observer
- type Option
- func WithMaxCommandsPerRun(max int) Option
- func WithNotifications(enabled bool) Option
- func WithObserver(observer Observer) Option
- func WithPollInterval(interval time.Duration) Option
- func WithQueueConcurrency(queue string, concurrency int) Option
- func WithShutdownGrace(grace time.Duration) Option
- func WithWorkerConcurrency(concurrency int) Option
- type QueueDepth
- type QueueState
- type Registration
- type ReplaceRunResult
- type RetryPolicy
- type Run
- type RunFilter
- type RunID
- type RunOption
- func WaitFor(event EventRef, key string) RunOption
- func WithFailFast(enabled bool) RunOption
- func WithLiveKey() RunOption
- func WithMetadata(metadata map[string]string) RunOption
- func WithRunDeadline(deadline time.Duration) RunOption
- func WithStartDelay(delay time.Duration) RunOption
- func Within(duration time.Duration) RunOption
- func WithoutRunDeadline() RunOption
- type RunPage
- type RunStatus
- type RunTrace
- type Runtime
- type SchemaStatus
- type TerminalStatus
- type TraceAttempt
- type TraceCommand
- type TraceEvent
- type TraceEventWait
- type TraceOption
- type TransactionClient
- type Tx
- type Work
- type WorkerOption
Constants ¶
const ( // MaxReadKeys bounds every by-keys batch read before duplicate removal. MaxReadKeys = store.MaxReadKeys // DefaultReadPageSize is used when a by-key read filter has PageSize zero. DefaultReadPageSize = 100 // MaxReadPageSize is the largest public by-key read page. MaxReadPageSize = 1000 )
const ( RunStatusRunning RunStatus = "running" RunStatusFailing RunStatus = "failing" RunStatusSucceeded RunStatus = "succeeded" RunStatusFailed RunStatus = "failed" RunStatusCancelled RunStatus = "cancelled" RunStatusExpired RunStatus = "expired" CommandStatusPending CommandStatus = "pending" CommandStatusReady CommandStatus = "ready" CommandStatusRunning CommandStatus = "running" CommandStatusRetryWait CommandStatus = "retry_wait" CommandStatusSucceeded CommandStatus = "succeeded" CommandStatusFailed CommandStatus = "failed" CommandStatusCancelled CommandStatus = "cancelled" CommandStatusExpired CommandStatus = "expired" QueueStateReady QueueState = "ready" QueueStateRetryWait QueueState = "retry_wait" QueueStateRunning QueueState = "running" KeyScopePermanent KeyScope = "permanent" KeyScopeLive KeyScope = "live" TerminalStatusSucceeded TerminalStatus = "succeeded" TerminalStatusFailed TerminalStatus = "failed" TerminalStatusCancelled TerminalStatus = "cancelled" TerminalStatusExpired TerminalStatus = "expired" // Short names remain source-compatible aliases for terminal command states. StatusSucceeded = CommandStatusSucceeded StatusFailed = CommandStatusFailed StatusCancelled = CommandStatusCancelled StatusExpired = CommandStatusExpired )
Variables ¶
var ( ErrNotFound = flowerr.ErrNotFound ErrConflict = flowerr.ErrConflict ErrInvalid = flowerr.ErrInvalid ErrInvalidState = flowerr.ErrInvalidState ErrTerminal = flowerr.ErrTerminal ErrLeaseLost = flowerr.ErrLeaseLost ErrPayloadTooLarge = flowerr.ErrPayloadTooLarge ErrClosed = flowerr.ErrClosed ErrSchema = flowerr.ErrSchema )
Functions ¶
func CancelCommand ¶
func Emit ¶
Emit stages an application event in a worker decision. It performs no database work and becomes durable only when the enclosing decision settles successfully.
func GetEventValue ¶
GetEventValue returns the typed value attached to an exact event gate materialized for the current command. The value is already in memory when the worker starts; this function does not wait or query the database. found=false reports ordinary absence without poisoning the worker decision.
func GetResult ¶ added in v0.3.2
func GetResult[A, R any]( ctx context.Context, c Client, id RunID, key string, cmd Command[A, R], ) (R, bool, error)
GetResult reads the typed result projection for one command key without loading or replaying the run trace. found=false means that the run exists but the command has no successful result yet, including when the command is absent, pending, running, or terminal without success. A stored command with a different name or version returns ErrConflict.
func Migrate ¶
Migrate applies every unapplied embedded Flow migration in its own run-serialized transaction and verifies all previously recorded checksums before writing.
func MigrationFS ¶
func MigrationFS(opts ...MigrateOption) (fs.FS, error)
MigrationFS returns schema-rendered SQL files for an external transactional migration runner. Each file records the same checksum and compatibility row as Migrate, so CheckSchema accepts either application path.
func Permanent ¶
Permanent classifies an application error as terminal for the current command delivery.
func RetryAfter ¶
RetryAfter classifies an error as retryable after a requested delay. The command's immutable retry bounds still apply.
func WithSchema ¶
func WithSchema(schema string) schemaOption
WithSchema places Flow's fixed flow_ tables in a validated PostgreSQL schema. The default is public. Runtime options adopt the same value in the runtime phase; table names always retain their flow_ prefix.
Types ¶
type Client ¶
type Client interface {
// contains filtered or unexported methods
}
Client is a sealed capability implemented by Runtime and transaction-scoped clients. Applications pass it directly to durable operations; they cannot construct another implementation that bypasses Flow's durable operations.
type Command ¶
type Command[A, R any] struct { // contains filtered or unexported fields }
func DefineCommand ¶
func DefineCommand[A, R any](name string, version int, opts ...CommandOption) Command[A, R]
func (Command[A, R]) Queue ¶ added in v0.3.3
Queue returns the command's normalized delivery queue. It returns an empty string for a zero or invalid command definition.
func (Command[A, R]) ReplaceCurrentRun ¶ added in v0.3.0
func (cmd Command[A, R]) ReplaceCurrentRun( ctx context.Context, client Client, expected RunID, key string, args A, reason string, opts ...RunOption, ) (ReplaceRunResult, error)
ReplaceCurrentRun atomically cancels expected and creates a distinct live-key successor. If expected is stale, an equivalent already-committed successor is returned with Replaced=false; a different current declaration conflicts and no state is changed.
type CommandFailure ¶
type CommandFailure = Failure
type CommandInfo ¶
type CommandOption ¶
type CommandOption interface {
// contains filtered or unexported methods
}
func WithQueue ¶
func WithQueue(queue string) CommandOption
func WithRetry ¶
func WithRetry(policy RetryPolicy) CommandOption
func WithTimeout ¶
func WithTimeout(timeout time.Duration) CommandOption
type CommandStatus ¶
type CommandStatus string
type Commit ¶
type Commit[A, R any] struct { Args A Result R Info CommandInfo }
type Error ¶
Error adds safe structured context to a sentinel category. Its fields must contain identifiers and bounded reasons only, never payloads, SQL, secrets, or lease tokens.
type Event ¶
type Event[T any] struct { // contains filtered or unexported fields }
func DefineEvent ¶
func (Event[T]) Deliver ¶
func (event Event[T]) Deliver(ctx context.Context, client Client, target RunID, key string, payload T) error
Deliver records an event in a known run, including from inside an active worker attempt. Delivery is detached from that attempt: pass a Runtime.InTx client to join a caller-owned transaction. Once committed, the event is not retracted if the source attempt fails or retries; equivalent repeats retain ordinary event idempotency. Use Emit(work, ...) for same-run events that must settle atomically with the worker decision.
type HistoryEntry ¶
type HistoryEntry struct {
RunID RunID
Position JournalPosition
EntryID JournalEntryID
Kind HistoryKind
RecordedAt time.Time
CausationPosition *JournalPosition
CommandID CommandID
AttemptID AttemptID
EventID EventID
EventNamespace string
EventName string
EventKey string
EventClass string
TerminalStatus TerminalStatus
Body json.RawMessage
BodyHash string
}
func History ¶
func History(ctx context.Context, c Client, id RunID, opts ...HistoryOption) ([]HistoryEntry, error)
type HistoryKind ¶
type HistoryKind string
const ( HistoryRunStarted HistoryKind = "execution_started" HistoryRunFailing HistoryKind = "execution_failing" HistoryCommandCreated HistoryKind = "command_created" HistoryAttemptStarted HistoryKind = "attempt_started" HistoryAttemptConcluded HistoryKind = "attempt_concluded" HistoryEventRecorded HistoryKind = "event_recorded" )
type HistoryOption ¶
type HistoryOption interface {
// contains filtered or unexported methods
}
func HistoryAfter ¶
func HistoryAfter(position JournalPosition) HistoryOption
func HistoryLimit ¶
func HistoryLimit(limit int) HistoryOption
type JournalEntryID ¶
type JournalEntryID string
type JournalPosition ¶
type JournalPosition uint64
type KeyedHistoryEntry ¶
type KeyedHistoryEntry struct {
DefinitionName string
RunKey string
KeyScope KeyScope
HistoryEntry
}
KeyedHistoryEntry is a history entry carrying its run's identity.
type KeyedHistoryFilter ¶
KeyedHistoryFilter selects bounded retained history for exact run keys. Cursor values are opaque and may be reused only with the same Keys filter.
type KeyedHistoryPage ¶
type KeyedHistoryPage struct {
Entries []KeyedHistoryEntry
NextCursor string
}
KeyedHistoryPage contains one bounded page and an opaque cursor for the next page. NextCursor is empty when no later row was observed.
func ListHistoryByKeys ¶
func ListHistoryByKeys(ctx context.Context, c Client, filter KeyedHistoryFilter) (KeyedHistoryPage, error)
ListHistoryByKeys returns one bounded retained-history page for every run that ever held one of filter.Keys. Rows are ordered by key, definition, run creation, run ID, and journal position. Journal order is preserved within each run. Transaction-scoped clients use the caller's transaction and observe their uncommitted writes.
type LiveWork ¶
type LiveWork struct {
RunID RunID
DefinitionName string
RunKey string
KeyScope KeyScope
RunStatus RunStatus
CommandID CommandID
CommandKey string
CommandName string
Queue string
QueueState QueueState
NextRunAt time.Time
LeaseOwner string
LeaseExpiresAt *time.Time
AttemptOrdinal int
CommandCreatedAt time.Time
}
LiveWork is one queued (or leased) command of a non-terminal run, carrying the run's identity. It is the batch, key-addressed read for consumers that decorate their own domain rows with dispatch state, without touching Flow's tables.
type LiveWorkFilter ¶
LiveWorkFilter selects bounded queued work for exact run keys. Cursor values are opaque and may be reused only with the same Keys filter.
type LiveWorkPage ¶
LiveWorkPage contains one bounded page and an opaque cursor for the next page. NextCursor is empty when no later row was observed.
func ListLiveWork ¶
func ListLiveWork(ctx context.Context, c Client, filter LiveWorkFilter) (LiveWorkPage, error)
ListLiveWork returns one bounded page of queued commands for non-terminal runs whose run key is in filter.Keys. Rows are ordered by key, definition, run creation, run ID, and command ID. An ordinary client does not provide a cross-page snapshot; a transaction-scoped client uses the caller's transaction and observes its uncommitted writes.
type MigrateOption ¶
type MigrateOption interface {
// contains filtered or unexported methods
}
MigrateOption is a sealed migration and schema-inspection option.
type Node ¶
type Node struct {
// contains filtered or unexported fields
}
Node is an ephemeral builder for a command staged by a worker decision. It is valid only for the duration of that decision.
type NopObserver ¶
type NopObserver struct{}
func (NopObserver) Observe ¶
func (NopObserver) Observe(context.Context, Observation)
type Observation ¶
type Observation struct {
Kind ObservationKind
Operation string
Outcome string
RunID RunID
CommandID CommandID
CommandKey string
Name string
Version int
Queue string
Worker string
Count int64
Duration time.Duration
OccurredAt time.Time
}
Observation contains only bounded operational metadata. It intentionally has no payload, result, raw SQL, connection, or lease token field.
type ObservationKind ¶
type ObservationKind string
const ( ObservationRun ObservationKind = "run" ObservationCommand ObservationKind = "command" ObservationEvent ObservationKind = "event" ObservationAttempt ObservationKind = "attempt" ObservationClaim ObservationKind = "claim" ObservationLease ObservationKind = "lease" ObservationWait ObservationKind = "wait" ObservationRuntime ObservationKind = "runtime" )
type Observer ¶
type Observer interface {
// Observe receives best-effort operational metadata. Implementations must
// return promptly and should stop work when ctx is cancelled. Flow never
// waits indefinitely for an observer during runtime shutdown.
Observe(context.Context, Observation)
}
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option is a sealed runtime configuration option.
func WithMaxCommandsPerRun ¶ added in v0.3.0
WithMaxCommandsPerRun sets the command ceiling copied into each newly created run. Zero explicitly disables the ceiling.
func WithNotifications ¶
WithNotifications enables or disables transactional PostgreSQL wake hints. It defaults to enabled. Polling always remains active and is the correctness path, so disabling notifications is suitable for transaction-pooling proxies and deliberately poll-only deployments.
func WithObserver ¶
WithObserver installs the optional no-op-by-default operational observer.
func WithPollInterval ¶
WithPollInterval configures the fallback scheduler and maintenance poll.
func WithQueueConcurrency ¶
WithQueueConcurrency optionally gives one queue lane a smaller process-local handler limit. The lane still shares the runtime's global worker capacity.
func WithShutdownGrace ¶
WithShutdownGrace configures how long Run waits before interrupting handlers.
func WithWorkerConcurrency ¶
WithWorkerConcurrency bounds command handlers running in this process.
type QueueDepth ¶
type QueueDepth struct {
Queue string
Ready int64
Delayed int64
Running int64
OldestReadyFor time.Duration
}
QueueDepth is a point-in-time operational snapshot of one queue lane. Ready commands are deliverable now, Delayed commands wait out a retry backoff or start delay, and Running commands hold an attempt lease. OldestReadyFor is how long the oldest deliverable command has been ready; a growing value with stable Ready means no compatible worker is claiming the lane.
func GetQueueDepth ¶
GetQueueDepth reports the lane's current deliverable, scheduled, and leased command counts. It reads operational delivery state, not application events: the counts change as attempts are claimed and settled.
type QueueState ¶
type QueueState string
type Registration ¶
type Registration interface {
// contains filtered or unexported methods
}
func Handle ¶
func Handle[A, R any]( cmd Command[A, R], worker func(context.Context, *Work[A]) (R, error), opts ...WorkerOption[A, R], ) Registration
type ReplaceRunResult ¶ added in v0.3.0
ReplaceRunResult reports the current run after an atomic live-key replacement attempt. Replaced is true only for the call that cancelled the expected predecessor and created Run.
type RetryPolicy ¶
type RetryPolicy = retrypolicy.PublicPolicy
RetryPolicy is immutable declarative data. Its fields are sealed so durable behavior can only be constructed through validated builders.
func Attempts ¶
func Attempts(max int) RetryPolicy
func RetryFor ¶
func RetryFor(maxElapsed time.Duration) RetryPolicy
type Run ¶ added in v0.3.0
type Run struct {
ID RunID
Type string
Version int
Key string
RootCommandID CommandID
Status RunStatus
FailFast bool
MaxCommands int
CommandCount int
OpenCommands int
DeadlineAt *time.Time
Failure *Failure
CreatedAt time.Time
UpdatedAt time.Time
StatusAt time.Time
FinishedAt *time.Time
Metadata json.RawMessage
Created bool
}
Run is a durable run state snapshot. Enqueue returns the snapshot as of durable acceptance; GetRun, AwaitRun, and other inspection reads return the current or final state. Created reports whether the producing Enqueue call created the run; it is false for an idempotent rediscovery and always false on inspection reads.
func AwaitRun ¶ added in v0.3.0
AwaitRun polls the durable run row until it reaches a terminal state or ctx ends. It consumes no command worker, connection while waiting, or durable lease.
func GetCurrentRun ¶ added in v0.3.0
GetCurrentRun finds the one non-terminal run currently holding a live-scoped key for the definition, if any. Live keys admit many settled runs per key over time but at most one live holder; this is the lookup that matches that invariant. found=false means no live holder — settled runs with the key may still exist.
type RunFilter ¶ added in v0.3.0
type RunFilter struct {
Type string
KeyPrefix string
Statuses []RunStatus
CreatedAfter *time.Time
CreatedBefore *time.Time
Metadata map[string]string
PageSize int
Cursor string
}
RunFilter is the bounded, indexed filter supported by ListRuns. CreatedBefore is exclusive and CreatedAfter is inclusive.
type RunOption ¶ added in v0.3.0
type RunOption interface {
// contains filtered or unexported methods
}
RunOption is a sealed command run option.
func WaitFor ¶
WaitFor gates a root command on one exact application event inside the run it creates. Multiple waits are AND conditions. Worker decisions use the matching Node.WaitFor method.
func WithFailFast ¶
func WithLiveKey ¶
func WithLiveKey() RunOption
WithLiveKey scopes the run key to live runs: while a running or failing run holds the key, Enqueue rediscovers it without comparing start identity — a silent, queue-style dedupe no-op — and once that run reaches a terminal status the key is released for a new start. Live-keyed starts therefore give at-most-one live run per key, not at-most-one run ever. Requires a non-empty key.
func WithMetadata ¶
func WithRunDeadline ¶ added in v0.3.0
func WithStartDelay ¶
WithStartDelay schedules a run's root command to become deliverable after the delay instead of immediately, mirroring Delay for sub-commands.
func Within ¶
Within bounds how long a direct root command waits for its exact events. It is valid only when the same start declares at least one WaitFor option.
func WithoutRunDeadline ¶ added in v0.3.0
func WithoutRunDeadline() RunOption
type RunTrace ¶ added in v0.3.0
type RunTrace struct {
Run Run
Commands []TraceCommand
Events []TraceEvent
History []HistoryEntry
}
func Trace ¶
Trace reconstructs one run and overlays its current operational projections. A Runtime client gets one Flow-owned Repeatable Read snapshot. A transaction-scoped client inherits the caller's isolation; callers needing a coherent multi-statement snapshot must use Repeatable Read or Serializable.
type Runtime ¶
type Runtime struct {
// contains filtered or unexported fields
}
Runtime is a configured PostgreSQL-backed Flow client. New starts no goroutines; run operations are usable before background processing is started.
func New ¶
New validates configuration and schema compatibility without migrating or starting background work.
func (*Runtime) InTx ¶
func (r *Runtime) InTx(tx pgx.Tx) *TransactionClient
InTx returns a transaction-scoped client. Call it once at the transaction boundary and thread the returned value through every Flow operation in that transaction; repeated calls for the same pgx.Tx create independent order guards and are invalid usage.
func (*Runtime) Register ¶
func (r *Runtime) Register(definitions ...Registration) error
type SchemaStatus ¶
type SchemaStatus struct {
Schema string
CurrentVersion int
MinReaderVersion int
MinWriterVersion int
Compatible bool
AppliedAt time.Time
}
SchemaStatus describes the verified migration and compatibility state.
func CheckSchema ¶
func CheckSchema(ctx context.Context, db *pgkit.DB, opts ...MigrateOption) (SchemaStatus, error)
CheckSchema verifies migration checksums, reader/writer compatibility, and the fixed Flow table inventory without changing the database.
type TerminalStatus ¶
type TerminalStatus string
type TraceAttempt ¶
type TraceCommand ¶
type TraceCommand struct {
ID CommandID
Key string
Name string
Version int
ParentCommandID CommandID
Required bool
State CommandStatus
Args json.RawMessage
Result json.RawMessage
Queue string
InitialDelay time.Duration
BudgetStartedAt *time.Time
NextAttemptAt *time.Time
Within time.Duration
Waits []TraceEventWait
CreatedPosition JournalPosition
TerminalPosition *JournalPosition
Failure *Failure
LastError *Failure
UnsatisfiedWaits int
AttemptOrdinal int
ConsumedAttempts int
WaitStartedAt *time.Time
WaitDeadlineAt *time.Time
DeliveryState QueueState
LeaseOwner string
LeaseStartedAt *time.Time
LeaseExpiresAt *time.Time
CreatedAt time.Time
UpdatedAt time.Time
StatusAt time.Time
FinishedAt *time.Time
Attempts []TraceAttempt
}
type TraceEvent ¶
type TraceEvent struct {
ID EventID
Position JournalPosition
Namespace string
Name string
Key string
Class string
TerminalStatus TerminalStatus
CommandID CommandID
RecordedAt time.Time
CausationPosition *JournalPosition
Body json.RawMessage
}
type TraceEventWait ¶
type TraceEventWait struct {
Name string
Key string
SatisfiedPosition *JournalPosition
}
type TraceOption ¶
type TraceOption interface {
// contains filtered or unexported methods
}
type TransactionClient ¶ added in v0.3.0
type TransactionClient struct {
// contains filtered or unexported fields
}
TransactionClient joins Flow operations to one caller-owned PostgreSQL transaction. Create it exactly once per pgx.Tx, use Flow operations before application row locks/writes, and do not use it concurrently or after the transaction ends. Flow never commits or rolls back the transaction.
func (*TransactionClient) BeginApplicationWrites ¶ added in v0.3.0
func (c *TransactionClient) BeginApplicationWrites() error
BeginApplicationWrites marks the irreversible boundary after which this client rejects every Flow write or run-locking operation before issuing SQL. It does not execute SQL or prove that the caller has not already taken application locks.
type Work ¶
type Work[A any] struct { Args A // contains filtered or unexported fields }
Work is the attempt-local command scope passed to a worker. It represents one invocation of one claimed command, not the whole Run and not the immutable Command definition. Args contains the command's typed arguments; Info returns its durable run, command, and attempt identity. The private scope backs Enqueue, Emit, and GetEventValue for the decision being built by this invocation.
A fresh Work is created for every command attempt. It is valid only during the worker call and must not be retained or used concurrently.
func (*Work[A]) Info ¶
func (w *Work[A]) Info() CommandInfo
Info returns immutable identity and timing information for the claimed command and its current attempt.
type WorkerOption ¶
type WorkerOption[A, R any] interface { // contains filtered or unexported methods }
func WithCommit ¶
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
agent
command
|
|
|
direct
command
|
|
|
fanout
command
|
|
|
monitor
command
|
|
|
pipeline
command
Command pipeline demonstrates when to split work into durable commands: independent queues, retryable side effects, an external wait, an all-of join, and a dynamic successor.
|
Command pipeline demonstrates when to split work into durable commands: independent queues, retryable side effects, an external wait, an all-of join, and a dynamic successor. |
|
Package flowtest provides database-free helpers backed by Flow's production codecs and deterministic engine primitives.
|
Package flowtest provides database-free helpers backed by Flow's production codecs and deterministic engine primitives. |
|
replaytest
Package replaytest provides PostgreSQL-backed assertions for verifying that Flow's journal replay agrees with its live projections.
|
Package replaytest provides PostgreSQL-backed assertions for verifying that Flow's journal replay agrees with its live projections. |
|
internal
|
|
|
canonical
Package canonical provides the deterministic JSON representation used by Flow's durable identities.
|
Package canonical provides the deterministic JSON representation used by Flow's durable identities. |
|
durable
Package durable contains validation shared by public construction and the PostgreSQL store for values whose durable representation is narrower than their Go representation.
|
Package durable contains validation shared by public construction and the PostgreSQL store for values whose durable representation is narrower than their Go representation. |
|
fault
Package fault defines named internal fault points used by integration and crash-recovery tests.
|
Package fault defines named internal fault points used by integration and crash-recovery tests. |
|
replay
Package replay folds retained journal entries into settled orchestration projections.
|
Package replay folds retained journal entries into settled orchestration projections. |
|
store/journalcodec
Package journalcodec owns version validation for internal journal bodies.
|
Package journalcodec owns version validation for internal journal bodies. |
|
testengine
Package testengine is the private bridge between flow's production deterministic recorders and the public database-free flowtest package.
|
Package testengine is the private bridge between flow's production deterministic recorders and the public database-free flowtest package. |
|
testpg
Package testpg creates isolated PostgreSQL schemas for integration tests.
|
Package testpg creates isolated PostgreSQL schemas for integration tests. |
|
uuid
Package uuid generates Flow's durable identifiers and re-exports the identifier type so identifier-producing packages depend on one policy.
|
Package uuid generates Flow's durable identifiers and re-exports the identifier type so identifier-producing packages depend on one policy. |
|
tools
|
|
|
db
command
Command db manages the disposable PostgreSQL database used by Flow's tests.
|
Command db manages the disposable PostgreSQL database used by Flow's tests. |