Documentation
¶
Overview ¶
Package statecharts implements statechart semantics with a Go-first authoring API.
Atomic, Compound, Parallel, Final, History, On, and Eventless construct a mutable, syntax-neutral Definition. Build validates that definition and compiles it with a Datamodel into an immutable *Chart. Compile accepts the same Definition directly, so a definition obtained from Chart.Definition can be encoded, edited, decoded, and compiled through exactly the same path. Chart.Definition always returns an independently editable deep copy.
New is the default Go authoring path. It combines ordinary typed Go state with a chart-local behavior registry, qualifies short action, condition, value, and location names under the chart ID, and compiles through the same syntax-neutral Definition path as every other datamodel. Definitions store stable names and versions rather than Go function values, making them deterministic and inspectable while each running Instance still owns ordinary typed Go data. NewGoModel and package-level Build expose the underlying registry and compiler directly when an application needs them. Compile derives Chart.Revision from a versioned canonical definition, datamodel identity, and deterministic program fingerprint; snapshots and durable outbound identities are scoped to that revision. Chart.DefinitionArtifact, DefinitionStore, and ActorStore provide the durable definition and actor-revision-pin contracts needed to resolve that exact revision after process restart. Other datamodels can implement Datamodel, DatamodelProgram, and DatamodelSession without changing the interpreter.
An Instance processes events serially, selecting transitions, resolving conflicts between parallel regions, and entering and exiting states in document order. Send, Stop, Wait, and Configuration provide its lifecycle API. ExecContext supplies registered model functions with the current event, active-state predicate, session metadata, and controlled raise, send, cancel, and logging capabilities.
Communication outside an Instance goes through IOProcessor. Longer-lived services are declared with Invoke and supplied at instance creation as environment-scoped InvokeHandler factories; handler capabilities never enter a Definition or model snapshot. Logger is the separate diagnostic output seam.
Instance.Snapshot captures a disposable restoration cache. Chart.Restore reconstructs from that cache, while Chart.Rehydrate rebuilds authoritative state from a Log and uses a compatible snapshot only to skip older replay. The sqllog package provides database/sql-backed durable storage, and the optional sqllog/sqlite3 package supplies a configured SQLite driver.
Index ¶
- Constants
- Variables
- func LoggingTimerFiredDetailsHook(log Log, sessionID SessionID, clock Clock) func(Identifier, Identifier, Identifier, Event) error
- func LoggingTimerFiredHook(log Log, sessionID SessionID, clocks ...Clock) func(Identifier, Event) error
- type AcknowledgingIOProcessor
- type ActiveInvoke
- type ActorBeginResult
- type ActorLifecycle
- type ActorMetadata
- type ActorMetadataCursor
- type ActorMetadataPage
- type ActorMetadataQuery
- type ActorStore
- type ActorTerminalResult
- type AssignDefinition
- type AuthoringOption
- type BuildOption
- type Builder
- func (b *Builder[D]) Action(name string, action GoAction[D]) GoActionRef
- func (b *Builder[D]) ActionVersion(name string, version string, action GoAction[D]) GoActionRef
- func (b *Builder[D]) Build(root StateDefinition, options ...BuildOption) (*Chart, error)
- func (b *Builder[D]) Condition(name string, condition GoCondition[D]) GoConditionRef
- func (b *Builder[D]) ConditionVersion(name string, version string, condition GoCondition[D]) GoConditionRef
- func (b *Builder[D]) Location(name string, get GoValue[D], set GoLocation[D]) GoLocationRef
- func (b *Builder[D]) LocationVersion(name string, version string, get GoValue[D], set GoLocation[D]) GoLocationRef
- func (b *Builder[D]) Value(name string, value GoValue[D]) GoValueRef
- func (b *Builder[D]) ValueVersion(name string, version string, value GoValue[D]) GoValueRef
- type CallDefinition
- type CancelDefinition
- type Chart
- func (c *Chart) Datamodel() Datamodel
- func (c *Chart) DatamodelProgram() DatamodelProgram
- func (c *Chart) Definition() Definition
- func (c *Chart) DefinitionArtifact() DefinitionArtifact
- func (c *Chart) ID() Identifier
- func (c *Chart) Name() string
- func (c *Chart) NewInstance(opts ...Option) (*Instance, error)
- func (c *Chart) Prepare(opts ...Option) error
- func (c *Chart) Rehydrate(ctx context.Context, log Log, snapshots SnapshotStore, sessionID SessionID, ...) (*Instance, error)
- func (c *Chart) Restore(snap Snapshot, opts ...Option) (*Instance, error)
- func (c *Chart) Revision() RevisionID
- func (c *Chart) States() []Identifier
- type Checkpoint
- type ChooseBranchDefinition
- type ChooseDefinition
- type Clock
- type CompiledExpression
- type DataBinding
- type DataDefinition
- type Datamodel
- type DatamodelProgram
- type DatamodelSession
- type Definition
- type DefinitionArtifact
- type DefinitionDeleteResult
- type DefinitionError
- type DefinitionPutResult
- type DefinitionStore
- type DeliveryID
- type Dispatcher
- type DoneDataDefinition
- type DurableLog
- type EncodedEvent
- type EntryKind
- type Event
- type EventType
- type ExecContext
- func (ec ExecContext) Cancel(sendID Identifier)
- func (ec ExecContext) Event() (Event, bool)
- func (ec ExecContext) IOProcessorLocation(typ Identifier) (location Location, ok bool)
- func (ec ExecContext) IOProcessors() []IOProcessorInfo
- func (ec ExecContext) In(id Identifier) bool
- func (ec ExecContext) Log(label string, data Value)
- func (ec ExecContext) Name() string
- func (ec ExecContext) PlatformVariables() map[string]any
- func (ec ExecContext) Raise(ev Event)
- func (ec ExecContext) Send(name Identifier, opts SendOptions)
- func (ec ExecContext) SessionID() string
- type Executable
- func CancelSend(sendID Identifier) Executable
- func LogValue(label string, expression Expression) Executable
- func NewAssignExecutable(value AssignDefinition) Executable
- func NewCallExecutable(value CallDefinition) Executable
- func NewCancelExecutable(value CancelDefinition) Executable
- func NewChooseExecutable(value ChooseDefinition) Executable
- func NewExtensionExecutable(value ExtensionDefinition) Executable
- func NewForEachExecutable(value ForEachDefinition) Executable
- func NewLogExecutable(value LogDefinition) Executable
- func NewRaiseExecutable(value RaiseDefinition) Executable
- func NewScriptExecutable(value ScriptDefinition) Executable
- func NewSendExecutable(value SendDefinition) Executable
- func Raise(event Identifier, data ...Expression) Executable
- func Send(event Identifier, options ...SendOption) Executable
- type ExecutableBlock
- type ExecutableKind
- type Expression
- type ExtensionDefinition
- type ForEachDefinition
- type FunctionRef
- type GoAction
- type GoActionRef
- type GoCondition
- type GoConditionRef
- type GoInspectionCodec
- type GoLocation
- type GoLocationRef
- type GoModel
- func (m *GoModel[D]) Action(n Identifier, v string, fn GoAction[D]) (GoActionRef, error)
- func (m *GoModel[D]) Compile(def *Definition) (DatamodelProgram, error)
- func (m *GoModel[D]) Condition(n Identifier, v string, fn GoCondition[D]) (GoConditionRef, error)
- func (m *GoModel[D]) Location(n Identifier, v string, get GoValue[D], set GoLocation[D]) (GoLocationRef, error)
- func (*GoModel[D]) Name() Identifier
- func (m *GoModel[D]) Script(n Identifier, v string, fn GoAction[D]) (GoActionRef, error)
- func (*GoModel[D]) TextExpressionCodec() TextExpressionCodec
- func (m *GoModel[D]) Value(n Identifier, v string, fn GoValue[D]) (GoValueRef, error)
- type GoModelOption
- type GoSnapshotCodec
- type GoTextExpressionCodec
- type GoValue
- type GoValueRef
- type HistoryKind
- type IDGenerator
- type IDGeneratorFunc
- type IDLocationFunc
- type IOProcessor
- type IOProcessorDescriber
- type IOProcessorInfo
- type Identifier
- func (id Identifier) Compare(other Identifier) int
- func (id Identifier) MarshalText() ([]byte, error)
- func (id Identifier) Matches(eventName Identifier) bool
- func (id *Identifier) Scan(src any) error
- func (id Identifier) Segments() []string
- func (id Identifier) String() string
- func (id *Identifier) UnmarshalText(text []byte) error
- func (id Identifier) Value() (driver.Value, error)
- type Instance
- func (in *Instance) Checkpoint(ctx context.Context, save func(Snapshot) error) error
- func (in *Instance) Configuration() []Identifier
- func (in *Instance) Deliver(ctx context.Context, ev Event) error
- func (in *Instance) Done() <-chan struct{}
- func (in *Instance) Err() error
- func (in *Instance) HasActiveInvokes(ctx context.Context) (bool, error)
- func (in *Instance) ID() SessionID
- func (in *Instance) Inspect(ctx context.Context) (InstanceInspection, error)
- func (in *Instance) Result() (Value, error)
- func (in *Instance) Send(ctx context.Context, ev Event) error
- func (in *Instance) Snapshot(ctx context.Context) (Snapshot, error)
- func (in *Instance) Start(ctx context.Context) error
- func (in *Instance) Stop(ctx context.Context) error
- func (in *Instance) Wait(ctx context.Context) error
- type InstanceInspection
- type InvokeDefinition
- type InvokeHandler
- type InvokeHandlerFactory
- type InvokeHandlerFunc
- type InvokeIO
- type InvokeOption
- func WithAutoForward() InvokeOption
- func WithFinalize(actions ...Executable) InvokeOption
- func WithInvokeContent(content Expression) InvokeOption
- func WithInvokeDefinitionID(id Identifier) InvokeOption
- func WithInvokeID(id Identifier) InvokeOption
- func WithInvokeIDLocation(location Expression) InvokeOption
- func WithInvokeParams(params ...ParamDefinition) InvokeOption
- func WithInvokeSourceExpression(expression Expression) InvokeOption
- func WithInvokeTypeExpression(expression Expression) InvokeOption
- type InvokeRequest
- type IterationBindings
- type LocalIOProcessor
- type Location
- type Log
- type LogDefinition
- type LogEntry
- type Logger
- type MacrostepObserver
- type MacrostepObserverFunc
- type MacrostepTrace
- type ManualClock
- type ManualIDGenerator
- type MicrostepTrace
- type Option
- func WithClock(clk Clock) Option
- func WithCompletionHook(fn func() error) Option
- func WithDeliveryNamespace(namespace string) Option
- func WithIDGenerator(g IDGenerator) Option
- func WithIOProcessor(typ Identifier, p IOProcessor) Option
- func WithInboxSize(n int) Option
- func WithIngressHook(fn func(Event) error) Option
- func WithInvokeHandler(typ Identifier, factory InvokeHandlerFactory) Option
- func WithLogger(l Logger) Option
- func WithMacrostepObserver(observer MacrostepObserver) Option
- func WithPlatformVariables(values map[string]any) Option
- func WithSessionID(id SessionID) Option
- func WithTimerFiredDetailsHook(fn func(sendID, target, typ Identifier, ev Event) error) Option
- func WithTimerFiredHook(fn func(sendID Identifier, ev Event) error) Option
- type OutboundMessage
- type OutboundResult
- type OutboundStatus
- type ParamDefinition
- type PendingSend
- type RaiseDefinition
- type ReplayAwareIOProcessor
- type ResumableInvokeHandler
- type RevisionID
- type ScriptDefinition
- type SendDefinition
- type SendExecutionError
- type SendOption
- func SendContent(content Expression) SendOption
- func SendDelay(delay time.Duration) SendOption
- func SendID(id Identifier) SendOption
- func SendIDLocation(location Expression) SendOption
- func SendParams(params ...ParamDefinition) SendOption
- func SendTarget(target string) SendOption
- func SendType(typ string) SendOption
- type SendOptions
- type SendRequest
- type SessionID
- type SessionOptions
- type Snapshot
- type SnapshotStore
- type StateDefinition
- func Atomic(id Identifier, opts ...StateOption) StateDefinition
- func Compound(id Identifier, initial Identifier, opts ...StateOption) StateDefinition
- func Final(id Identifier, opts ...StateOption) StateDefinition
- func History(id Identifier, kind HistoryKind, defaultTarget Identifier, ...) StateDefinition
- func Parallel(id Identifier, opts ...StateOption) StateDefinition
- type StateDefinitionID
- type StateKind
- type StateOption
- func Children(children ...StateDefinition) StateOption
- func Eventless(opts ...TransitionOption) StateOption
- func Invoke(typ, source string, opts ...InvokeOption) StateOption
- func On(events string, opts ...TransitionOption) StateOption
- func OnEntry(actions ...Executable) StateOption
- func OnExit(actions ...Executable) StateOption
- func WithDone(content Expression) StateOption
- func WithDoneParams(params ...ParamDefinition) StateOption
- func WithInitial(opts ...TransitionOption) StateOption
- type TextExpressionCodec
- type TextExpressionRole
- type TransitionDefinition
- type TransitionOption
- type TransitionRef
- type TransitionType
- type Value
- func BoolValue(value bool) Value
- func Float64Value(value float64) (Value, error)
- func Int64Value(value int64) Value
- func ListValue(values []Value) Value
- func MapValue(values map[string]Value) (Value, error)
- func NullValue() Value
- func NumberValue(value string) (Value, error)
- func PlatformErrorValue(classification Identifier, err error) Value
- func StringValue(value string) (Value, error)
- func TaggedValue(tag string, payload Value) (Value, error)
- func Uint64Value(value uint64) Value
- func ValueFromJSON(input any) (Value, error)
- func ValueFromWire(wire ValueWire) (Value, error)
- func (v Value) AsBool() (bool, bool)
- func (v Value) AsInt64() (int64, bool)
- func (v Value) AsList() ([]Value, bool)
- func (v Value) AsMap() (map[string]Value, bool)
- func (v Value) AsNumber() (string, bool)
- func (v Value) AsString() (string, bool)
- func (v Value) AsTagged() (tag string, payload Value, ok bool)
- func (v Value) Clone() Value
- func (v Value) Equal(other Value) bool
- func (v Value) JSONValue() (any, error)
- func (v Value) Kind() ValueKind
- func (v Value) MarshalBinary() ([]byte, error)
- func (v Value) MarshalJSON() ([]byte, error)
- func (v Value) MarshalText() ([]byte, error)
- func (v *Value) UnmarshalBinary(data []byte) error
- func (v *Value) UnmarshalJSON(data []byte) error
- func (v *Value) UnmarshalText(data []byte) error
- func (v Value) Wire() (ValueWire, error)
- type ValueKind
- type ValueWire
- type WriterLogger
Constants ¶
const ( // DefinitionCanonicalVersion identifies the internal canonical definition // encoding. It must change when that encoding changes. DefinitionCanonicalVersion uint32 = 2 // DefinitionCanonicalMagic separates canonical definitions from other // versioned byte formats when they are used as revision material. DefinitionCanonicalMagic = "statecharts-definition\x00" )
const ( // RevisionEnvelopeVersion identifies the inputs and framing used to derive // chart revisions. It must change whenever that material or framing changes. RevisionEnvelopeVersion uint32 = 1 // RevisionEnvelopeMagic separates revision material from every other // versioned canonical byte format. RevisionEnvelopeMagic = "statecharts-revision\x00" )
const ( // DefaultActorMetadataPageLimit is used when ActorMetadataQuery.Limit is zero. DefaultActorMetadataPageLimit = 50 // MaxActorMetadataPageLimit is the largest accepted actor directory page. MaxActorMetadataPageLimit = 200 )
const GoInspectionValueTag = "statecharts.go-datamodel/v1"
GoInspectionValueTag identifies the tagged Value returned by a Go datamodel session's Inspect method.
const PlatformErrorValueTag = "statecharts.error/v1"
PlatformErrorValueTag is the stable tag used for interpreter and platform errors that cross event, session, actor, or durability boundaries.
const ValueWireVersion = 1
ValueWireVersion is the current canonical Value wire-format version.
Variables ¶
var ( // ErrInvalidDefinitionArtifact marks corrupt, unsupported, or internally // inconsistent persisted definition data. ErrInvalidDefinitionArtifact = errors.New("statecharts: invalid definition artifact") // ErrDefinitionCollision marks an attempt to associate one RevisionID // with artifact bytes other than the bytes already stored for that ID. ErrDefinitionCollision = errors.New("statecharts: definition revision collision") // ErrDefinitionNotFound marks an operation that requires an immutable // definition artifact that is not present. ErrDefinitionNotFound = errors.New("statecharts: definition artifact not found") )
var ( // ErrInvalidActorMetadata marks malformed durable actor identity, pin, // lifecycle data, or its required session-start boundary. ErrInvalidActorMetadata = errors.New("statecharts: invalid actor metadata") // ErrActorCollision marks reuse of an actor ID with a different chart, // revision, session, or durability. ErrActorCollision = errors.New("statecharts: actor identity collision") // ErrActorTerminal marks an attempt to begin an actor ID whose durable // lifecycle has already reached terminal. ErrActorTerminal = errors.New("statecharts: actor is terminal") )
var ErrInstanceStopped = errors.New("statecharts: instance stopped")
ErrInstanceStopped is returned by Send (and, internally, treated as success by Stop) when a message could not be confirmed as accepted by a live interpreter goroutine -- either the goroutine had already exited, or it exited in the narrow window between the message being buffered and the goroutine actually dequeuing it. It is distinct from Err(): the instance's terminal error may well be nil (a clean stop), but that must never be confused with "this particular message was processed".
var ErrInvalidSnapshot = errors.New("statecharts: invalid snapshot")
ErrInvalidSnapshot marks malformed or incompatible snapshot cache data.
var ErrOutboundCollision = errors.New("statecharts: outbound delivery ID collision")
ErrOutboundCollision marks two different durable send intents carrying the same DeliveryID. A durable store must reject the second intent rather than silently treating it as an idempotent retry of the first.
Functions ¶
func LoggingTimerFiredDetailsHook ¶
func LoggingTimerFiredDetailsHook(log Log, sessionID SessionID, clock Clock) func(Identifier, Identifier, Identifier, Event) error
LoggingTimerFiredDetailsHook returns a callback for WithTimerFiredDetailsHook. It persists the original target and I/O processor type as well as the event, and uses clock for the entry's logical timestamp.
func LoggingTimerFiredHook ¶
func LoggingTimerFiredHook(log Log, sessionID SessionID, clocks ...Clock) func(Identifier, Event) error
LoggingTimerFiredHook returns a callback for WithTimerFiredHook that appends a KindTimerFired entry to log before the event is allowed to apply, satisfying the write-ahead requirement for timer-fired events -- the one kind of inbound message with no explicit Instance.Send call site for an application to log itself. Explicit application Sends must separately call log.Append(ctx, LogEntry{Kind: KindExternalEvent, ...}) before calling Instance.Send; that ordinary call site needs no hook.
Types ¶
type AcknowledgingIOProcessor ¶
type AcknowledgingIOProcessor interface {
IOProcessor
SendWithAck(ctx context.Context, req SendRequest, complete func(error)) error
}
AcknowledgingIOProcessor reports stable asynchronous acceptance. complete must be called exactly once after the destination has accepted (or rejected) the request; returning an error reports a synchronous failure.
type ActiveInvoke ¶
type ActiveInvoke struct {
State Identifier `json:"state"` // the state that owns this invocation
DefinitionID Identifier `json:"definition_id"` // stable declaration identity in the pinned chart definition
ID Identifier `json:"id"` // the invocation's own id, exactly as assigned when it started
Type Identifier `json:"type,omitempty"` // evaluated handler type selected when this invocation began
Source string `json:"source,omitempty"` // evaluated source selected when this invocation began
}
ActiveInvoke records one <invoke> that was active in Configuration when a Snapshot was taken.
type ActorBeginResult ¶
type ActorBeginResult uint8
ActorBeginResult describes an idempotent atomic actor start.
const ( ActorStarted ActorBeginResult = iota + 1 ActorAlreadyActive )
type ActorLifecycle ¶
type ActorLifecycle string
ActorLifecycle is the durable lifecycle of a started actor. Absence from an ActorStore means never started; no never-started metadata row is persisted.
const ( ActorLifecycleActive ActorLifecycle = "active" ActorLifecycleTerminal ActorLifecycle = "terminal" )
type ActorMetadata ¶
type ActorMetadata struct {
ActorID Identifier
ChartID Identifier
Revision RevisionID
SessionID SessionID
Durable bool
Lifecycle ActorLifecycle
StartedAt time.Time
TerminalAt time.Time
}
ActorMetadata is the authoritative durable revision pin for one actor ID. Ephemeral actors retain their Chart directly and are not written to an ActorStore; Durable remains explicit so identity retries cannot silently cross the durable/ephemeral boundary.
func (ActorMetadata) Validate ¶
func (m ActorMetadata) Validate() error
Validate checks active or terminal persisted metadata. BeginActor accepts only ActorLifecycleActive values.
type ActorMetadataCursor ¶
type ActorMetadataCursor string
ActorMetadataCursor is an opaque, storage-independent position in the ActorID ordering. Callers should only retain and return cursor values from a previous ActorMetadataPage.
func ActorMetadataCursorFor ¶
func ActorMetadataCursorFor(actorID Identifier) ActorMetadataCursor
ActorMetadataCursorFor returns the opaque cursor following actorID.
type ActorMetadataPage ¶
type ActorMetadataPage struct {
Actors []ActorMetadata
Next ActorMetadataCursor
}
ActorMetadataPage owns its Actors slice and contains Next only when another matching actor exists.
type ActorMetadataQuery ¶
type ActorMetadataQuery struct {
After ActorMetadataCursor
Limit int
ActorIDPrefix string
ChartID Identifier
Revision RevisionID
Lifecycle ActorLifecycle
}
ActorMetadataQuery selects durable actor metadata. An empty Lifecycle selects both active and terminal actors, making the default suitable for a complete directory traversal. After is exclusive. Limit zero uses DefaultActorMetadataPageLimit; negative or oversized limits are rejected.
func (ActorMetadataQuery) Validate ¶
func (q ActorMetadataQuery) Validate() (normalized ActorMetadataQuery, after Identifier, err error)
Validate normalizes the limit and decodes the exclusive ActorID cursor. Storage implementations use this method to ensure identical validation.
type ActorStore ¶
type ActorStore interface {
// BeginActor atomically stores metadata and appends exactly one
// KindSessionStarted entry at metadata.StartedAt before any initial chart
// behavior may run. It requires a valid matching DefinitionArtifact.
// Exact identity retries return the originally stored metadata and
// ActorAlreadyActive without another log entry. Different pins return
// ErrActorCollision; terminal IDs return ErrActorTerminal. Reusing a
// SessionID or beginning against a pre-populated session log also returns
// ErrActorCollision.
BeginActor(ctx context.Context, metadata ActorMetadata) (ActorMetadata, ActorBeginResult, error)
// GetActor returns authoritative metadata regardless of residency or
// terminal state. Absence means the actor was never started. Corrupt actor
// metadata or a missing/inconsistent session-start record returns
// ErrInvalidActorMetadata before replay can begin.
GetActor(ctx context.Context, actorID Identifier) (ActorMetadata, bool, error)
// QueryActors returns durable metadata in ActorID ascending order without
// activating actors. Filters are combined, and the cursor is exclusive.
QueryActors(ctx context.Context, query ActorMetadataQuery) (ActorMetadataPage, error)
// MarkActorTerminal atomically releases actorID's revision reference. It
// is idempotent and preserves the first terminal timestamp.
MarkActorTerminal(ctx context.Context, actorID Identifier, terminalAt time.Time) (ActorMetadata, ActorTerminalResult, error)
// ReferencedRevisions returns the sorted, deduplicated revisions pinned by
// non-terminal durable actors.
ReferencedRevisions(ctx context.Context) ([]RevisionID, error)
}
ActorStore persists durable actor revision pins and their lifecycle. The same concrete storage object must also implement Log and DefinitionStore so BeginActor and DeleteDefinitionIfUnreferenced can provide their documented cross-record atomicity. A SessionID is owned by exactly one ActorID. Its first log entry is the actor's sole KindSessionStarted record, at Seq 1 and the stored StartedAt; every actor read verifies that boundary before returning metadata.
type ActorTerminalResult ¶
type ActorTerminalResult uint8
ActorTerminalResult describes an idempotent terminal transition.
const ( ActorMarkedTerminal ActorTerminalResult = iota + 1 ActorAlreadyTerminal ActorNotFound )
type AssignDefinition ¶
type AssignDefinition struct {
Location Expression `json:"location"`
Expr Expression `json:"expr"`
}
AssignDefinition evaluates Expr and stores it at the datamodel Location.
type AuthoringOption ¶
type AuthoringOption func(*authoringConfig)
AuthoringOption configures the default Go authoring path created by New.
func Version ¶
func Version(version string) AuthoringOption
Version sets the default version for registered behavior and supplies the chart revision salt. Bump it when Go behavior changes without changing the chart structure. The default is "v1".
type BuildOption ¶
type BuildOption func(*Definition)
BuildOption configures the mutable Definition assembled by Build before it is validated and compiled. Options must store only definition data.
func WithData ¶
func WithData(data ...DataDefinition) BuildOption
WithData appends document-level data declarations.
func WithDataBinding ¶
func WithDataBinding(binding DataBinding) BuildOption
WithDataBinding selects early or late initialization for data declarations.
func WithName ¶
func WithName(name string) BuildOption
WithName sets the SCXML document name exposed as _name. It is independent of the root state's structural ID.
func WithRevisionSalt ¶
func WithRevisionSalt(salt string) BuildOption
WithRevisionSalt adds explicit application-controlled revision material. Change it when registered behavior changes without a corresponding function version change.
type Builder ¶
type Builder[D any] struct { // contains filtered or unexported fields }
Builder is the concise, default authoring surface for Go applications. It owns one model-local behavior registry, qualifies short behavior names with the chart ID, and reports registration errors when Build is called.
Use the package-level Build with an explicit Datamodel instead when authoring for another datamodel or when direct registry control is required.
func New ¶
func New[D any](id Identifier, factory func() *D, options ...AuthoringOption) *Builder[D]
New starts a Go-authored chart definition. id is the stable chart identity; behavior registered as "publish" is stored as "<id>.publish" in the canonical Definition. The returned Builder is intended for configuration by one goroutine before Build.
func (*Builder[D]) Action ¶
func (b *Builder[D]) Action(name string, action GoAction[D]) GoActionRef
Action registers a named action at the Builder's default Version.
func (*Builder[D]) ActionVersion ¶
func (b *Builder[D]) ActionVersion(name string, version string, action GoAction[D]) GoActionRef
ActionVersion registers a retained implementation at an explicit version. This is useful when old, revision-pinned actors may still resolve it.
func (*Builder[D]) Build ¶
func (b *Builder[D]) Build(root StateDefinition, options ...BuildOption) (*Chart, error)
Build compiles root through the ordinary Definition compiler. The Builder's ID becomes the chart ID and its Version becomes the default revision salt; an explicit WithRevisionSalt option may override that salt.
func (*Builder[D]) Condition ¶
func (b *Builder[D]) Condition(name string, condition GoCondition[D]) GoConditionRef
Condition registers a named condition at the Builder's default Version.
func (*Builder[D]) ConditionVersion ¶
func (b *Builder[D]) ConditionVersion(name string, version string, condition GoCondition[D]) GoConditionRef
ConditionVersion registers a retained condition implementation at an explicit version.
func (*Builder[D]) Location ¶
func (b *Builder[D]) Location(name string, get GoValue[D], set GoLocation[D]) GoLocationRef
Location registers a named readable/writable location at the Builder's default Version.
func (*Builder[D]) LocationVersion ¶
func (b *Builder[D]) LocationVersion(name string, version string, get GoValue[D], set GoLocation[D]) GoLocationRef
LocationVersion registers a retained location implementation at an explicit version.
func (*Builder[D]) Value ¶
func (b *Builder[D]) Value(name string, value GoValue[D]) GoValueRef
Value registers a named value producer at the Builder's default Version.
func (*Builder[D]) ValueVersion ¶
func (b *Builder[D]) ValueVersion(name string, version string, value GoValue[D]) GoValueRef
ValueVersion registers a retained value implementation at an explicit version.
type CallDefinition ¶
type CallDefinition struct {
Function FunctionRef `json:"function"`
}
CallDefinition invokes one named, versioned host behavior.
type CancelDefinition ¶
type CancelDefinition struct {
SendID Identifier `json:"sendID,omitempty"`
SendIDExpr *Expression `json:"sendIDExpr,omitempty"`
}
CancelDefinition cancels a delayed send selected by either a static ID or a datamodel expression.
type Chart ¶
type Chart struct {
// contains filtered or unexported fields
}
Chart is an immutable, validated, indexed chart definition produced by Build. It is safe for concurrent use by multiple Instances.
func Build ¶
func Build(root StateDefinition, model Datamodel, opts ...BuildOption) (*Chart, error)
Build assembles a canonical Go-authored Definition and sends it through the same compiler used by decoded or edited definitions.
func Compile ¶
func Compile(definition Definition, model Datamodel) (*Chart, error)
Compile validates and normalizes definition, compiles all model-owned expressions, and lowers it to an immutable Chart.
func (*Chart) Datamodel ¶
Datamodel returns the compiler used to build this chart. Actor registries retain it to compile complete replacement definitions and resolve retained artifacts without modifying an existing Chart.
func (*Chart) DatamodelProgram ¶
func (c *Chart) DatamodelProgram() DatamodelProgram
DatamodelProgram returns the immutable model program shared by this chart's instances.
func (*Chart) Definition ¶
func (c *Chart) Definition() Definition
Definition returns an independently editable copy of the normalized definition used to compile c.
func (*Chart) DefinitionArtifact ¶
func (c *Chart) DefinitionArtifact() DefinitionArtifact
DefinitionArtifact returns an immutable-storage representation of c that can be recompiled after a process restart. Returned byte slices are owned by the caller.
func (*Chart) ID ¶
func (c *Chart) ID() Identifier
ID returns the stable Definition identity used for publication and actor kinds. It is independent of the root state's structural ID.
func (*Chart) NewInstance ¶
NewInstance constructs an Instance with a fresh session from the chart's DatamodelProgram. The interpreter goroutine is not started until Start is called.
func (*Chart) Prepare ¶
Prepare validates this chart's statically declared runtime requirements against opts without creating a datamodel session or running behavior. Dynamic invoke type expressions are deliberately resolved at runtime.
func (*Chart) Rehydrate ¶
func (c *Chart) Rehydrate(ctx context.Context, log Log, snapshots SnapshotStore, sessionID SessionID, realIO IOProcessor, opts ...Option) (*Instance, error)
Rehydrate reconstructs a running Instance for sessionID: it loads the latest Checkpoint if one exists, then replays every subsequent Log entry. Real I/O, Logger calls, invocation starts, and live timers are suppressed until replay catches up. Each entry's Timestamp supplies logical time for delayed sends created while applying it, and a KindTimerFired entry consumes the corresponding pending send by SendID without logging the fire again. Finally, remaining timers are activated against the configured Clock -- including synchronously applying overdue sends -- and active invocations are reconciled before the returned Instance is considered live. Rehydrate reconstructs a running Instance using fresh sessions from the chart's DatamodelProgram. Snapshot model state is decoded into one fresh session; an incompatible cache is discarded before replay starts with another fresh session.
func (*Chart) Restore ¶
Restore reconstructs a paused Instance from snap with a fresh session from the chart's DatamodelProgram. The session owns decoding the opaque model snapshot bytes. The returned instance is not started.
func (*Chart) Revision ¶
func (c *Chart) Revision() RevisionID
Revision returns the deterministic identity of this compiled definition and datamodel program.
func (*Chart) States ¶
func (c *Chart) States() []Identifier
States returns every state's ID in document order.
type Checkpoint ¶
Checkpoint pairs a Snapshot with the Log sequence number it reflects. Seq == 0 means the Snapshot was taken independent of any Log.
type ChooseBranchDefinition ¶
type ChooseBranchDefinition struct {
Condition Expression `json:"condition"`
Actions []ExecutableBlock `json:"actions,omitempty"`
}
ChooseBranchDefinition is one condition and its ordered action blocks.
type ChooseDefinition ¶
type ChooseDefinition struct {
Branches []ChooseBranchDefinition `json:"branches"`
Else []ExecutableBlock `json:"else,omitempty"`
}
ChooseDefinition evaluates branches in order and executes the first true branch, or Else when none match.
type Clock ¶
Clock abstracts time so delayed-<send> timers can be replaced with compute-only bookkeeping during log replay (see Rehydrate), instead of arming real OS timers for events that already fired historically.
func NewRealClock ¶
func NewRealClock() Clock
NewRealClock returns the default Clock, backed by the real wall clock and time.AfterFunc.
type CompiledExpression ¶
type CompiledExpression any
CompiledExpression is an opaque immutable handle produced by a DatamodelProgram. The interpreter passes it back to that program's sessions without inspecting its concrete representation.
type DataBinding ¶
type DataBinding string
DataBinding controls when declarations receive their initial values. The zero value means DataBindingEarly.
const ( // DataBindingEarly initializes every declaration when a session starts. DataBindingEarly DataBinding = "early" // DataBindingLate initializes a declaration immediately before its owning // state is entered for the first time. DataBindingLate DataBinding = "late" )
type DataDefinition ¶
type DataDefinition struct {
ID Identifier `json:"id"`
Source string `json:"source,omitempty"`
Expr *Expression `json:"expr,omitempty"`
Content *Expression `json:"content,omitempty"`
}
DataDefinition declares one model-owned data item. Source, Expr, and Content are mutually exclusive initialization modes; all three may be absent to declare an initially empty item. Declarations retain their order.
type Datamodel ¶
type Datamodel interface {
Name() Identifier
Compile(definition *Definition) (DatamodelProgram, error)
}
Datamodel compiles syntax-neutral definitions for one model implementation. Compile must not mutate definition. It returns an immutable program only after every model-owned expression has been validated and compiled.
type DatamodelProgram ¶
type DatamodelProgram interface {
// Fingerprint returns deterministic implementation identity used as chart
// revision material. It must be non-empty and restart-stable for equivalent
// programs. Callers must treat the returned bytes as immutable.
Fingerprint() []byte
// ResolveExpression returns the immutable handle compiled for expression.
// It rejects expressions that were not part of the compiled Definition.
ResolveExpression(Expression) (CompiledExpression, error)
// ResolveFunction returns the immutable executable handle compiled for a
// named host-function reference in the Definition.
ResolveFunction(FunctionRef) (CompiledExpression, error)
// ResolveDataLocation returns an assignable handle for a declared data ID.
// This lets the syntax-neutral chart compiler implement ordered early and
// late initialization and foreach bindings without knowing the model.
ResolveDataLocation(Identifier) (CompiledExpression, error)
// NewSession creates fresh mutable model state owned by one Instance.
NewSession(SessionOptions) (DatamodelSession, error)
}
DatamodelProgram is immutable compiled model state shared safely by every instance of one chart revision.
type DatamodelSession ¶
type DatamodelSession interface {
EvaluateBoolean(ExecContext, CompiledExpression) (bool, error)
EvaluateValue(ExecContext, CompiledExpression) (Value, error)
Assign(ExecContext, CompiledExpression, Value) error
Execute(ExecContext, CompiledExpression) error
ForEach(ExecContext, CompiledExpression, IterationBindings, func() error) error
// Inspect returns an independently owned canonical representation of the
// application-owned model state.
Inspect() (Value, error)
// EncodeSnapshot returns opaque, model-owned cache bytes.
EncodeSnapshot() ([]byte, error)
// DecodeSnapshot atomically replaces this fresh session's restorable model
// state. A failed session is closed and discarded rather than reused.
DecodeSnapshot([]byte) error
// Close releases model resources. Instance calls it exactly once.
Close() error
}
DatamodelSession owns exactly one Instance's mutable model state and any model runtime resources. Methods return ordinary Go errors; only the interpreter translates them into statechart error events and abort rules. Implementations are single-owner and need not be safe for concurrent use.
type Definition ¶
type Definition struct {
ID Identifier `json:"id"`
Name string `json:"name,omitempty"`
Datamodel Identifier `json:"datamodel"`
RevisionSalt string `json:"revisionSalt,omitempty"`
DataBinding DataBinding `json:"dataBinding,omitempty"`
Data []DataDefinition `json:"data,omitempty"`
Root StateDefinition `json:"root"`
}
Definition is a complete, syntax-neutral statechart program. It is mutable authoring/inspection data, unlike the immutable compiled Chart. Definition contains no callbacks, runtime pointers, compiled indexes, or syntax bytes.
func (Definition) CanonicalBytes ¶
func (d Definition) CanonicalBytes() ([]byte, error)
CanonicalBytes returns deterministic, versioned bytes suitable for chart revision material. The encoding is internal: authoring surfaces should translate to and from Definition rather than expose this format.
The canonical form resolves generated state IDs and default transition types on a clone. It does not mutate d.
func (Definition) Clone ¶
func (d Definition) Clone() Definition
Clone returns a deep, independently editable copy.
func (Definition) Validate ¶
func (d Definition) Validate() error
Validate performs syntax-neutral structural validation. Datamodel-specific expression checking belongs to Datamodel compilation, not this method. Validation assigns generated IDs only on a private clone.
type DefinitionArtifact ¶
type DefinitionArtifact struct {
Revision RevisionID
RevisionEnvelopeVersion uint32
ChartID Identifier // stable Definition.ID, independent of the root state's structural ID
Datamodel Identifier
CanonicalDefinition []byte
ProgramFingerprint []byte
}
DefinitionArtifact is the deterministic data required to recompile one Chart revision after a process restart. Go functions are represented only by the named/versioned references in CanonicalDefinition; the process must supply their implementations through the selected Datamodel.
func (DefinitionArtifact) Clone ¶
func (a DefinitionArtifact) Clone() DefinitionArtifact
Clone returns a deep copy whose byte slices are independently owned.
func (DefinitionArtifact) Compile ¶
func (a DefinitionArtifact) Compile(model Datamodel) (*Chart, error)
Compile validates a, resolves its references through model, and verifies that recompilation produces the exact persisted program fingerprint and revision. Applications must do this before replaying a pinned actor.
func (DefinitionArtifact) Definition ¶
func (a DefinitionArtifact) Definition() (Definition, error)
Definition decodes and validates an independently editable definition.
func (DefinitionArtifact) Equal ¶
func (a DefinitionArtifact) Equal(other DefinitionArtifact) bool
Equal reports whether every persisted field is byte-for-byte equal.
func (DefinitionArtifact) Validate ¶
func (a DefinitionArtifact) Validate() error
Validate checks canonical encoding, identity fields, envelope version, and revision integrity.
type DefinitionDeleteResult ¶
type DefinitionDeleteResult uint8
DefinitionDeleteResult describes an atomic reference-check-and-delete.
const ( DefinitionDeleted DefinitionDeleteResult = iota + 1 DefinitionReferenced DefinitionNotFound )
type DefinitionError ¶
DefinitionError reports a structural definition error at a stable public traversal path.
func (*DefinitionError) Error ¶
func (e *DefinitionError) Error() string
func (*DefinitionError) Unwrap ¶
func (e *DefinitionError) Unwrap() error
type DefinitionPutResult ¶
type DefinitionPutResult uint8
DefinitionPutResult describes an idempotent immutable artifact write.
const ( DefinitionStored DefinitionPutResult = iota + 1 DefinitionUnchanged )
type DefinitionStore ¶
type DefinitionStore interface {
// PutDefinition validates artifact and stores it when its revision is
// absent. An exact retry returns DefinitionUnchanged. If the revision is
// already associated with any different field or byte, it returns
// ErrDefinitionCollision without changing the stored artifact.
PutDefinition(ctx context.Context, artifact DefinitionArtifact) (DefinitionPutResult, error)
// GetDefinition returns a validated, independently owned artifact. Corrupt
// stored data returns ErrInvalidDefinitionArtifact rather than found=true.
GetDefinition(ctx context.Context, revision RevisionID) (artifact DefinitionArtifact, found bool, err error)
// DeleteDefinitionIfUnreferenced atomically checks non-terminal actor
// references and deletes revision only when none exist. It must linearize
// with BeginActor on the same storage implementation. Publication state is
// intentionally separate; callers must not request deletion of a current
// revision.
DeleteDefinitionIfUnreferenced(ctx context.Context, revision RevisionID) (DefinitionDeleteResult, error)
}
DefinitionStore persists immutable, content-addressed chart definitions. Implementations must copy caller-owned bytes on writes and returns.
type DeliveryID ¶
type DeliveryID string
DeliveryID is an opaque, stable identity for one external delivery. Applications must not interpret it; durable transports use it for inbox deduplication and as an idempotency key.
type Dispatcher ¶
Dispatcher lets an IOProcessor deliver events back into whichever Instance attached it -- fired invoke results, responses, or messages from other sessions. Instance implements Dispatcher.
type DoneDataDefinition ¶
type DoneDataDefinition struct {
Params []ParamDefinition `json:"params,omitempty"`
Content *Expression `json:"content,omitempty"`
}
DoneDataDefinition computes the payload of a final state's done event. Params and Content are mutually exclusive; Content is one whole payload.
type DurableLog ¶
type DurableLog interface {
Log
// AppendIngress atomically deduplicates deliveryID and appends entry. When
// the implementation also stores ActorMetadata for entry.SessionID, it
// must linearize with MarkActorTerminal and return ErrActorTerminal instead
// of appending after that actor is terminal.
AppendIngress(ctx context.Context, entry LogEntry, deliveryID DeliveryID) (seq uint64, appended bool, err error)
StoreOutbound(ctx context.Context, message OutboundMessage) error
ResolveOutbound(ctx context.Context, sessionID SessionID, deliveryID DeliveryID, result OutboundResult) error
Outbounds(ctx context.Context, sessionID SessionID) ([]OutboundMessage, error)
}
DurableLog combines the WAL inbox/dedup and durable outbox boundary.
type EncodedEvent ¶
type EncodedEvent struct {
Name Identifier `json:"name"`
Type EventType `json:"type"`
SendID Identifier `json:"send_id,omitempty"`
Origin Identifier `json:"origin,omitempty"`
OriginType Identifier `json:"origin_type,omitempty"`
InvokeID Identifier `json:"invoke_id,omitempty"`
DeliveryID DeliveryID `json:"delivery_id,omitempty"`
Data []byte `json:"data"`
}
EncodedEvent is the flat, JSON/SQL-safe encoding of an Event, used by Snapshot's JSON envelope and durable stores. Data is always the canonical Value marshal representation, including for null.
func EncodeEvent ¶
func EncodeEvent(ev Event) (EncodedEvent, error)
EncodeEvent flattens ev using Value's canonical, versioned bytes.
type EntryKind ¶
type EntryKind string
EntryKind distinguishes durable inputs and the session-start boundary. Everything else a chart does (<raise>, <cancel>, history recording, new transitions) is pure, deterministic recomputation given the initial configuration and these entries (see Rehydrate in replay.go).
const ( // KindSessionStarted is written before a durable actor is started for the // first time. It is a no-op during replay, but proves initial executable // content may already have run -- particularly an initial <invoke> -- even // when the process crashed before the actor received its first message. // Its Timestamp also anchors initial delayed sends to the original start // time instead of the recovery time. KindSessionStarted EntryKind = "session_started" // KindExternalEvent records an explicit application call, Instance.Send. KindExternalEvent EntryKind = "external_event" // KindTimerFired records a delayed <send>'s timer elapsing -- this // originates outside the deterministic microstep computation (a real // wall-clock timer) and must be replayed as data, never re-derived by // letting a real timer re-elapse. KindTimerFired EntryKind = "timer_fired" )
type Event ¶
type Event struct {
Name Identifier
Type EventType
Data Value
SendID Identifier
Origin Identifier
OriginType Identifier
InvokeID Identifier
DeliveryID DeliveryID
}
Event is a message flowing through a chart's internal or external queue. It mirrors the mandatory fields of an SCXML event (5.10.1). Data is the canonical payload representation shared by datamodel, actor, process, and durability boundaries. Its zero value is canonical null.
func DecodeEvent ¶
func DecodeEvent(enc EncodedEvent) (Event, error)
DecodeEvent reconstructs an Event from canonical Value bytes.
type EventType ¶
type EventType uint8
EventType classifies where an Event originated, per SCXML 5.10.1.
const ( // EventExternal events arrived via the blocking external queue (an // application Send, or a message from another session/processor). EventExternal EventType = iota // EventInternal events were raised via <raise> or sent to "#_internal". EventInternal // EventPlatform events are placed by the interpreter itself, e.g. // error.execution, error.communication, done.state.<id>. EventPlatform )
type ExecContext ¶
type ExecContext struct {
// contains filtered or unexported fields
}
ExecContext exposes the runtime context supplied to datamodel operations.
func (ExecContext) Cancel ¶
func (ec ExecContext) Cancel(sendID Identifier)
Cancel best-effort cancels every pending delayed Send with the author-given sendID, mirroring <cancel>. An unknown or already-fired sendID is a no-op.
func (ExecContext) Event ¶
func (ec ExecContext) Event() (Event, bool)
Event returns the event currently being processed, if any. Per SCXML 5.10.1, _event is unbound before the first event is processed.
func (ExecContext) IOProcessorLocation ¶
func (ec ExecContext) IOProcessorLocation(typ Identifier) (location Location, ok bool)
IOProcessorLocation returns the Location advertised for typ among IOProcessors(), the common case of wanting one specific processor's own address (e.g. to embed in outgoing event data so a peer can reply) -- callers don't need to write that lookup loop themselves. ok is false if no processor of that Type is advertised, in which case location is the zero Location.
func (ExecContext) IOProcessors ¶
func (ec ExecContext) IOProcessors() []IOProcessorInfo
IOProcessors reports every Event I/O Processor available to this session, per SCXML 5.10's _ioprocessors -- specifically, the ones with an address another session could use to reach this one (see IOProcessorDescriber). It is empty/nil if the configured IOProcessor has nothing to advertise.
func (ExecContext) In ¶
func (ec ExecContext) In(id Identifier) bool
In implements the SCXML In() predicate: reports whether id is a member of the current configuration.
func (ExecContext) Log ¶
func (ec ExecContext) Log(label string, data Value)
Log records one diagnostic entry, mirroring <log>: label names it, data carries canonical data. It is routed to whichever Logger the owning Instance was configured with (see WithLogger), and is a silent no-op if none was. Unlike Send, Log never produces an event another transition can match against, and unlike Raise, it never touches either event queue -- it exists purely for a human or a log aggregator to read.
func (ExecContext) Name ¶
func (ec ExecContext) Name() string
Name returns the SCXML document name, bound for this session's entire lifetime, per SCXML 5.10's _name.
func (ExecContext) PlatformVariables ¶
func (ec ExecContext) PlatformVariables() map[string]any
PlatformVariables returns a fresh binding map for SCXML's protected _x system variable. Opaque values are shared, but the map itself is not.
func (ExecContext) Raise ¶
func (ec ExecContext) Raise(ev Event)
Raise enqueues ev on the internal queue, as <raise> would. ev.Type is always overwritten to EventInternal.
func (ExecContext) Send ¶
func (ec ExecContext) Send(name Identifier, opts SendOptions)
Send schedules delivery of an event, mirroring <send>: immediately (if opts.Delay is zero) or after opts.Delay elapses. Dispatch failures are never returned here -- per SCXML, invalid/unsupported requests become error.execution and delivery failures become error.communication on the internal queue, rather than Go errors propagated to the caller.
func (ExecContext) SessionID ¶
func (ec ExecContext) SessionID() string
SessionID returns this session's id, bound for its entire lifetime, per SCXML 5.10's _sessionid. See WithSessionID and WithIDGenerator (instance.go) for how it is minted or supplied.
type Executable ¶
type Executable struct {
Kind ExecutableKind `json:"kind"`
Raise *RaiseDefinition `json:"raise,omitempty"`
Send *SendDefinition `json:"send,omitempty"`
Cancel *CancelDefinition `json:"cancel,omitempty"`
Log *LogDefinition `json:"log,omitempty"`
Assign *AssignDefinition `json:"assign,omitempty"`
Choose *ChooseDefinition `json:"choose,omitempty"`
ForEach *ForEachDefinition `json:"foreach,omitempty"`
Script *ScriptDefinition `json:"script,omitempty"`
Call *CallDefinition `json:"call,omitempty"`
Extension *ExtensionDefinition `json:"extension,omitempty"`
}
Executable is a closed tagged union. Exactly one payload pointer must be present and it must match Kind. Constructors below create that outer union; Definition.Validate validates both the union and its payload.
func CancelSend ¶
func CancelSend(sendID Identifier) Executable
CancelSend creates executable content that cancels a delayed send by ID.
func LogValue ¶
func LogValue(label string, expression Expression) Executable
LogValue creates diagnostic logging executable content.
func NewAssignExecutable ¶
func NewAssignExecutable(value AssignDefinition) Executable
NewAssignExecutable returns an assignment executable with a valid outer union.
func NewCallExecutable ¶
func NewCallExecutable(value CallDefinition) Executable
NewCallExecutable returns a host-function call executable with a valid outer union.
func NewCancelExecutable ¶
func NewCancelExecutable(value CancelDefinition) Executable
NewCancelExecutable returns a cancel executable with a valid outer union.
func NewChooseExecutable ¶
func NewChooseExecutable(value ChooseDefinition) Executable
NewChooseExecutable returns a conditional executable with a valid outer union.
func NewExtensionExecutable ¶
func NewExtensionExecutable(value ExtensionDefinition) Executable
NewExtensionExecutable returns an extension executable with a valid outer union.
func NewForEachExecutable ¶
func NewForEachExecutable(value ForEachDefinition) Executable
NewForEachExecutable returns an iteration executable with a valid outer union.
func NewLogExecutable ¶
func NewLogExecutable(value LogDefinition) Executable
NewLogExecutable returns a log executable with a valid outer union.
func NewRaiseExecutable ¶
func NewRaiseExecutable(value RaiseDefinition) Executable
NewRaiseExecutable returns a raise executable with a valid outer union.
func NewScriptExecutable ¶
func NewScriptExecutable(value ScriptDefinition) Executable
NewScriptExecutable returns a model-script executable with a valid outer union.
func NewSendExecutable ¶
func NewSendExecutable(value SendDefinition) Executable
NewSendExecutable returns a send executable with a valid outer union.
func Raise ¶
func Raise(event Identifier, data ...Expression) Executable
Raise creates executable content that raises an internal event. An optional expression computes its payload.
func Send ¶
func Send(event Identifier, options ...SendOption) Executable
Send creates serializable event-delivery executable content.
type ExecutableBlock ¶
type ExecutableBlock []Executable
ExecutableBlock is one ordered executable-content block. Blocks remain distinct because an evaluation error aborts only its containing block.
type ExecutableKind ¶
type ExecutableKind string
ExecutableKind identifies one first-class executable-content node.
const ( ExecutableRaise ExecutableKind = "raise" ExecutableSend ExecutableKind = "send" ExecutableCancel ExecutableKind = "cancel" ExecutableLog ExecutableKind = "log" ExecutableAssign ExecutableKind = "assign" ExecutableChoose ExecutableKind = "choose" ExecutableForEach ExecutableKind = "foreach" ExecutableScript ExecutableKind = "script" ExecutableCall ExecutableKind = "call" ExecutableExtension ExecutableKind = "extension" )
type Expression ¶
type Expression struct {
Kind Identifier `json:"kind"`
Data Value `json:"data"`
}
Expression is syntax-neutral, datamodel-owned program data. Kind selects an expression form understood by a Datamodel; Data contains that form's canonical operands or source. Structural validation checks only that Kind and Data are well formed. A datamodel validates their meaning at compile time.
func GoData ¶
func GoData(id Identifier) Expression
GoData returns a readable and writable expression for a declared data ID.
func GoLiteral ¶
func GoLiteral(v Value) Expression
GoLiteral returns a canonical literal expression.
func (Expression) Clone ¶
func (e Expression) Clone() Expression
Clone returns an independently editable expression.
type ExtensionDefinition ¶
type ExtensionDefinition struct {
Namespace string `json:"namespace"`
Name string `json:"name"`
Data Value `json:"data"`
}
ExtensionDefinition preserves executable content owned by an extension. Namespace and Name identify the extension; Data is its canonical payload.
type ForEachDefinition ¶
type ForEachDefinition struct {
Array Expression `json:"array"`
Item Identifier `json:"item"`
Index Identifier `json:"index,omitempty"`
Actions []ExecutableBlock `json:"actions,omitempty"`
}
ForEachDefinition iterates Array with datamodel-owned Item and optional Index bindings.
type FunctionRef ¶
type FunctionRef struct {
Name Identifier `json:"name"`
Version string `json:"version"`
Args []Expression `json:"args,omitempty"`
}
FunctionRef identifies host behavior without storing a Go function. Name and Version are stable definition data; Args are datamodel expressions evaluated according to the operation that owns the reference.
type GoAction ¶
type GoAction[D any] func(*D, ExecContext, []Value) error
GoAction is a typed host action used by both script expressions and named call nodes.
type GoActionRef ¶
type GoActionRef struct {
// contains filtered or unexported fields
}
GoActionRef creates serializable script expressions and call references.
func (GoActionRef) Call ¶
func (r GoActionRef) Call(args ...Expression) Executable
Call returns this registered action as an explicit named call node.
func (GoActionRef) Do ¶
func (r GoActionRef) Do(args ...Expression) Executable
Do returns this registered action as a serializable executable node.
func (GoActionRef) Expression ¶
func (r GoActionRef) Expression(args ...Expression) Expression
func (GoActionRef) Function ¶
func (r GoActionRef) Function(args ...Expression) FunctionRef
type GoCondition ¶
type GoCondition[D any] func(*D, ExecContext, []Value) (bool, error)
GoCondition is a typed host condition. Args are the evaluated expressions attached to the reference at its use site.
type GoConditionRef ¶
type GoConditionRef struct {
// contains filtered or unexported fields
}
GoConditionRef creates serializable condition expressions without repeating the registered behavior's name or version.
func (GoConditionRef) Expression ¶
func (r GoConditionRef) Expression(args ...Expression) Expression
func (GoConditionRef) If ¶
func (r GoConditionRef) If(args ...Expression) Expression
If returns this registered condition as a serializable expression.
type GoInspectionCodec ¶
GoInspectionCodec converts application-owned D into canonical inspector data. It is independent of the opaque snapshot codec. Implementations must not mutate D; the returned Value is cloned before it leaves the session.
type GoLocation ¶
type GoLocation[D any] func(*D, ExecContext, Value, []Value) error
GoLocation writes a canonical value to a typed host location.
type GoLocationRef ¶
type GoLocationRef struct {
// contains filtered or unexported fields
}
GoLocationRef creates serializable readable and writable location expressions.
func (GoLocationRef) At ¶
func (r GoLocationRef) At(args ...Expression) Expression
At returns this registered readable/writable location as a serializable expression.
func (GoLocationRef) Expression ¶
func (r GoLocationRef) Expression(args ...Expression) Expression
type GoModel ¶
type GoModel[D any] struct { // contains filtered or unexported fields }
GoModel is the default datamodel. It combines a typed D factory with a model-local registry of stable, named host behavior.
func NewGoModel ¶
func NewGoModel[D any](factory func() *D, options ...GoModelOption[D]) *GoModel[D]
NewGoModel creates an independently scoped Go datamodel registry.
func (*GoModel[D]) Action ¶
func (m *GoModel[D]) Action(n Identifier, v string, fn GoAction[D]) (GoActionRef, error)
Action is an alias for Script; its handle supports both Script expressions and Call references.
func (*GoModel[D]) Compile ¶
func (m *GoModel[D]) Compile(def *Definition) (DatamodelProgram, error)
func (*GoModel[D]) Condition ¶
func (m *GoModel[D]) Condition(n Identifier, v string, fn GoCondition[D]) (GoConditionRef, error)
Condition registers one condition implementation and returns its reusable reference.
func (*GoModel[D]) Location ¶
func (m *GoModel[D]) Location(n Identifier, v string, get GoValue[D], set GoLocation[D]) (GoLocationRef, error)
Location registers a reusable readable and writable host location.
func (*GoModel[D]) Name ¶
func (*GoModel[D]) Name() Identifier
func (*GoModel[D]) Script ¶
func (m *GoModel[D]) Script(n Identifier, v string, fn GoAction[D]) (GoActionRef, error)
Script registers one action implementation and returns its reusable reference.
func (*GoModel[D]) TextExpressionCodec ¶
func (*GoModel[D]) TextExpressionCodec() TextExpressionCodec
TextExpressionCodec returns the default text codec for this GoModel.
func (*GoModel[D]) Value ¶
func (m *GoModel[D]) Value(n Identifier, v string, fn GoValue[D]) (GoValueRef, error)
Value registers one value producer and returns its reusable reference.
type GoModelOption ¶
GoModelOption configures a GoModel.
func WithGoInspectionCodec ¶
func WithGoInspectionCodec[D any](codec GoInspectionCodec[D]) GoModelOption[D]
WithGoInspectionCodec replaces the default JSON-shaped conversion for D.
func WithGoSnapshotCodec ¶
func WithGoSnapshotCodec[D any](codec GoSnapshotCodec[D]) GoModelOption[D]
WithGoSnapshotCodec replaces the default encoding/json codec for D.
type GoSnapshotCodec ¶
type GoSnapshotCodec[D any] struct { Encode func(*D) ([]byte, error) Decode func([]byte) (*D, error) }
GoSnapshotCodec controls the D portion of a session snapshot. Decode must construct a replacement value. The default is encoding/json. Applications whose D has a non-deterministic MarshalJSON must provide a deterministic codec because snapshot and revision reproducibility otherwise cannot be guaranteed.
type GoTextExpressionCodec ¶
type GoTextExpressionCodec struct{}
GoTextExpressionCodec represents GoModel expressions as deterministic JSON text. The text contains stable registered function names and versions, never Go function pointers. It can therefore be inspected, edited, and resolved again against the same model-local registry during compilation.
func (GoTextExpressionCodec) FormatExpression ¶
func (GoTextExpressionCodec) FormatExpression(_ TextExpressionRole, expression Expression) (string, error)
FormatExpression encodes one GoModel expression without changing its canonical Value representation.
func (GoTextExpressionCodec) ParseExpression ¶
func (GoTextExpressionCodec) ParseExpression(_ TextExpressionRole, text string) (Expression, error)
ParseExpression decodes one GoModel expression and rejects trailing input.
type GoValue ¶
type GoValue[D any] func(*D, ExecContext, []Value) (Value, error)
GoValue is a typed host value producer or location reader.
type GoValueRef ¶
type GoValueRef struct {
// contains filtered or unexported fields
}
GoValueRef creates serializable value expressions.
func (GoValueRef) Expression ¶
func (r GoValueRef) Expression(args ...Expression) Expression
func (GoValueRef) Get ¶
func (r GoValueRef) Get(args ...Expression) Expression
Get returns this registered value computation as a serializable expression.
type HistoryKind ¶
type HistoryKind uint8
HistoryKind distinguishes shallow from deep history, per SCXML "history" element semantics.
const ( Shallow HistoryKind = iota Deep )
type IDGenerator ¶
type IDGenerator interface {
NewID() SessionID
}
IDGenerator mints a fresh id, such as an Instance's SCXML 5.10 _sessionid. Swapping it for a deterministic stand-in, the way Clock abstracts time, lets a test assert against a specific id instead of only checking that some unpredictable text was assigned.
type IDGeneratorFunc ¶
type IDGeneratorFunc func() SessionID
IDGeneratorFunc adapts a plain func into an IDGenerator, mirroring http.HandlerFunc.
type IDLocationFunc ¶
type IDLocationFunc func(ExecContext, Identifier) error
IDLocationFunc is the Go datamodel profile's equivalent of SCXML's idlocation expression. It synchronously assigns a generated send or invoke ID while that element is being evaluated. Returning an error or panicking produces error.execution and aborts the element.
type IOProcessor ¶
type IOProcessor interface {
// Attach is called once, before Start, giving the processor a way to
// deliver events back in later via Dispatcher.
Attach(d Dispatcher)
// Send dispatches req immediately. It is called synchronously, in-line,
// while executing a microstep's action list, to preserve SCXML's
// lock-step ordering of executable content -- implementations MUST
// return quickly (hand off to their own goroutine and return) rather
// than blocking on real delivery.
Send(ctx context.Context, req SendRequest) error
}
IOProcessor is the seam every real side effect goes through: anything that reaches outside the process, or otherwise isn't pure and deterministic, is routed through here, so the interpreter core stays pure everywhere else. A replay-safe caller can swap in a suppressing implementation (see NoopIOProcessor and Rehydrate) without the interpreter noticing any difference.
var NoopIOProcessor IOProcessor = noopIOProcessor{}
NoopIOProcessor suppresses all outbound dispatch while reporting success. Replaying Instances use it so real-world effects are never repeated when reconstructing state from a Log (see replay.go).
type IOProcessorDescriber ¶
type IOProcessorDescriber interface {
IOProcessors() []IOProcessorInfo
}
IOProcessorDescriber is implemented by an IOProcessor that has an address to advertise for the current session -- one another session could use to reach it. An IOProcessor with no transport of its own (NoopIOProcessor, LocalIOProcessor) simply doesn't implement this: ExecContext.IOProcessors reports no entries for it rather than guessing at an address.
type IOProcessorInfo ¶
type IOProcessorInfo struct {
Type Identifier
Location Location
}
IOProcessorInfo describes one Event I/O Processor available to the current session, per SCXML 5.10's _ioprocessors: Type is the same value an action would put in SendOptions.Type / that arrives as SendRequest.Type to select this processor, and Location is the address a *different* session must set as its own SendOptions.Target in order to reach this session through that processor.
type Identifier ¶
type Identifier string
Identifier is a dot-segmented, case-sensitive name. It is used uniformly for state IDs, event names, event descriptors (the "event" attribute of a transition), and SCXML send targets (including the special "#_..." forms).
const ( ErrEventExecution Identifier = "error.execution" ErrEventCommunication Identifier = "error.communication" )
Platform event names placed on the internal queue by the interpreter itself, per SCXML 5.10.2 / C.1. These are ordinary event names, not Go errors: a chart reacts to them with transitions exactly like any other event.
const SCXMLEventProcessor Identifier = "http://www.w3.org/TR/scxml/#SCXMLEventProcessor"
SCXMLEventProcessor is the mandatory SCXML Event I/O Processor type and the default for a send that does not specify a type.
const SCXMLEventProcessorAlias Identifier = "scxml"
SCXMLEventProcessorAlias is the short SCXML processor name and the value required for Event.OriginType by Appendix C.1.
const SCXMLInvokeType Identifier = "http://www.w3.org/TR/scxml/"
SCXMLInvokeType is the standard handler type used when an invocation does not declare a type. Environments may bind it to a child-chart resolver.
func NewIdentifier ¶
func NewIdentifier(s string) (Identifier, error)
NewIdentifier validates s and returns it as an Identifier. Use this for untrusted input (e.g. values read back from a database or external message); identifiers built from Go source literals in chart definitions can be used directly via the defined string type without calling this.
func PlatformErrorDetails ¶
func PlatformErrorDetails(value Value) (classification Identifier, message string, ok bool)
PlatformErrorDetails extracts a canonical platform error.
func (Identifier) Compare ¶
func (id Identifier) Compare(other Identifier) int
Compare gives a total, deterministic lexicographic order over Identifier values, for diagnostics, sorted dumps, and deterministic map-key iteration. It is NOT SCXML "document order" -- document order is an explicit sequence number assigned by Build, tracking declaration order in the Go builder calls, and must never be derived by sorting Identifiers.
func (Identifier) MarshalText ¶
func (id Identifier) MarshalText() ([]byte, error)
MarshalText implements encoding.TextMarshaler.
func (Identifier) Matches ¶
func (id Identifier) Matches(eventName Identifier) bool
Matches reports whether id, used as an event descriptor, matches the event name eventName, per SCXML 3.12.1: a descriptor matches if it is an exact match or a token-prefix match of the event name. A bare "*" matches any event name; a trailing ".*" or "." is sugar with the same effect as the bare token-prefix it leaves behind once trimmed.
func (*Identifier) Scan ¶
func (id *Identifier) Scan(src any) error
Scan implements database/sql.Scanner.
func (*Identifier) UnmarshalText ¶
func (id *Identifier) UnmarshalText(text []byte) error
UnmarshalText implements encoding.TextUnmarshaler.
type Instance ¶
type Instance struct {
// contains filtered or unexported fields
}
Instance is one running chart: a single goroutine driving the interpreter algorithm, exposed through plain method calls. No channel type ever appears in this public surface -- Send and Stop internally hand a request to the actor's own goroutine and wait for it to be accepted, but that plumbing is entirely unexported.
func (*Instance) Checkpoint ¶
Checkpoint calls save with a stable Snapshot on the Instance's own goroutine. No event or timer can be applied until save returns, allowing a durable runtime to pair the Snapshot atomically with its current Log sequence. A successful save stops the Instance at that exact boundary; a failed save leaves it running so checkpointing can be retried. Because save runs on the actor goroutine, it must not call back into this Instance.
func (*Instance) Configuration ¶
func (in *Instance) Configuration() []Identifier
Configuration returns the active state IDs as of the last completed macrostep.
func (*Instance) Deliver ¶
Deliver implements Dispatcher, letting an attached IOProcessor feed events back into this Instance exactly as any other caller would via Send.
func (*Instance) Done ¶
func (in *Instance) Done() <-chan struct{}
Done returns a channel that's closed once the interpreter goroutine has exited -- a top-level final state was reached, Stop was called, or a fatal error occurred -- the same condition Wait blocks on. Unlike Wait, Done never blocks by itself: it's meant for a non-blocking check (a select against it with a default case) or as one case among several in a larger select, e.g. an embedder deciding whether an Instance that has stopped on its own is now safe to discard.
func (*Instance) Err ¶
Err returns the sticky terminal error, or nil while the instance is healthy (including while it is still running).
func (*Instance) HasActiveInvokes ¶
HasActiveInvokes reports whether at least one <invoke> currently belongs to this Instance's active configuration -- true for as long as its invoking state remains entered, regardless of whether the invoked service itself has already finished (SCXML 6.4.2: cancellation on state exit, not on the service's own completion, is what ends an invocation). Snapshot and Rehydrate cannot capture or restart a real invocation (ADR 0010), so the actors package uses this to avoid paging out (and later Rehydrating) an actor while one is running -- see System's eviction paths.
func (*Instance) ID ¶
ID returns this Instance's session id (SCXML 5.10's _sessionid). In order of precedence, it is an explicit WithSessionID, an id recorded in the Snapshot Restore was called with, or one minted by the configured IDGenerator. It is stable for the lifetime of the Instance.
func (*Instance) Inspect ¶
func (in *Instance) Inspect(ctx context.Context) (InstanceInspection, error)
Inspect returns a stable live view without invoking snapshot codecs.
func (*Instance) Result ¶
Result returns the data produced by the top-level final state. It is available after the Instance has completed naturally; a stopped or still running Instance has no final result.
func (*Instance) Send ¶
Send places ev on the external queue, regardless of its incoming Type, and blocks until the resulting macrostep(s) have been fully processed and Configuration() reflects them, honoring ctx.
func (*Instance) Snapshot ¶
Snapshot captures this Instance's current state (safely, by running on the interpreter's own goroutine), suitable for persisting and later passing to Restore.
func (*Instance) Start ¶
Start spawns the interpreter goroutine, enters the chart's initial configuration, and drains to the first stable point before returning. ctx bounds only this handshake, not the goroutine's subsequent lifetime.
type InstanceInspection ¶
type InstanceInspection struct {
SessionID SessionID
Revision RevisionID
Running bool
Configuration []Identifier
HistoryValue map[Identifier][]Identifier
Datamodel Value
InternalQueue []Event
ExternalQueue []Event
PendingSends []PendingSend
ActiveInvokes []ActiveInvoke
}
InstanceInspection is an independently owned, point-in-time view captured at a stable macrostep boundary on an Instance's goroutine.
type InvokeDefinition ¶
type InvokeDefinition struct {
DefinitionID Identifier `json:"definitionId,omitempty"`
ID Identifier `json:"id,omitempty"`
IDLocation *Expression `json:"idLocation,omitempty"`
Type string `json:"type,omitempty"`
TypeExpr *Expression `json:"typeExpr,omitempty"`
Src string `json:"src,omitempty"`
SrcExpr *Expression `json:"srcExpr,omitempty"`
Params []ParamDefinition `json:"params,omitempty"`
Content *Expression `json:"content,omitempty"`
AutoForward bool `json:"autoForward,omitempty"`
Finalize []ExecutableBlock `json:"finalize,omitempty"`
}
InvokeDefinition contains invocation declaration data only. Src is a static source while SrcExpr is a datamodel expression; preserving both forms avoids making static source identity model-dependent. Content is one whole payload and is not a synthetic parameter map.
type InvokeHandler ¶
InvokeHandler implements one environment-provided invocation type. The runtime cancels ctx when the owning state exits and owns event delivery, completion, and error classification around the handler call.
type InvokeHandlerFactory ¶
type InvokeHandlerFactory func() InvokeHandler
InvokeHandlerFactory creates isolated mutable handler state for one start or resume. Registrations are Instance- or System-scoped, never global.
func InvokeChartHandler ¶
func InvokeChartHandler(chart *Chart, baseIO IOProcessor) InvokeHandlerFactory
InvokeChartHandler returns an environment-scoped handler factory for the standard child-chart invocation type. The child chart and fallback transport remain runtime capabilities; only the invocation source key belongs in a serializable InvokeDefinition. Child input should be modeled explicitly by the child definition rather than by replacing its model.
type InvokeHandlerFunc ¶
InvokeHandlerFunc adapts a function to InvokeHandler.
func (InvokeHandlerFunc) Start ¶
func (fn InvokeHandlerFunc) Start(ctx context.Context, request InvokeRequest, io InvokeIO) (Value, error)
type InvokeIO ¶
type InvokeIO struct {
// Deliver posts ev to the invoking chart's external event queue,
// tagged with this invocation's InvokeID, exactly as SCXML 6.4
// requires of events an invoked service returns. Safe to call from any
// goroutine at any time, including after the invocation has been
// cancelled (a no-op once cancelled, per SCXML 6.4.3: a cancelled
// invocation's events "MUST NOT" reach the invoking session).
Deliver func(Event)
// Incoming delivers events sent to this invocation from the chart --
// via Send(name, SendOptions{Target: "#_<invokeid>"}), SCXML 6.4.4's
// addressing form for talking back to a running invocation. Always
// non-nil; a service that never expects inbound traffic simply never
// reads from it.
Incoming <-chan Event
}
InvokeIO is an invoked service's only channel back into (and, for services that accept forwarded events, in from) the chart that invoked it -- the <invoke> analogue of IOProcessor for the rest of the world.
type InvokeOption ¶
type InvokeOption func(*InvokeDefinition)
InvokeOption appends serializable authoring data to an invocation.
func WithAutoForward ¶
func WithAutoForward() InvokeOption
WithAutoForward forwards each external event to the active invocation.
func WithFinalize ¶
func WithFinalize(actions ...Executable) InvokeOption
WithFinalize attaches executable blocks run before processing an event returned by this invocation. Each call creates one independent block.
func WithInvokeContent ¶
func WithInvokeContent(content Expression) InvokeOption
WithInvokeContent sets one whole invocation input expression.
func WithInvokeDefinitionID ¶
func WithInvokeDefinitionID(id Identifier) InvokeOption
WithInvokeDefinitionID sets the stable declaration identity used by snapshots and hot-deployment revision pinning.
func WithInvokeID ¶
func WithInvokeID(id Identifier) InvokeOption
WithInvokeID sets an explicit invoke ID, e.g. for targeting it later via SendOptions{Target: "#_" + id}. Left unset, an ID unique within the session is generated when the invocation actually starts.
func WithInvokeIDLocation ¶
func WithInvokeIDLocation(location Expression) InvokeOption
WithInvokeIDLocation stores a generated runtime ID in a model location.
func WithInvokeParams ¶
func WithInvokeParams(params ...ParamDefinition) InvokeOption
WithInvokeParams sets named invocation input expressions.
func WithInvokeSourceExpression ¶
func WithInvokeSourceExpression(expression Expression) InvokeOption
WithInvokeSourceExpression selects a handler source from the datamodel.
func WithInvokeTypeExpression ¶
func WithInvokeTypeExpression(expression Expression) InvokeOption
WithInvokeTypeExpression selects a handler type from the datamodel.
type InvokeRequest ¶
type InvokeRequest struct {
DefinitionID Identifier
ID Identifier
Type Identifier
Source string
Data Value
}
InvokeRequest is the fully evaluated, immutable input to one invocation. DefinitionID identifies the declaration across definition edits; ID is the runtime address visible to events and #_<invokeid> sends.
type IterationBindings ¶
type IterationBindings struct {
Item CompiledExpression
Index CompiledExpression
}
IterationBindings identifies model-owned locations receiving the current item and optional index during ForEach.
type LocalIOProcessor ¶
type LocalIOProcessor struct {
// contains filtered or unexported fields
}
LocalIOProcessor is the default IOProcessor for a single, non-distributed Instance: it has no transport for genuinely external targets and reports that honestly, rather than silently discarding. Internal/self dispatch never reaches an IOProcessor at all (see SendRequest), so this type has nothing to do for that traffic either.
func NewLocalIOProcessor ¶
func NewLocalIOProcessor() *LocalIOProcessor
NewLocalIOProcessor returns the default IOProcessor.
func (*LocalIOProcessor) Attach ¶
func (p *LocalIOProcessor) Attach(d Dispatcher)
func (*LocalIOProcessor) IOProcessors ¶
func (p *LocalIOProcessor) IOProcessors() []IOProcessorInfo
IOProcessors advertises this session's mandatory SCXML processor address.
func (*LocalIOProcessor) Send ¶
func (p *LocalIOProcessor) Send(ctx context.Context, req SendRequest) error
type Location ¶
type Location struct {
// contains filtered or unexported fields
}
Location is the address an IOProcessor advertises for the current session (IOProcessorInfo.Location) -- what a different session sets as its own SendOptions.Target to reach this one, per SCXML 5.10's _ioprocessors. It wraps a parsed net/url.URL, so a real network address (scheme, host, path) round-trips with genuine structure a real transport can inspect, while an opaque in-process token -- an actor's own dotted name, say -- is exactly as easy to construct as it always was: net/url does not require a scheme or host, so "locator-1" parses just as validly as "https://example.com/svc", and both round-trip through String() unchanged.
func LocationFromIdentifier ¶
func LocationFromIdentifier(id Identifier) Location
LocationFromIdentifier converts id directly to a Location. It never fails: id's own construction (NewIdentifier) already restricts it to characters that are always a valid URL path segment with no escaping needed, so parsing id's text can never produce an error here.
func NewLocation ¶
NewLocation parses s as a URL and returns the result. The only strings it rejects are genuinely malformed ones (bad percent-encoding, a stray control character) -- the absence of a scheme or host is not malformed, it is simply an opaque, schemeless Location.
type Log ¶
type Log interface {
// Append durably records entry, assigning the next Seq for
// entry.SessionID (entry.Seq is ignored on input), and returns the
// assigned Seq. Callers must Append before applying entry's effects
// (write-ahead): a crash between Append and full processing just means
// replay reprocesses that entry from the last stable configuration,
// which is safe since processing is deterministic and replay's
// IOProcessor is suppressed.
Append(ctx context.Context, entry LogEntry) (seq uint64, err error)
// Read streams entries for sessionID in ascending Seq order, starting
// at from (inclusive). Iteration stops as soon as the consumer stops
// ranging, or on the first yielded error.
Read(ctx context.Context, sessionID SessionID, from uint64) iter.Seq2[LogEntry, error]
// LastSeq returns the highest Seq recorded for sessionID, or 0 if none.
LastSeq(ctx context.Context, sessionID SessionID) (uint64, error)
}
Log is the primary persistence mechanism for a chart: recording every inbound message lets a session's state be reconstructed exactly by replaying them, rather than by directly serializing the datamodel.
type LogDefinition ¶
type LogDefinition struct {
Label string `json:"label,omitempty"`
LabelExpr *Expression `json:"labelExpr,omitempty"`
Expr *Expression `json:"expr,omitempty"`
}
LogDefinition records one diagnostic value. Label and LabelExpr are mutually exclusive; Expr may be omitted to log canonical null.
type LogEntry ¶
type LogEntry struct {
SessionID SessionID
Seq uint64
Kind EntryKind
// Timestamp is the entry's logical append time (UTC), obtained from the
// same configured Clock that drives the live Instance. It is used as
// "now" during replay when recomputing a new pending send's FireAt
// (FireAt = Timestamp + delay) -- replay never consults the real clock.
Timestamp time.Time
Event Event // the inbound event (for KindTimerFired, the event that fired)
SendID Identifier // KindTimerFired only
Target Identifier // KindTimerFired only
Type Identifier // KindTimerFired only; original I/O processor selector
}
LogEntry is one recorded message. SessionID+Seq is monotonically increasing and gapless, assigned by Log.Append.
type Logger ¶
type Logger interface {
// Log records one diagnostic entry. It is called synchronously, inline,
// from the interpreter's own goroutine, and is not expected to hand off
// to a goroutine of its own the way IOProcessor.Send is -- a Logger call
// is a local, in-process write, not real I/O.
Log(label string, data Value)
}
Logger is where ExecContext.Log's output goes: a chart's diagnostic output, distinct from any event traffic or persisted Log entry. label and data mirror <log>'s own label-plus-expr shape.
var NoopLogger Logger = noopLogger{}
NoopLogger discards every call. It is the default Logger for an Instance built with no WithLogger option, so a chart that never calls ExecContext.Log behaves identically whether or not WithLogger was ever configured.
type MacrostepObserver ¶
type MacrostepObserver interface {
Enabled() bool
ObserveMacrostep(MacrostepTrace)
}
MacrostepObserver receives diagnostic descriptions of completed live macrosteps. Enabled and ObserveMacrostep execute on the Instance's actor goroutine and must return promptly. Panics are recovered and ignored.
type MacrostepObserverFunc ¶
type MacrostepObserverFunc func(MacrostepTrace)
MacrostepObserverFunc adapts a function to an always-enabled observer.
func (MacrostepObserverFunc) Enabled ¶
func (f MacrostepObserverFunc) Enabled() bool
func (MacrostepObserverFunc) ObserveMacrostep ¶
func (f MacrostepObserverFunc) ObserveMacrostep(trace MacrostepTrace)
type MacrostepTrace ¶
type MacrostepTrace struct {
Sequence uint64
Timestamp time.Time
Trigger *Event
Before []Identifier
Microsteps []MicrostepTrace
After []Identifier
Terminal bool
TerminalError string
}
MacrostepTrace describes one completed macrostep. All values in a delivered trace are independently owned and may be mutated by the observer. Sequence starts at one for each live Instance activation and is unrelated to any durable log sequence. Timestamp is read from the configured Clock and normalized to UTC.
func (MacrostepTrace) Clone ¶
func (trace MacrostepTrace) Clone() MacrostepTrace
Clone returns an independently owned copy of the trace, including all events, values, and slices.
type ManualClock ¶
type ManualClock struct {
// contains filtered or unexported fields
}
ManualClock is a Clock for tests: time only advances when Advance is called, and pending callbacks fire synchronously, in fire-time order, as part of that call instead of on a real timer goroutine.
func NewManualClock ¶
func NewManualClock(start time.Time) *ManualClock
NewManualClock returns a ManualClock starting at start.
func (*ManualClock) Advance ¶
func (c *ManualClock) Advance(d time.Duration)
Advance moves the clock forward by d, then synchronously fires (in fire-time order) any timers now due.
func (*ManualClock) AfterFunc ¶
func (c *ManualClock) AfterFunc(d time.Duration, f func()) func() bool
func (*ManualClock) Now ¶
func (c *ManualClock) Now() time.Time
type ManualIDGenerator ¶
type ManualIDGenerator struct {
// contains filtered or unexported fields
}
ManualIDGenerator is an IDGenerator for tests. Each call to NewID returns the next value from a sequential counter ("id-1", "id-2", ...) instead of random text, so a test can assert against a specific, reproducible id rather than merely checking that one was assigned.
func (*ManualIDGenerator) NewID ¶
func (g *ManualIDGenerator) NewID() SessionID
NewID returns the next sequential id, starting at "id-1".
type MicrostepTrace ¶
type MicrostepTrace struct {
Trigger *Event
Transitions []TransitionRef
Exited []Identifier
Entered []Identifier
}
MicrostepTrace describes one selected transition set and its state changes.
type Option ¶
type Option func(*instanceConfig)
Option configures an Instance built by New or Restore.
func WithClock ¶
WithClock sets the Clock used for delayed-send timers. Defaults to the real wall clock.
func WithCompletionHook ¶
WithCompletionHook registers a callback run exactly once when the Instance reaches a top-level final state. It runs synchronously on the interpreter goroutine after exit processing and before Send, Start, or Done can report completion. Returning an error makes completion fail and records that error as the Instance's terminal error. Stop, Checkpoint, and fatal interpreter exits do not invoke the hook.
func WithDeliveryNamespace ¶
WithDeliveryNamespace sets a stable external-delivery namespace. It is primarily intended for durable runtimes; ordinary instances receive a unique incarnation namespace automatically.
func WithIDGenerator ¶
func WithIDGenerator(g IDGenerator) Option
WithIDGenerator sets the IDGenerator used to mint this Instance's session id (SCXML 5.10's _sessionid) when no explicit WithSessionID is given. Defaults to IDGeneratorFunc(rand.Text) (crypto/rand.Text). Tests that need a reproducible id instead of random text can pass a ManualIDGenerator.
func WithIOProcessor ¶
func WithIOProcessor(typ Identifier, p IOProcessor) Option
WithIOProcessor sets the IOProcessor used for genuinely external dispatch. Defaults to LocalIOProcessor, which reports unreachable targets instead of silently discarding them.
func WithInboxSize ¶
WithInboxSize sets the buffer size of the actor's ingress channel, i.e. how many in-flight Send/Stop calls can be accepted before callers start experiencing backpressure. Defaults to 1.
func WithIngressHook ¶
WithIngressHook registers a callback run on the Instance's goroutine immediately before every event accepted through Send or Deliver is applied. Returning an error rejects the event and terminates the Instance: a durable runtime cannot safely continue after its write-ahead record failed. Rehydrate suppresses this hook while replaying entries already in the Log, then enables it for new live arrivals.
func WithInvokeHandler ¶
func WithInvokeHandler(typ Identifier, factory InvokeHandlerFactory) Option
WithInvokeHandler binds one declarative invocation type in this Instance's environment. The factory is called once per live start or resume; static requirements are validated before a datamodel session is created.
func WithLogger ¶
WithLogger sets the Logger that ExecContext.Log calls are routed to. Defaults to NoopLogger.
func WithMacrostepObserver ¶
func WithMacrostepObserver(observer MacrostepObserver) Option
WithMacrostepObserver installs a diagnostic observer for completed live macrosteps. Its Enabled method is consulted at the start of every macrostep, so an observer may cheaply toggle collection after an Instance has started.
func WithPlatformVariables ¶
WithPlatformVariables supplies the opaque capabilities exposed through SCXML's protected _x system-variable root. The binding map is copied; callers must provide the option again to Restore or Rehydrate because platform capabilities are runtime configuration, not snapshot data.
func WithSessionID ¶
WithSessionID pins this Instance's session id (SCXML 5.10's _sessionid) to an id the caller already has -- e.g. from a Log -- instead of minting a fresh one. It takes priority over both the configured IDGenerator and, for Restore, any id recorded in the Snapshot being restored from.
func WithTimerFiredDetailsHook ¶
func WithTimerFiredDetailsHook(fn func(sendID, target, typ Identifier, ev Event) error) Option
WithTimerFiredDetailsHook is WithTimerFiredHook's metadata-preserving counterpart. In addition to the generated send ID and event, fn receives the original send target and I/O processor type so a durable log can reconstruct the dispatch even if its pending-send record is unavailable.
func WithTimerFiredHook ¶
func WithTimerFiredHook(fn func(sendID Identifier, ev Event) error) Option
WithTimerFiredHook registers a callback invoked synchronously, on the interpreter's own goroutine, immediately before a fired delayed-send's event is applied. It exists so a Log implementation can satisfy the write-ahead requirement (record the message, then let it be applied) for the one kind of inbound message that has no explicit Instance.Send call site for an application to hook itself -- see log.go, LoggingTimerFiredHook. A non-nil returned error is treated as this Instance's fatal terminal error (surfaced via Err()/Wait()) rather than silently letting the event through.
type OutboundMessage ¶
type OutboundMessage struct {
SessionID SessionID
DeliveryID DeliveryID
Request SendRequest
Status OutboundStatus
Result OutboundResult
}
OutboundMessage is one stable external send intent.
type OutboundResult ¶
type OutboundResult struct {
Error string
Execution bool
// Synchronous distinguishes an outcome returned by Send (and therefore
// reproduced during replay) from a callback/recovery failure, which is
// reported as a separate inbound platform event.
Synchronous bool
}
OutboundResult is the recorded synchronous/asynchronous outcome.
type OutboundStatus ¶
type OutboundStatus string
OutboundStatus is the durable lifecycle of an external send intent.
const ( OutboundPending OutboundStatus = "pending" OutboundResolved OutboundStatus = "resolved" )
type ParamDefinition ¶
type ParamDefinition struct {
Name Identifier `json:"name"`
Expr *Expression `json:"expr,omitempty"`
Location *Expression `json:"location,omitempty"`
}
ParamDefinition binds one named invocation or done-data parameter. Exactly one of Expr and Location must be present. Location lets the selected datamodel read a value from one of its own locations without exposing that representation to the interpreter.
type PendingSend ¶
type PendingSend struct {
SendID Identifier
Target Identifier
Type Identifier
Event Event
FireAt time.Time
}
PendingSend describes one delayed <send> that has not yet fired or been cancelled. FireAt is absolute so a restored Instance can re-arm it against its configured Clock, firing it during Start if it is already overdue.
type RaiseDefinition ¶
type RaiseDefinition struct {
Event Identifier `json:"event,omitempty"`
EventExpr *Expression `json:"eventExpr,omitempty"`
Data *Expression `json:"data,omitempty"`
}
RaiseDefinition raises an internal event. Exactly one of Event and EventExpr is required. Data, when present, computes its canonical payload.
type ReplayAwareIOProcessor ¶
type ReplayAwareIOProcessor interface {
IOProcessor
ReplaySend(ctx context.Context, req SendRequest) error
Recover(ctx context.Context) error
}
ReplayAwareIOProcessor lets a durable processor reproduce the recorded synchronous result of a send while deterministic replay is in progress, and hand persisted work back to its transport once replay has caught up. Implementations must not perform external I/O from ReplaySend.
type ResumableInvokeHandler ¶
type ResumableInvokeHandler interface {
InvokeHandler
Resume(context.Context, InvokeRequest, InvokeIO) (Value, error)
}
ResumableInvokeHandler can reattach to an invocation that was active when a durable process stopped. A fresh handler is created for every resume.
type RevisionID ¶
type RevisionID string
RevisionID is the deterministic identity of one compiled Chart revision. Version 1 IDs are "sha256:" followed by 64 lowercase hexadecimal digits.
type ScriptDefinition ¶
type ScriptDefinition struct {
Expr Expression `json:"expr"`
}
ScriptDefinition executes one datamodel-owned script expression.
type SendDefinition ¶
type SendDefinition struct {
Event Identifier `json:"event,omitempty"`
EventExpr *Expression `json:"eventExpr,omitempty"`
Target string `json:"target,omitempty"`
TargetExpr *Expression `json:"targetExpr,omitempty"`
Type string `json:"type,omitempty"`
TypeExpr *Expression `json:"typeExpr,omitempty"`
ID Identifier `json:"id,omitempty"`
IDLocation *Expression `json:"idLocation,omitempty"`
Delay string `json:"delay,omitempty"`
DelayExpr *Expression `json:"delayExpr,omitempty"`
Params []ParamDefinition `json:"params,omitempty"`
Content *Expression `json:"content,omitempty"`
}
SendDefinition describes one send operation. Static and expression forms of each field are mutually exclusive. Content is one whole payload and is mutually exclusive with Params.
type SendExecutionError ¶
type SendExecutionError interface {
error
SendExecutionError()
}
SendExecutionError marks an IOProcessor.Send failure as an invalid or unsupported target/type rather than a delivery failure. The interpreter turns marked errors into error.execution; all other Send errors become error.communication.
type SendOption ¶
type SendOption func(*SendDefinition)
SendOption configures serializable send executable content.
func SendContent ¶
func SendContent(content Expression) SendOption
SendContent sets the whole event payload expression.
func SendDelay ¶
func SendDelay(delay time.Duration) SendOption
SendDelay delays delivery by a static duration.
func SendIDLocation ¶
func SendIDLocation(location Expression) SendOption
SendIDLocation stores a generated send ID at a model-owned location.
func SendParams ¶
func SendParams(params ...ParamDefinition) SendOption
SendParams sets named event payload expressions.
type SendOptions ¶
type SendOptions struct {
SendID Identifier // author-visible ID; empty uses an unexposed execution ID
IDLocation IDLocationFunc // assigns a generated, author-visible ID; mutually exclusive with SendID
Target Identifier // "" = own external queue (default); "#_internal"; or an external target
Type Identifier // IOProcessor selector, meaningful for external targets only
Data Value
Delay time.Duration // 0 = dispatch immediately
}
SendOptions configures a scheduled event, mirroring <send>'s attributes.
type SendRequest ¶
type SendRequest struct {
DeliveryID DeliveryID
SendID Identifier // execution ID, including an implementation-generated ID
EventSendID Identifier // author-specified ID exposed as _event.sendid; empty if none
Target Identifier
Type Identifier
Event Identifier
Data Value
}
SendRequest is a request to dispatch an event to a genuinely external target (Target is neither "" nor "#_internal" -- those two are handled directly by the interpreter core, never reaching an IOProcessor, since they aren't real I/O). By the time an IOProcessor sees a SendRequest, any <send delay="..."> has already elapsed: delay-timer bookkeeping belongs to the interpreter core, so Send is always an immediate dispatch request.
type SessionID ¶
type SessionID string
SessionID identifies one running session -- SCXML 5.10's _sessionid: an Instance's identity for logging, snapshotting, and Rehydrate. Unlike Identifier, it is an opaque token: it has no dot-segment structure, is never matched as an event descriptor, and is never split into segments.
func (SessionID) Compare ¶
Compare gives a total, deterministic lexicographic order over SessionID values, for diagnostics, sorted dumps, and deterministic map-key iteration.
func (SessionID) MarshalText ¶
MarshalText implements encoding.TextMarshaler.
func (*SessionID) UnmarshalText ¶
UnmarshalText implements encoding.TextUnmarshaler.
type SessionOptions ¶
type SessionOptions struct{}
SessionOptions configures creation of one datamodel session. Interpreter environment such as the current event, configuration, identity, and platform values is deliberately supplied per operation through ExecContext rather than cached here.
type Snapshot ¶
type Snapshot struct {
Version int
Revision RevisionID
Datamodel []byte
ID SessionID // SCXML 5.10's _sessionid for this session; Restore preserves it unless WithSessionID overrides it
Configuration []Identifier
HistoryValue map[Identifier][]Identifier
InternalQueue []Event
ExternalQueue []Event
Running bool
SendSeq int // high-water mark for auto-generated send.<n> IDs
InvokeSeq int // high-water mark for auto-generated <state>.invoke<n> IDs
DispatchSeq uint64
DeliveryNamespace string
PendingSends []PendingSend
ActiveInvokes []ActiveInvoke
InitializedData []Identifier
}
Snapshot is a point-in-time cache of a running chart's datamodel and interpreter state: the session id, active configuration, recorded history, both event queues, running flag, outstanding delayed sends, and active invocation bookkeeping. Datamodel bytes are an opaque cache owned by the instance's DatamodelSession.
Snapshot is a derivable checkpoint, not an independent source of truth: it captures exactly what replaying a Log up to some point would produce, and exists purely so a cold start doesn't need to replay from the beginning every time (see Checkpoint, Rehydrate in replay.go).
func (Snapshot) MarshalJSON ¶
MarshalJSON implements json.Marshaler.
func (*Snapshot) UnmarshalJSON ¶
UnmarshalJSON implements json.Unmarshaler.
type SnapshotStore ¶
type SnapshotStore interface {
Save(ctx context.Context, sessionID SessionID, cp Checkpoint) error
Load(ctx context.Context, sessionID SessionID) (Checkpoint, bool, error)
}
SnapshotStore persists Checkpoints, letting Rehydrate skip replaying a Log from the very beginning.
type StateDefinition ¶
type StateDefinition struct {
ID StateDefinitionID `json:"id"`
Kind StateKind `json:"kind"`
History HistoryKind `json:"history,omitempty"`
Initial *TransitionDefinition `json:"initial,omitempty"`
OnEntry []ExecutableBlock `json:"onEntry,omitempty"`
OnExit []ExecutableBlock `json:"onExit,omitempty"`
Transitions []TransitionDefinition `json:"transitions,omitempty"`
Invokes []InvokeDefinition `json:"invokes,omitempty"`
Data []DataDefinition `json:"data,omitempty"`
DoneData *DoneDataDefinition `json:"doneData,omitempty"`
Children []StateDefinition `json:"children,omitempty"`
}
StateDefinition describes one state-tree node in document order.
func Atomic ¶
func Atomic(id Identifier, opts ...StateOption) StateDefinition
Atomic declares a leaf state with no children.
func Compound ¶
func Compound(id Identifier, initial Identifier, opts ...StateOption) StateDefinition
Compound declares a state with children. initial is the first target of its default transition; WithInitial may add targets and executable content. If initial is empty and WithInitial is absent, the first child is the default, as required by SCXML.
func Final ¶
func Final(id Identifier, opts ...StateOption) StateDefinition
Final declares a final state.
func History ¶
func History(id Identifier, kind HistoryKind, defaultTarget Identifier, opts ...TransitionOption) StateDefinition
History declares a history pseudostate belonging to whichever compound or parallel state contains it. defaultTarget is entered when the history has never recorded a configuration (i.e. on first entry to the parent). opts may add targets and executable content to that default transition.
func Parallel ¶
func Parallel(id Identifier, opts ...StateOption) StateDefinition
Parallel declares a state whose children are all simultaneously active (each child is one region).
type StateDefinitionID ¶
type StateDefinitionID struct {
Value Identifier `json:"value,omitempty"`
Generated bool `json:"generated,omitempty"`
}
StateDefinitionID preserves whether a state's ID was written explicitly or generated by the builder. A generated ID may have an empty Value before validation/canonicalization; normalization assigns it deterministically on a private clone and never mutates caller-owned input.
type StateOption ¶
type StateOption func(*StateDefinition)
StateOption appends serializable authoring data to a state definition.
func Children ¶
func Children(children ...StateDefinition) StateOption
Children attaches child states, in document order.
func Eventless ¶
func Eventless(opts ...TransitionOption) StateOption
Eventless attaches an eventless (automatic) transition, evaluated whenever no event is required for it to fire -- only its Cond gates it.
func Invoke ¶
func Invoke(typ, source string, opts ...InvokeOption) StateOption
Invoke attaches a declarative external service to a state. Runtime behavior is supplied separately through WithInvokeHandler.
func On ¶
func On(events string, opts ...TransitionOption) StateOption
On attaches a transition matching the space-separated event descriptors.
func OnEntry ¶
func OnEntry(actions ...Executable) StateOption
OnEntry attaches executable content run when the state is entered.
func OnExit ¶
func OnExit(actions ...Executable) StateOption
OnExit attaches executable content run when the state is exited.
func WithDone ¶
func WithDone(content Expression) StateOption
WithDone sets a final state's whole result payload expression.
func WithDoneParams ¶
func WithDoneParams(params ...ParamDefinition) StateOption
WithDoneParams sets a final state's named result payload expressions.
func WithInitial ¶
func WithInitial(opts ...TransitionOption) StateOption
WithInitial configures a compound state's eventless, unconditional default transition. The initial argument passed to Compound remains its first target; pass an empty initial when Target supplies every target.
type TextExpressionCodec ¶
type TextExpressionCodec interface {
ParseExpression(role TextExpressionRole, text string) (Expression, error)
FormatExpression(role TextExpressionRole, expression Expression) (string, error)
}
TextExpressionCodec is the optional bridge between a datamodel's canonical Expression values and expression text in a surface syntax. It is owned by the datamodel rather than by Definition or any particular syntax package.
type TextExpressionRole ¶
type TextExpressionRole string
TextExpressionRole describes how a textual surface syntax will use an expression. Datamodel codecs may use the role to parse context-sensitive expression forms; models with one source language may ignore it.
const ( TextExpressionValue TextExpressionRole = "value" TextExpressionCondition TextExpressionRole = "condition" TextExpressionLocation TextExpressionRole = "location" TextExpressionScript TextExpressionRole = "script" TextExpressionEvent TextExpressionRole = "event" TextExpressionTarget TextExpressionRole = "target" TextExpressionType TextExpressionRole = "type" TextExpressionSendID TextExpressionRole = "send-id" TextExpressionDelay TextExpressionRole = "delay" TextExpressionLabel TextExpressionRole = "label" TextExpressionArray TextExpressionRole = "array" )
type TransitionDefinition ¶
type TransitionDefinition struct {
Events []Identifier `json:"events,omitempty"`
Targets []Identifier `json:"targets,omitempty"`
Type TransitionType `json:"type,omitempty"`
Condition *Expression `json:"condition,omitempty"`
Actions []ExecutableBlock `json:"actions,omitempty"`
}
TransitionDefinition preserves event, target, condition, executable-block, and transition-type ordering. Empty Events means eventless; empty Targets means targetless.
type TransitionOption ¶
type TransitionOption func(*TransitionDefinition)
TransitionOption appends serializable authoring data to a transition.
func AsInternal ¶
func AsInternal() TransitionOption
AsInternal marks the transition as SCXML transition type="internal".
func Target ¶
func Target(ids ...Identifier) TransitionOption
Target sets the transition's target state(s) (more than one for a transition that enters multiple parallel regions).
func Then ¶
func Then(actions ...Executable) TransitionOption
Then attaches executable content run when the transition fires.
type TransitionRef ¶
type TransitionRef struct {
Source Identifier
Index int
}
TransitionRef identifies a transition in the pinned immutable definition. Index is zero-based within Source's StateDefinition.Transitions.
type TransitionType ¶
type TransitionType string
TransitionType describes SCXML external versus internal transition entry semantics. The zero value means TransitionExternal.
const ( TransitionExternal TransitionType = "external" TransitionInternal TransitionType = "internal" )
type Value ¶
type Value struct {
// contains filtered or unexported fields
}
Value is syntax-neutral data that can cross datamodel, actor, process, and durability boundaries. Its variants are null, boolean, UTF-8 string, exact decimal number, ordered list, string-keyed map, and a tagged application value whose payload is another Value.
Value is immutable through its public API: constructors copy collection inputs, collection accessors return copies, and Clone makes a deep copy. The zero value is the canonical null value.
Numbers are finite decimal values, not float64 values. NumberValue accepts RFC 8259 JSON number syntax and stores a canonical coefficient/exponent representation without imposing an integer size or silently rounding.
func Float64Value ¶
Float64Value returns a canonical number for the exact decimal spelling Go uses to round-trip value. NaN and infinities are rejected because they are not canonical data numbers.
func Int64Value ¶
Int64Value returns an exact canonical number for value.
func MapValue ¶
MapValue returns a string-keyed map and deeply copies values. It rejects invalid UTF-8 keys. Map order is not semantically significant; canonical encodings sort keys.
func NullValue ¶
func NullValue() Value
NullValue returns the canonical null Value. It is equal to a zero Value.
func NumberValue ¶
NumberValue parses an RFC 8259 JSON number without converting it through a floating-point type. Mathematically equal spellings have the same canonical representation: insignificant zeroes and a negative sign on zero are removed, and a base-10 exponent is used when necessary.
func PlatformErrorValue ¶
func PlatformErrorValue(classification Identifier, err error) Value
PlatformErrorValue converts err into canonical data with a stable classification and message. Invalid UTF-8 is replaced deterministically so an error can never make a durable event unencodable.
func StringValue ¶
StringValue returns a canonical string Value. It rejects invalid UTF-8 at construction rather than creating a Value that cannot be persisted.
func TaggedValue ¶
TaggedValue returns an application value identified by tag. A tag is a stable application-defined type identifier; it must be non-empty UTF-8. The canonical payload is deeply copied and needs no concrete-type registry to decode.
func Uint64Value ¶
Uint64Value returns an exact canonical number for value.
func ValueFromJSON ¶
ValueFromJSON converts a JSON-shaped Go value to a canonical Value without reflection. It accepts nil, bool, string, json.Number, finite float types, integer types, []any, and map[string]any. Use json.Decoder.UseNumber before this conversion when decoding JSON whose integer precision must be kept.
func ValueFromWire ¶
ValueFromWire validates wire and returns an immutable Value. Unknown versions, unknown kinds, malformed union combinations, invalid numbers, invalid UTF-8, and malformed tagged values are rejected.
func (Value) AsInt64 ¶
AsInt64 returns the exact signed integer represented by v. It accepts the canonical exponent form used for integers with trailing zeroes (for example, Int64Value(10) is stored as "1e1") and rejects fractional and out-of-range numbers.
func (Value) AsNumber ¶
AsNumber returns the exact canonical decimal spelling and true when v is a number Value. The spelling is either "0", a signed coefficient, or a signed coefficient followed by "e" and a signed base-10 exponent.
func (Value) AsTagged ¶
AsTagged returns the tag, a deep copy of the payload, and true when v is a tagged application Value.
func (Value) JSONValue ¶
JSONValue converts v to an independent JSON-shaped Go value. Numbers are returned as json.Number to retain precision. Their canonical spelling may use exponent form even when mathematically integral, so json.Number.Int64 does not necessarily succeed. Tagged values are rejected because untagged JSON cannot preserve their application tag.
func (Value) MarshalBinary ¶
MarshalBinary implements encoding.BinaryMarshaler using the deterministic, versioned ValueWire representation.
func (Value) MarshalJSON ¶
MarshalJSON implements json.Marshaler using the deterministic, versioned ValueWire representation. This is the canonical Value wire JSON, not the untagged JSON-shaped form returned by JSONValue.
func (Value) MarshalText ¶
MarshalText implements encoding.TextMarshaler using the deterministic, versioned ValueWire representation.
func (*Value) UnmarshalBinary ¶
UnmarshalBinary implements encoding.BinaryUnmarshaler using the deterministic, versioned ValueWire representation.
func (*Value) UnmarshalJSON ¶
UnmarshalJSON implements json.Unmarshaler using the deterministic, versioned ValueWire representation.
func (*Value) UnmarshalText ¶
UnmarshalText implements encoding.TextUnmarshaler using the deterministic, versioned ValueWire representation.
type ValueKind ¶
type ValueKind string
ValueKind identifies one of the closed set of canonical Value variants.
const ( // ValueKindNull is the null variant. It is also the kind of a zero Value. ValueKindNull ValueKind = "null" // ValueKindBool is the boolean variant. ValueKindBool ValueKind = "bool" // ValueKindString is the UTF-8 string variant. ValueKindString ValueKind = "string" // ValueKindNumber is the arbitrary-precision decimal number variant. ValueKindNumber ValueKind = "number" // ValueKindList is the ordered list variant. ValueKindList ValueKind = "list" // ValueKindMap is the string-keyed map variant. ValueKindMap ValueKind = "map" // ValueKindTagged is an application-tagged canonical payload. ValueKindTagged ValueKind = "tagged" )
type ValueWire ¶
type ValueWire struct {
Version int `json:"version"`
Kind ValueKind `json:"kind"`
Bool *bool `json:"bool,omitempty"`
String *string `json:"string,omitempty"`
Number *string `json:"number,omitempty"`
List *[]ValueWire `json:"list,omitempty"`
Map *map[string]ValueWire `json:"map,omitempty"`
Tag *string `json:"tag,omitempty"`
Payload *ValueWire `json:"payload,omitempty"`
}
ValueWire is the documented wire union for Value. Exactly one variant field is present according to Kind; null has no variant field, while tagged has both Tag and Payload. Version must be ValueWireVersion.
The JSON field names are the canonical text and binary representation used by Value's marshal methods. JSON object keys in Map are sorted by encoding/json, so the resulting bytes are deterministic and suitable as revision material. The binary representation deliberately uses the same versioned UTF-8 bytes as the text representation. Unmarshal into Value when decoding bytes; ValueFromWire is the validation gate for a ValueWire built or decoded separately.
type WriterLogger ¶
type WriterLogger struct {
// contains filtered or unexported fields
}
WriterLogger is a Logger that writes one line per call to an underlying io.Writer. It is safe for concurrent use by multiple goroutines: calls to Log are serialized, so multiple Instances or actors sharing one WriterLogger never interleave partial writes.
func NewWriterLogger ¶
func NewWriterLogger(w io.Writer) *WriterLogger
NewWriterLogger returns a WriterLogger that writes to w.
func (*WriterLogger) Log ¶
func (l *WriterLogger) Log(label string, data Value)
Log writes label and data as a single line to the underlying io.Writer.
Source Files
¶
- authoring.go
- chart.go
- clock.go
- compile.go
- datamodel.go
- definition.go
- definition_artifact.go
- definition_canonical.go
- definition_validate.go
- doc.go
- errors.go
- event.go
- event_codec.go
- exec.go
- executable.go
- expression.go
- go_model.go
- go_text_expression.go
- identifier.go
- idgenerator.go
- inspection.go
- instance.go
- interpreter.go
- invoke.go
- ioprocessor.go
- location.go
- log.go
- logger.go
- macrostep_trace.go
- replay.go
- revision.go
- sessionid.go
- snapshot.go
- state.go
- storage.go
- text_expression.go
- transition.go
- value.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package actors builds virtual actors on top of statecharts.Chart, statecharts.Instance, statecharts.IOProcessor, and statecharts.Log: named, addressable instances that can be spawned durable so a process restart resumes them exactly where they left off, and that page into and out of memory automatically as they go idle or as the system comes under resident-actor pressure.
|
Package actors builds virtual actors on top of statecharts.Chart, statecharts.Instance, statecharts.IOProcessor, and statecharts.Log: named, addressable instances that can be spawned durable so a process restart resumes them exactly where they left off, and that page into and out of memory automatically as they go idle or as the system comes under resident-actor pressure. |
|
datamodel
|
|
|
ecmascript
Package ecmascript provides an optional ECMAScript datamodel backed by the pure-Go modernc QuickJS port.
|
Package ecmascript provides an optional ECMAScript datamodel backed by the pure-Go modernc QuickJS port. |
|
Package inspector provides a transport-neutral, non-activating view of actor systems.
|
Package inspector provides a transport-neutral, non-activating view of actor systems. |
|
http
Package inspectorhttp adapts an inspector.Service to a versioned HTTP API.
|
Package inspectorhttp adapts an inspector.Service to a versioned HTTP API. |
|
Package sqllog provides database/sql-backed durable statechart storage.
|
Package sqllog provides database/sql-backed durable statechart storage. |
|
sqlite3
Package sqlite3 opens SQLite-backed sqllog storage using the pure-Go modernc.org/sqlite driver.
|
Package sqlite3 opens SQLite-backed sqllog storage using the pure-Go modernc.org/sqlite driver. |
|
Package storagetest provides a reusable storage conformance suite and an in-memory implementation for statecharts storage implementations.
|
Package storagetest provides a reusable storage conformance suite and an in-memory implementation for statecharts storage implementations. |
|
syntax
|
|
|
json
Package json encodes and decodes statecharts.Definition as a strict, human-editable JSON surface syntax.
|
Package json encodes and decodes statecharts.Definition as a strict, human-editable JSON surface syntax. |
|
scxml
Package scxml encodes and decodes statecharts.Definition using the W3C State Chart XML surface syntax.
|
Package scxml encodes and decodes statecharts.Definition using the W3C State Chart XML surface syntax. |