Documentation
¶
Index ¶
- func Initialize(db *sql.DB, schema string) error
- func RunInTx(ctx context.Context, db *sql.DB, fn func(*sql.Tx) error) (err error)
- type Option
- type PostgresStorage
- func (s *PostgresStorage) DeleteState(ctx context.Context, id string) error
- func (s *PostgresStorage) DeleteStateTx(ctx context.Context, tx *sql.Tx, id string) error
- func (s *PostgresStorage) EnsureSchema(ctx context.Context) error
- func (s *PostgresStorage) GenerateSchema() string
- func (s *PostgresStorage) ListDue(ctx context.Context, before time.Time, limit int) ([]string, error)
- func (s *PostgresStorage) ListIDs(ctx context.Context, opts workflow.ListOptions) ([]string, error)
- func (s *PostgresStorage) LoadState(ctx context.Context, id string) (workflow.Marking, map[string]any, error)
- func (s *PostgresStorage) LoadStateTx(ctx context.Context, tx *sql.Tx, id string) (workflow.Marking, map[string]any, error)
- func (s *PostgresStorage) LoadVersionedState(ctx context.Context, id string) (workflow.Marking, map[string]any, int64, error)
- func (s *PostgresStorage) SaveState(ctx context.Context, id string, marking workflow.Marking, ...) error
- func (s *PostgresStorage) SaveStateTx(ctx context.Context, tx *sql.Tx, id string, marking workflow.Marking, ...) error
- func (s *PostgresStorage) SaveVersionedState(ctx context.Context, id string, marking workflow.Marking, ...) (int64, error)
- func (s *PostgresStorage) SaveVersionedStateInTx(ctx context.Context, id string, marking workflow.Marking, ...) (int64, error)
- func (s *PostgresStorage) SaveVersionedStateInTxWithDue(ctx context.Context, id string, marking workflow.Marking, ...) (int64, error)
- func (s *PostgresStorage) SaveVersionedStateTx(ctx context.Context, tx *sql.Tx, id string, marking workflow.Marking, ...) (int64, error)
- func (s *PostgresStorage) SaveVersionedStateWithDue(ctx context.Context, id string, marking workflow.Marking, ...) (int64, error)
- type SQLiteStorage
- func (s *SQLiteStorage) DeleteState(ctx context.Context, id string) error
- func (s *SQLiteStorage) DeleteStateTx(ctx context.Context, tx *sql.Tx, id string) error
- func (s *SQLiteStorage) EnsureSchema(ctx context.Context) error
- func (s *SQLiteStorage) GenerateSchema() string
- func (s *SQLiteStorage) ListDue(ctx context.Context, before time.Time, limit int) ([]string, error)
- func (s *SQLiteStorage) ListIDs(ctx context.Context, opts workflow.ListOptions) ([]string, error)
- func (s *SQLiteStorage) LoadState(ctx context.Context, id string) (workflow.Marking, map[string]any, error)
- func (s *SQLiteStorage) LoadStateTx(ctx context.Context, tx *sql.Tx, id string) (workflow.Marking, map[string]any, error)
- func (s *SQLiteStorage) LoadVersionedState(ctx context.Context, id string) (workflow.Marking, map[string]any, int64, error)
- func (s *SQLiteStorage) SaveState(ctx context.Context, id string, marking workflow.Marking, ...) error
- func (s *SQLiteStorage) SaveStateTx(ctx context.Context, tx *sql.Tx, id string, marking workflow.Marking, ...) error
- func (s *SQLiteStorage) SaveVersionedState(ctx context.Context, id string, marking workflow.Marking, ...) (int64, error)
- func (s *SQLiteStorage) SaveVersionedStateInTx(ctx context.Context, id string, marking workflow.Marking, ...) (int64, error)
- func (s *SQLiteStorage) SaveVersionedStateInTxWithDue(ctx context.Context, id string, marking workflow.Marking, ...) (int64, error)
- func (s *SQLiteStorage) SaveVersionedStateTx(ctx context.Context, tx *sql.Tx, id string, marking workflow.Marking, ...) (int64, error)
- func (s *SQLiteStorage) SaveVersionedStateWithDue(ctx context.Context, id string, marking workflow.Marking, ...) (int64, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Initialize ¶
Initialize executes the schema generated by GenerateSchema. It's a convenience helper for development and testing. For production, it's recommended to use a proper migration tool.
Initialize creates the table only; it does not migrate a pre-existing table or create the due index. Use EnsureSchema for the M4 due index (ListDue / Manager.FireDue), which is idempotent on both fresh and pre-existing tables.
func RunInTx ¶ added in v0.8.0
RunInTx runs fn inside a database transaction. It commits if fn returns nil and rolls back if fn returns an error or panics (the panic is re-raised after the rollback). It lets callers persist workflow state and append history atomically, so a crash mid-transition cannot leave the state and the audit log disagreeing:
err := storage.RunInTx(ctx, db, func(tx *sql.Tx) error {
if err := store.SaveStateTx(ctx, tx, id, places, data); err != nil {
return err
}
return hist.SaveTransitionTx(ctx, tx, record)
})
The same *sql.DB must back both stores for their writes to share the transaction.
Note: composing a versioned save manually here (via SaveVersionedStateTx) does NOT maintain the due index — the storage-level Tx saves leave the due column untouched. For a timed definition, drive saves through the Manager, or use SaveVersionedStateInTxWithDue, so the due index commits atomically with state.
Types ¶
type Option ¶
type Option func(*config)
Option configures a SQL-backed storage implementation (SQLite or Postgres).
func WithContextColumn ¶ added in v0.8.0
WithContextColumn sets the name of the column that persists the workflow's full context map as a single JSON document. Default: "context".
Pass an empty name to disable it (e.g. for a pre-existing table without the column) — then only the keys configured via WithCustomFields survive a save/load round-trip and every other context key is dropped on save.
func WithCustomFields ¶
WithCustomFields defines the schema for additional application-specific data. The map key is the key used in the workflow's context map; the value is the full SQL column definition (e.g. "title TEXT", "amount INTEGER NOT NULL").
func WithDueColumn ¶ added in v0.8.0
WithDueColumn sets the name of the column that stores each instance's next-due time — the maintained index behind DueStorage.ListDue and Manager.FireDue. Default: "due_at".
Pass an empty name to disable the due index (e.g. for a pre-existing table you do not want to migrate). The backend then no longer advertises DueStorage, so the Manager keeps working but a fleet timer scan is unavailable for it.
func WithIDColumn ¶
WithIDColumn sets the name of the column used to store the workflow ID. Default: "id".
func WithStateColumn ¶
WithStateColumn sets the name of the column used to store the workflow's current places (state). Default: "state".
func WithTable ¶
WithTable sets the name of the table used to store workflow state. Default: "workflow_states".
func WithVersionColumn ¶ added in v0.8.0
WithVersionColumn sets the name of the optimistic-concurrency version column. Default: "version".
type PostgresStorage ¶ added in v0.8.0
type PostgresStorage struct {
// contains filtered or unexported fields
}
PostgresStorage is a PostgreSQL-backed implementation of workflow.Storage and workflow.VersionedStorage. It mirrors SQLiteStorage but uses PostgreSQL syntax ($N placeholders and INSERT ... ON CONFLICT upserts).
Use it with any database/sql driver that speaks PostgreSQL; the pgx stdlib adapter is recommended:
import _ "github.com/jackc/pgx/v5/stdlib"
db, _ := sql.Open("pgx", dsn)
store, _ := storage.NewPostgresStorage(db)
_ = storage.Initialize(db, store.GenerateSchema())
func NewPostgresStorage ¶ added in v0.8.0
func NewPostgresStorage(db *sql.DB, opts ...Option) (*PostgresStorage, error)
NewPostgresStorage creates a new PostgresStorage with the given options.
func (*PostgresStorage) DeleteState ¶ added in v0.8.0
func (s *PostgresStorage) DeleteState(ctx context.Context, id string) error
DeleteState removes a workflow's state.
func (*PostgresStorage) DeleteStateTx ¶ added in v0.8.0
DeleteStateTx behaves like DeleteState but writes through the provided transaction.
func (*PostgresStorage) EnsureSchema ¶ added in v0.8.0
func (s *PostgresStorage) EnsureSchema(ctx context.Context) error
EnsureSchema creates the state table if it does not exist and idempotently applies the migrations this library version needs — currently the M4 due index: it adds the due column to a pre-existing table (ADD COLUMN IF NOT EXISTS) and creates the supporting index. It is safe to call on every process start against both fresh and pre-existing tables, and is the recommended one-call setup for backends that use Manager.FireDue.
func (*PostgresStorage) GenerateSchema ¶ added in v0.8.0
func (s *PostgresStorage) GenerateSchema() string
GenerateSchema returns the CREATE TABLE statement for the state table.
func (*PostgresStorage) ListDue ¶ added in v0.8.0
func (s *PostgresStorage) ListDue(ctx context.Context, before time.Time, limit int) ([]string, error)
ListDue implements workflow.DueStorage, returning the IDs of instances whose stored next-due time is non-null and at or before `before`, ordered by due time ascending then by ID. A zero limit means no limit.
func (*PostgresStorage) ListIDs ¶ added in v0.8.0
func (s *PostgresStorage) ListIDs(ctx context.Context, opts workflow.ListOptions) ([]string, error)
ListIDs implements workflow.ListableStorage, returning persisted workflow IDs ordered by ID for stable pagination. A zero opts.Limit means no limit.
func (*PostgresStorage) LoadState ¶ added in v0.8.0
func (s *PostgresStorage) LoadState(ctx context.Context, id string) (workflow.Marking, map[string]any, error)
LoadState loads the workflow's marking and custom fields.
func (*PostgresStorage) LoadStateTx ¶ added in v0.8.0
func (s *PostgresStorage) LoadStateTx(ctx context.Context, tx *sql.Tx, id string) (workflow.Marking, map[string]any, error)
LoadStateTx behaves like LoadState but reads through the provided transaction.
func (*PostgresStorage) LoadVersionedState ¶ added in v0.8.0
func (s *PostgresStorage) LoadVersionedState(ctx context.Context, id string) (workflow.Marking, map[string]any, int64, error)
LoadVersionedState implements workflow.VersionedStorage.
func (*PostgresStorage) SaveState ¶ added in v0.8.0
func (s *PostgresStorage) SaveState(ctx context.Context, id string, marking workflow.Marking, ctxData map[string]any) error
SaveState upserts the workflow's places and custom fields (last write wins). It does not maintain the due index (the due column is left untouched); for a timed definition, save through the Manager or SaveVersionedStateWithDue so the index stays consistent.
func (*PostgresStorage) SaveStateTx ¶ added in v0.8.0
func (s *PostgresStorage) SaveStateTx(ctx context.Context, tx *sql.Tx, id string, marking workflow.Marking, ctxData map[string]any) error
SaveStateTx behaves like SaveState but writes through the provided transaction.
func (*PostgresStorage) SaveVersionedState ¶ added in v0.8.0
func (s *PostgresStorage) SaveVersionedState(ctx context.Context, id string, marking workflow.Marking, ctxData map[string]any, expectedVersion int64) (int64, error)
SaveVersionedState implements workflow.VersionedStorage. It preserves the due column (untouched on update, NULL on insert) but does not maintain the due index; for a timed definition, use SaveVersionedStateWithDue or go through the Manager so the index stays current.
func (*PostgresStorage) SaveVersionedStateInTx ¶ added in v0.8.0
func (s *PostgresStorage) SaveVersionedStateInTx(ctx context.Context, id string, marking workflow.Marking, ctxData map[string]any, expectedVersion int64, effects ...workflow.TxSideEffect) (int64, error)
SaveVersionedStateInTx implements workflow.TransactionalStorage: the versioned save and every side effect run in one transaction, committing only if all succeed. Effects receive the *sql.Tx (as an any). It does not maintain the due index; for a timed definition use SaveVersionedStateInTxWithDue so the index commits atomically with state and effects.
func (*PostgresStorage) SaveVersionedStateInTxWithDue ¶ added in v0.8.0
func (s *PostgresStorage) SaveVersionedStateInTxWithDue(ctx context.Context, id string, marking workflow.Marking, ctxData map[string]any, expectedVersion int64, due *time.Time, effects ...workflow.TxSideEffect) (int64, error)
SaveVersionedStateInTxWithDue implements workflow.TransactionalDueStorage: the versioned save, the due-index update, and every side effect run in one transaction, committing only if all succeed.
func (*PostgresStorage) SaveVersionedStateTx ¶ added in v0.8.0
func (s *PostgresStorage) SaveVersionedStateTx(ctx context.Context, tx *sql.Tx, id string, marking workflow.Marking, ctxData map[string]any, expectedVersion int64) (int64, error)
SaveVersionedStateTx behaves like SaveVersionedState but writes through the provided transaction. Like SaveVersionedState it does not maintain the due index; for a timed definition composed manually into a transaction, use SaveVersionedStateInTxWithDue (or the Manager) so the due index commits with it.
func (*PostgresStorage) SaveVersionedStateWithDue ¶ added in v0.8.0
func (s *PostgresStorage) SaveVersionedStateWithDue(ctx context.Context, id string, marking workflow.Marking, ctxData map[string]any, expectedVersion int64, due *time.Time) (int64, error)
SaveVersionedStateWithDue implements workflow.DueStorage: it saves the versioned state and records the instance's next-due time (nil clears it) in the due-index column.
type SQLiteStorage ¶
type SQLiteStorage struct {
// contains filtered or unexported fields
}
SQLiteStorage provides a persistent storage implementation using SQLite. It is highly configurable to allow for custom table and column names, as well as storing arbitrary application-specific data alongside the workflow state. It implements workflow.Storage and workflow.VersionedStorage.
func NewSQLiteStorage ¶
func NewSQLiteStorage(db *sql.DB, opts ...Option) (*SQLiteStorage, error)
NewSQLiteStorage creates a new SQLiteStorage with the given options.
func (*SQLiteStorage) DeleteState ¶
func (s *SQLiteStorage) DeleteState(ctx context.Context, id string) error
DeleteState removes a workflow's state from the database.
func (*SQLiteStorage) DeleteStateTx ¶ added in v0.8.0
DeleteStateTx behaves like DeleteState but writes through the provided transaction.
func (*SQLiteStorage) EnsureSchema ¶ added in v0.8.0
func (s *SQLiteStorage) EnsureSchema(ctx context.Context) error
EnsureSchema creates the state table if it does not exist and idempotently applies the migrations this library version needs — currently the M4 due index: it adds the due column to a pre-existing table (safely tolerating a table that already has it) and creates the supporting index. It is safe to call on every process start against both fresh and pre-existing tables, and is the recommended one-call setup for backends that use Manager.FireDue.
func (*SQLiteStorage) GenerateSchema ¶
func (s *SQLiteStorage) GenerateSchema() string
GenerateSchema returns the `CREATE TABLE` SQL statement based on the storage configuration. This allows the user to see, modify, or use the schema with a separate migration tool.
func (*SQLiteStorage) ListDue ¶ added in v0.8.0
ListDue implements workflow.DueStorage, returning the IDs of instances whose stored next-due time is non-null and at or before `before`, ordered by due time ascending then by ID. A zero limit means no limit.
func (*SQLiteStorage) ListIDs ¶ added in v0.8.0
func (s *SQLiteStorage) ListIDs(ctx context.Context, opts workflow.ListOptions) ([]string, error)
ListIDs implements workflow.ListableStorage, returning persisted workflow IDs ordered by ID for stable pagination. A zero opts.Limit means no limit.
func (*SQLiteStorage) LoadState ¶
func (s *SQLiteStorage) LoadState(ctx context.Context, id string) (workflow.Marking, map[string]any, error)
LoadState loads the workflow's marking and all configured custom fields into the context map.
func (*SQLiteStorage) LoadStateTx ¶ added in v0.8.0
func (s *SQLiteStorage) LoadStateTx(ctx context.Context, tx *sql.Tx, id string) (workflow.Marking, map[string]any, error)
LoadStateTx behaves like LoadState but reads through the provided transaction, so it observes the transaction's own uncommitted writes.
func (*SQLiteStorage) LoadVersionedState ¶ added in v0.8.0
func (s *SQLiteStorage) LoadVersionedState(ctx context.Context, id string) (workflow.Marking, map[string]any, int64, error)
LoadVersionedState implements workflow.VersionedStorage. It loads the workflow's marking and context data along with its current optimistic-concurrency version. A never-saved workflow returns workflow.ErrWorkflowNotFound.
func (*SQLiteStorage) SaveState ¶
func (s *SQLiteStorage) SaveState(ctx context.Context, id string, marking workflow.Marking, ctxData map[string]any) error
SaveState saves the workflow's current places and any configured custom fields from its context. It does not maintain the due index (the due column is left untouched); for a timed definition, save through the Manager or SaveVersionedStateWithDue so the index stays consistent.
func (*SQLiteStorage) SaveStateTx ¶ added in v0.8.0
func (s *SQLiteStorage) SaveStateTx(ctx context.Context, tx *sql.Tx, id string, marking workflow.Marking, ctxData map[string]any) error
SaveStateTx behaves like SaveState but writes through the provided transaction, so it can be committed atomically with other writes (e.g. a history record). See RunInTx.
func (*SQLiteStorage) SaveVersionedState ¶ added in v0.8.0
func (s *SQLiteStorage) SaveVersionedState(ctx context.Context, id string, marking workflow.Marking, ctxData map[string]any, expectedVersion int64) (int64, error)
SaveVersionedState implements workflow.VersionedStorage. It saves the workflow only if the stored version equals expectedVersion, returning the new version. Pass expectedVersion 0 to create a new workflow. A mismatch returns workflow.ErrConflict.
It preserves the due column (leaves it untouched on update, NULL on insert) but does not maintain the due index; for a timed definition, use SaveVersionedStateWithDue or go through the Manager so the index stays current.
func (*SQLiteStorage) SaveVersionedStateInTx ¶ added in v0.8.0
func (s *SQLiteStorage) SaveVersionedStateInTx(ctx context.Context, id string, marking workflow.Marking, ctxData map[string]any, expectedVersion int64, effects ...workflow.TxSideEffect) (int64, error)
SaveVersionedStateInTx implements workflow.TransactionalStorage: the versioned save and every side effect run in one transaction, committing only if all succeed. Effects receive the *sql.Tx (as an any). It does not maintain the due index; for a timed definition use SaveVersionedStateInTxWithDue so the index commits atomically with state and effects.
func (*SQLiteStorage) SaveVersionedStateInTxWithDue ¶ added in v0.8.0
func (s *SQLiteStorage) SaveVersionedStateInTxWithDue(ctx context.Context, id string, marking workflow.Marking, ctxData map[string]any, expectedVersion int64, due *time.Time, effects ...workflow.TxSideEffect) (int64, error)
SaveVersionedStateInTxWithDue implements workflow.TransactionalDueStorage: the versioned save, the due-index update, and every side effect run in one transaction, committing only if all succeed.
func (*SQLiteStorage) SaveVersionedStateTx ¶ added in v0.8.0
func (s *SQLiteStorage) SaveVersionedStateTx(ctx context.Context, tx *sql.Tx, id string, marking workflow.Marking, ctxData map[string]any, expectedVersion int64) (int64, error)
SaveVersionedStateTx behaves like SaveVersionedState but writes through the provided transaction, so a versioned state change and a history record can be committed atomically. See RunInTx. Like SaveVersionedState it does not maintain the due index; for a timed definition composed manually into a transaction, use SaveVersionedStateInTxWithDue (or the Manager) so the due index commits with it.
func (*SQLiteStorage) SaveVersionedStateWithDue ¶ added in v0.8.0
func (s *SQLiteStorage) SaveVersionedStateWithDue(ctx context.Context, id string, marking workflow.Marking, ctxData map[string]any, expectedVersion int64, due *time.Time) (int64, error)
SaveVersionedStateWithDue implements workflow.DueStorage: it saves the versioned state and records the instance's next-due time (nil clears it) in the due-index column.