Documentation
¶
Overview ¶
Package flezha is the Flezha Go SDK: a poll host over the shared core, linked in through its C ABI.
The SDK holds no kernel code. Transport, framing, ordering, per-cell exclusivity, durability, retries, timers, routing, the steps driver and reconnects are the core's; this package brings the authoring surface, the codec for Go types, the goroutine host and idiomatic errors.
type Echo struct{}
func (Echo) Spec() flezha.Spec { return flezha.Spec{Name: "echo"} }
func (Echo) Run(in string, ctx *flezha.Ctx[flezha.NoState, string]) error {
return ctx.Emit(in)
}
type EchoRelay struct{}
func (EchoRelay) Spec() flezha.RelaySpec { return flezha.RelaySpec{FactoryID: "echo"} }
func (EchoRelay) Channels(c *flezha.ChannelBuilder) {
flezha.Into(flezha.Input[string](c, "input"), Echo{}).Output("out")
}
runner, err := flezha.CreateRunner("default")
...
err = runner.RegisterFactory(EchoRelay{})
err = runner.Run()
Example (Harness) ¶
package main
import (
"fmt"
flezha "github.com/flezha/flezha_go_sdk"
"github.com/flezha/flezha_go_sdk/flezhatest"
)
type Order struct {
Pair string `json:"pair"`
Qty int `json:"qty"`
}
type Book struct {
Sum int `json:"sum"`
}
type Added struct {
Qty int `json:"qty"`
}
func (a Added) ApplyTo(b *Book) { b.Sum += a.Qty }
type Totals struct{}
func (Totals) Spec() flezha.Spec { return flezha.Spec{Name: "totals", IdleTTLSeconds: 3600} }
func (Totals) Changes() flezha.Changes[Book] { return flezha.Changes[Book]{"added": Added{}} }
func (Totals) Run(in Order, ctx *flezha.Ctx[Book, int]) error {
if err := ctx.Change(Added{Qty: in.Qty}); err != nil {
return err
}
return ctx.Emit(ctx.State().Sum)
}
func main() {
h, err := flezhatest.New[Order, Book, int](Totals{})
if err != nil {
panic(err)
}
out, err := h.Feed(Order{Pair: "EUR/USD", Qty: 4}, 0, false)
if err != nil {
panic(err)
}
fmt.Println(out.Outputs, h.State().Sum, h.ReplayEquals())
}
Output: [4] 4 <nil>
Example (Runner) ¶
The runner a program serves its relay types with; compiled here, run against a controller.
package main
import (
flezha "github.com/flezha/flezha_go_sdk"
)
type Order struct {
Pair string `json:"pair"`
Qty int `json:"qty"`
}
type Book struct {
Sum int `json:"sum"`
}
type Added struct {
Qty int `json:"qty"`
}
func (a Added) ApplyTo(b *Book) { b.Sum += a.Qty }
type Totals struct{}
func (Totals) Spec() flezha.Spec { return flezha.Spec{Name: "totals", IdleTTLSeconds: 3600} }
func (Totals) Changes() flezha.Changes[Book] { return flezha.Changes[Book]{"added": Added{}} }
func (Totals) Run(in Order, ctx *flezha.Ctx[Book, int]) error {
if err := ctx.Change(Added{Qty: in.Qty}); err != nil {
return err
}
return ctx.Emit(ctx.State().Sum)
}
type Orders struct{}
func (Orders) Spec() flezha.RelaySpec { return flezha.RelaySpec{FactoryID: "orders"} }
func (Orders) Channels(c *flezha.ChannelBuilder) {
orders := flezha.Input[Order](c, "orders").KeyBy(func(o Order) string { return o.Pair })
flezha.Into(orders, Totals{}).Output("totals")
}
func main() {
run := func() error {
runner, err := flezha.CreateRunner("trading")
if err != nil {
return err
}
if err := runner.RegisterFactory(Orders{}); err != nil {
return err
}
return runner.Run()
}
_ = run
}
Output:
Index ¶
- Constants
- func Effect[T, S, O any](ctx *Ctx[S, O], name string, fn func() (T, error)) (T, error)
- func NonRetryable(err error) error
- type CallSpec
- type Change
- type Changes
- type ChannelBuilder
- type ChannelCodec
- type Control
- func (c *Control) BindPlugin(name, relayID string, hooks []any, channel string) (any, error)
- func (c *Control) Call(verb string, args ...any) (any, error)
- func (c *Control) CellState(relayID, cell string) (any, error)
- func (c *Control) DisablePlugin(name string) (any, error)
- func (c *Control) EnablePlugin(name, provider string, opts map[string]any, single bool, relayID string, ...) (any, error)
- func (c *Control) ListPlugins() (any, error)
- func (c *Control) ListRelays() (any, error)
- func (c *Control) StartRelay(factoryID, id string, initValues, opts any) (StartResult, error)
- func (c *Control) StopRelay(relayID string) (any, error)
- func (c *Control) UnbindPlugin(name, relayID string) (any, error)
- type Ctx
- func (c *Ctx[S, O]) CancelTimer(kind TimerKind, at uint64) error
- func (c *Ctx[S, O]) CellKey() (string, bool)
- func (c *Ctx[S, O]) Change(change Change[S]) error
- func (c *Ctx[S, O]) Checkpoint()
- func (c *Ctx[S, O]) Complete(result any) error
- func (c *Ctx[S, O]) Emit(value O, opts ...EmitOption) error
- func (c *Ctx[S, O]) Now() uint64
- func (c *Ctx[S, O]) Part(value O) error
- func (c *Ctx[S, O]) Replay() bool
- func (c *Ctx[S, O]) SpawnSteps(factoryID string, payload any, opts ...SpawnOption) (*SpawnHandle, error)
- func (c *Ctx[S, O]) StableID() string
- func (c *Ctx[S, O]) State() S
- func (c *Ctx[S, O]) TimerAfter(ms uint64) (uint64, error)
- func (c *Ctx[S, O]) TimerAtEventTime(at uint64) (uint64, error)
- type EmitOption
- type Error
- type InputOptions
- type LocalOutput
- type LocalRelay
- type Merge
- type NoOutput
- type NoState
- type Overflow
- type Relay
- type RelaySpec
- type Response
- type Routed
- type Runner
- func (r *Runner) AwaitTermination() error
- func (r *Runner) Call(relayID, channel string, value any) (any, error)
- func (r *Runner) Close()
- func (r *Runner) Control() *Control
- func (r *Runner) Namespace() string
- func (r *Runner) RegisterFactory(relay Relay) error
- func (r *Runner) Relays() ([]string, error)
- func (r *Runner) Run() error
- func (r *Runner) Send(relayID, channel string, message []byte, opts ...SendOption) (*SendVerdict, error)
- func (r *Runner) Start() error
- func (r *Runner) UnregisterFactory(relay Relay) error
- type RunnerOption
- type SendOption
- type SendVerdict
- type ShortOptions
- type SpawnHandle
- type SpawnOption
- type SpawnOutcome
- type SpawnResult
- type Spec
- type StartResult
- type Stream
- func Call[Req, Ans any](s Stream[Req], spec CallSpec) Stream[Response[Req, Ans]]
- func FlatMap[T, U any](s Stream[T], f func(T) []U) Stream[U]
- func Input[T any](c *ChannelBuilder, name string, opts ...InputOptions) Stream[T]
- func InputDecoded[T any](c *ChannelBuilder, name string, decode func([]byte) (T, error), ...) Stream[T]
- func Into[I, S, O any](s Stream[I], t Tasklet[I, S, O]) Stream[O]
- func IntoNamed[I, S, O any](s Stream[I], t Tasklet[I, S, O], nodeName string) Stream[O]
- func Map[T, U any](s Stream[T], f func(T) U) Stream[U]
- func MergeInto[S, O, M any](m *Merge[M], t Tasklet[M, S, O]) Stream[O]
- func MergeIntoNamed[S, O, M any](m *Merge[M], t Tasklet[M, S, O], nodeName string) Stream[O]
- func RouteLatest[D, T any](c *ChannelBuilder, documents Stream[D], traffic Stream[T], key func(T) string) Stream[Routed[D]]
- func RouteLatestNamed[D, T any](c *ChannelBuilder, documents Stream[D], traffic Stream[T], key func(T) string, ...) Stream[Routed[D]]
- func (s Stream[T]) Branch(arms ...func(Stream[T])) Stream[T]
- func (s Stream[T]) Filter(pred func(T) bool) Stream[T]
- func (s Stream[T]) KeyBy(key func(T) string) Stream[T]
- func (s Stream[T]) Keyed() Stream[T]
- func (s Stream[T]) Named(name string) Stream[T]
- func (s Stream[T]) OnFull(policy Overflow) Stream[T]
- func (s Stream[T]) Output(name string, codec ...ChannelCodec) Stream[T]
- func (s Stream[T]) OutputEncoded(name string, encode func(T) ([]byte, error)) Stream[T]
- func (s Stream[T]) RetryBackoffMs(ms int) Stream[T]
- func (s Stream[T]) RetryMax(attempts int) Stream[T]
- type Tasklet
- type TimerFiring
- type TimerKind
Examples ¶
Constants ¶
const Version = "0.1.1"
Version is this SDK's own released version, stamped into every durable record it writes. Go modules carry no version in go.mod, so this constant is the one source of truth and the release checklist bumps it.
Variables ¶
This section is empty.
Functions ¶
func Effect ¶
Effect runs fn, a call to anything outside the instance, and keeps its result: when this invocation runs again (a crash re-run, a replay, a move) the call returns the kept result and fn does not run. name names the call, counted per invocation. A string or []byte result is kept as it stands and anything else as JSON; an invocation with no input-log offset runs fn each time and keeps nothing.
func NonRetryable ¶
NonRetryable marks err as one no retry can change: the item parks at once, with no further attempts.
Types ¶
type CallSpec ¶
type CallSpec struct {
Target string
Factory string
DeadlineMs int64
NoCreate bool
Channel string
AnswerChannel string
Codec ChannelCodec
}
CallSpec is a call to another relay at the end of a chain. Target names an instance, or a partition group whose member the key chooses; Factory names a factory whose instance the key names instead, started when absent unless NoCreate. DeadlineMs is required. Channel is the callee's entry channel, AnswerChannel the channel whose output answers (its first output for the request when empty), and Codec the format of the request and the answer, JSON by default.
type Change ¶
type Change[S any] interface { ApplyTo(state *S) }
Change is one recorded change of a cell's state: ApplyTo folds it in, live and on restore alike, so it must read nothing but the state and itself.
type Changes ¶
Changes lists a tasklet's change types under explicit names. A record carries the name, never the Go type's, so a type rename keeps every saved record readable. Each value is a zero value of its type.
type ChannelBuilder ¶
type ChannelBuilder struct {
// contains filtered or unexported fields
}
ChannelBuilder is what a relay's Channels receives: entry channels come from Input, tasklets are wired with Into, and every step that changes the element type is a package function taking and returning typed streams, so a mismatched edge fails `go build`.
The builder records the chains as written and judges nothing: the core checks the record when the relay registers, and its refusal is the error RegisterFactory returns.
type ChannelCodec ¶
type ChannelCodec string
ChannelCodec is the payload format a channel names. A channel that names none reads JSON, and an output that names none sends a string or a []byte as it stands and anything else as JSON.
const ( JSON ChannelCodec = "json" Text ChannelCodec = "text" Bytes ChannelCodec = "bytes" )
type Control ¶
type Control struct {
// contains filtered or unexported fields
}
Control administers the namespace this runner's connection proved, from ordinary application code: start and stop relays, enable and bind plugins, read what is running. The controller judges every call as the identity the connection established, so the application holds no credential; a user grants a namespace's applications the authority once:
flz role bind runner@team-orders app team-orders
func (*Control) BindPlugin ¶
BindPlugin binds relayID to the enabled plugin name, with optional hooks and channel.
func (*Control) Call ¶
Call is any published function, by name, with its arguments other than the namespace, which the controller fills from the connection.
func (*Control) CellState ¶
CellState is a relay's live state and the change sequence it was read at. cell is `<tasklet>[/<cell_key>]`; "" reads every cell of the relay.
func (*Control) DisablePlugin ¶
DisablePlugin disables the plugin name, stopping it wherever it runs.
func (*Control) EnablePlugin ¶
func (c *Control) EnablePlugin(name, provider string, opts map[string]any, single bool, relayID string, hooks []any) (any, error)
EnablePlugin enables the plugin name of provider (for example relay_websocket) on opts. single runs one copy in the whole cluster; relayID with hooks binds that relay in the same call.
func (*Control) ListPlugins ¶
ListPlugins is the plugins enabled in this namespace, one row each.
func (*Control) ListRelays ¶
ListRelays is the relays in this namespace across the cluster: rows, one row each, and unreachable, the controllers that did not answer.
func (*Control) StartRelay ¶
func (c *Control) StartRelay(factoryID, id string, initValues, opts any) (StartResult, error)
StartRelay starts a relay of factoryID. Without an id the controller generates one, so a start retried after a lost answer starts a second relay; with one, a start of an id already running answers already_running. initValues and opts are the specification `flz relay start` takes, nil for none.
type Ctx ¶
type Ctx[S, O any] struct { // contains filtered or unexported fields }
Ctx is the invocation context: every deterministic effect a tasklet is allowed. It accumulates one item's effects (recorded changes, emitted values, timer operations, the checkpoint) and the runner turns them into the record the core folds; nothing reaches the wire on its own.
A failing call returns its error; Run returning it fails the item, as an uncaught exception does in the other SDKs.
func (*Ctx[S, O]) CancelTimer ¶
CancelTimer cancels a registered timer by the time its registration answered.
func (*Ctx[S, O]) Change ¶
Change records one change: journaled, then folded into the state through the same ApplyTo a restore uses. A change type the tasklet's Changes does not list is refused with runtime.change_not_registered.
func (*Ctx[S, O]) Checkpoint ¶
func (c *Ctx[S, O]) Checkpoint()
Checkpoint closes the open checkpoint interval (checkpoint ack-granularity classes).
func (*Ctx[S, O]) Complete ¶
Complete ends the instance with result once the current iteration commits; a later call replaces an earlier one. The result is sent as an output naming no codec sends a value, and nil is no result.
func (*Ctx[S, O]) Emit ¶
func (c *Ctx[S, O]) Emit(value O, opts ...EmitOption) error
Emit sends one value on the tasklet's output: to each consumer through its own edge, and to the channel's output or call when it ends in one.
func (*Ctx[S, O]) Part ¶
Part sends value as a part: a preview of the output this invocation is producing, which leaves now rather than when Run returns. It never waits; a part that cannot leave at once is dropped, and a replay sends none.
func (*Ctx[S, O]) Replay ¶
Replay answers whether this invocation replays an input already processed.
func (*Ctx[S, O]) SpawnSteps ¶
func (c *Ctx[S, O]) SpawnSteps(factoryID string, payload any, opts ...SpawnOption) (*SpawnHandle, error)
SpawnSteps asks the controller for a steps instance of factoryID with payload as its first input, and answers the handle at once. A replayed invocation sends nothing and its handle answers skipped_on_replay.
func (*Ctx[S, O]) StableID ¶
StableID is a replay-stable identifier, distinct per call within the invocation: the n-th call of a replayed invocation equals the n-th of the original.
func (*Ctx[S, O]) State ¶
func (c *Ctx[S, O]) State() S
State is a copy of the cell's state: assigning a field of it changes nothing durable. Maps, slices and pointers inside it are shared and not guarded; change state only through Change.
func (*Ctx[S, O]) TimerAfter ¶
TimerAfter registers a processing-time timer ms after Now, and answers its time.
type EmitOption ¶
type EmitOption func(*emitOptions)
EmitOption qualifies one Emit.
func WithChannel ¶
func WithChannel(name string) EmitOption
WithChannel emits on the named channel this tasklet produces on.
func WithKey ¶
func WithKey(key string) EmitOption
WithKey emits under key instead of the edge's own.
func WithMetadata ¶
func WithMetadata(metadata map[string]string) EmitOption
WithMetadata attaches metadata; a key in the reserved `flz.` namespace is refused.
type Error ¶
Error is anything Flezha refuses: the controller, the core or this package. Code is what a program branches on (errors.As, then Code), Class the error's class (invalid, not_found, denied, ...), Message one sentence for a reader, Details what the message is about, and Hint the next command to run.
type InputOptions ¶
type InputOptions struct {
// The payload format: JSON by default; Text needs a string stream and
// Bytes a []byte one.
Codec ChannelCodec
// What the channel is for, in the relay's API.
Description string
// The channel's JSON Schema, as a value json.Marshal writes as an object;
// nil derives one from T when T is a struct and the codec is JSON.
Schema any
}
InputOptions are an entry channel's optional settings.
type LocalOutput ¶
type LocalOutput struct {
Channel string
Payload []byte
// What a deployed run would have put on the wire, `flz.*` stamps included.
Metadata map[string]string
}
LocalOutput is one value a graph released on a declared output.
type LocalRelay ¶
type LocalRelay struct {
// contains filtered or unexported fields
}
LocalRelay runs a declared relay graph in this process, with no controller: the deployed machinery (entry decode, edge transforms and keying, one cell per key with its own mailbox, the retry ladder, inter-tasklet delivery) in memory, with nothing durable. Durability, plugins, placement, the dead-letter queue and scale need a controller; the run says so through the logger every time it starts.
func StartLocal ¶
func StartLocal(relay Relay, opts ...RunnerOption) (*LocalRelay, error)
StartLocal registers relay's graph and starts it locally.
Example ¶
package main
import (
"fmt"
"io"
"log/slog"
"time"
flezha "github.com/flezha/flezha_go_sdk"
)
type Order struct {
Pair string `json:"pair"`
Qty int `json:"qty"`
}
type Book struct {
Sum int `json:"sum"`
}
type Added struct {
Qty int `json:"qty"`
}
func (a Added) ApplyTo(b *Book) { b.Sum += a.Qty }
type Totals struct{}
func (Totals) Spec() flezha.Spec { return flezha.Spec{Name: "totals", IdleTTLSeconds: 3600} }
func (Totals) Changes() flezha.Changes[Book] { return flezha.Changes[Book]{"added": Added{}} }
func (Totals) Run(in Order, ctx *flezha.Ctx[Book, int]) error {
if err := ctx.Change(Added{Qty: in.Qty}); err != nil {
return err
}
return ctx.Emit(ctx.State().Sum)
}
type Orders struct{}
func (Orders) Spec() flezha.RelaySpec { return flezha.RelaySpec{FactoryID: "orders"} }
func (Orders) Channels(c *flezha.ChannelBuilder) {
orders := flezha.Input[Order](c, "orders").KeyBy(func(o Order) string { return o.Pair })
flezha.Into(orders, Totals{}).Output("totals")
}
func main() {
run, err := flezha.StartLocal(Orders{}, flezha.WithLogger(quietLogger()))
if err != nil {
panic(err)
}
defer run.Close()
_ = run.OnOutput("totals", func(out flezha.LocalOutput) { fmt.Println(string(out.Payload)) })
_ = run.Feed("orders", []byte(`{"pair":"EUR/USD","qty":2}`))
_ = run.Feed("orders", []byte(`{"pair":"EUR/USD","qty":3}`))
if err := run.RunUntilIdle(10 * time.Second); err != nil {
panic(err)
}
}
func quietLogger() *slog.Logger { return slog.New(slog.NewTextHandler(io.Discard, nil)) }
Output: 2 5
func (*LocalRelay) Close ¶
func (l *LocalRelay) Close() error
Close ends the run and releases its cells. Idempotent.
func (*LocalRelay) Feed ¶
func (l *LocalRelay) Feed(channel string, payload []byte) error
Feed feeds one value's wire bytes to a declared entry channel.
func (*LocalRelay) OnOutput ¶
func (l *LocalRelay) OnOutput(channel string, callback func(LocalOutput)) error
OnOutput delivers every value released on the output channel to callback, in release order. A channel the declaration does not carry is refused.
func (*LocalRelay) RunUntilIdle ¶
func (l *LocalRelay) RunUntilIdle(budget time.Duration) error
RunUntilIdle drives the graph until it has nothing left to do: take an activation if there is one and answer it, hand on what the outputs released, and when a turn hands nothing back ask the core whether the graph settled. A budget that elapses first is reported, never passed off as done.
type Merge ¶
type Merge[M any] struct { // contains filtered or unexported fields }
Merge merges several channels into one tasklet, each source lifted into the merged value M by its own mapping.
type Overflow ¶
type Overflow string
Overflow is what a channel does when its consumer's mailbox is full.
type Relay ¶
type Relay interface {
Spec() RelaySpec
Channels(c *ChannelBuilder)
}
Relay is a relay type: its RelaySpec and its channels graph.
func ShortRelay ¶
func ShortRelay[I, S, O any](factoryID string, fn func(in I, ctx *Ctx[S, O]) (O, bool), opts ...ShortOptions) Relay
ShortRelay declares a one-tasklet relay from a function: it emits the value fn returns when the boolean is true, and nothing when it is false. The tasklet is named factoryID; a stateless one uses NoState.
Example ¶
package main
import (
"fmt"
"io"
"log/slog"
"strings"
"time"
flezha "github.com/flezha/flezha_go_sdk"
)
func main() {
upcase := flezha.ShortRelay("upcase", func(in string, _ *flezha.Ctx[flezha.NoState, string]) (string, bool) {
return strings.ToUpper(in), in != ""
}, flezha.ShortOptions{Codec: flezha.Text, Output: "out"})
run, err := flezha.StartLocal(upcase, flezha.WithLogger(quietLogger()))
if err != nil {
panic(err)
}
defer run.Close()
_ = run.OnOutput("out", func(out flezha.LocalOutput) { fmt.Println(string(out.Payload)) })
for _, in := range []string{"", "eur/usd"} {
_ = run.Feed("input", []byte(in))
}
if err := run.RunUntilIdle(10 * time.Second); err != nil {
panic(err)
}
}
func quietLogger() *slog.Logger { return slog.New(slog.NewTextHandler(io.Discard, nil)) }
Output: EUR/USD
func ShortTasklet ¶
func ShortTasklet[I, S, O any](factoryID string, t Tasklet[I, S, O], opts ...ShortOptions) Relay
ShortTasklet declares a one-tasklet relay from a tasklet type, whose hooks it keeps. The tasklet is named factoryID: its Spec leaves Name empty or writes the same id.
type RelaySpec ¶
type RelaySpec struct {
FactoryID string
Run any
Durable any
MaxDurationMs int64
Description string
}
RelaySpec is the factory id a relay registers under and its class settings, each written as the settings tree's own data: Run "steps" or map[string]any{"steps": map[string]any{"each": "per_input"}}, Durable false, "local" or map[string]any{"local": map[string]any{"sleep_after": 2000}}. Unwritten, the class runs as a flow and keeps its work locally. A finished instance keeps nothing unless the level sets "keep_finished" to hours, or to true for the controller's window (72 hours by default), so flz relay info can still show its Cells and result. The core reads the tree at registration and refuses a misplaced setting by name.
type Response ¶
Response is one outcome of a call, as its Response channel delivers it: the request the call end sent, the answer as Value or the Err the call ended in (a missed deadline is call.timeout), the callee's instance id, and whether this call started the callee.
type Routed ¶
Routed is one delivery of RouteLatest: the latest document, for one key. It travels as the JSON pair [key, document].
func (Routed[D]) MarshalJSON ¶
func (*Routed[D]) UnmarshalJSON ¶
type Runner ¶
type Runner struct {
// contains filtered or unexported fields
}
Runner is what an application starts: the relay types it registers and the connection that serves them. One runner per process; N processes are N runners, which the controller's placement already spreads relays across.
func CreateRunner ¶
func CreateRunner(namespace string, opts ...RunnerOption) (*Runner, error)
CreateRunner creates the runner of namespace. The linked core is checked here: a core of another activation schema is refused, naming both versions, before anything connects.
func (*Runner) AwaitTermination ¶
AwaitTermination blocks until the runner stops, then releases the core.
func (*Runner) Call ¶
Call calls the entry channel of relayID with value, through the controller under the same role check as Send, answering what the relay answers through its outputs: a JSON answer decoded, a text one as a string, a binary one as []byte, and a channel that does not answer as the controller's reply.
func (*Runner) Close ¶
func (r *Runner) Close()
Close shuts the runner down: every relay's state ships, what is in flight finishes, and AwaitTermination returns.
func (*Runner) RegisterFactory ¶
RegisterFactory registers a relay type, a full form or a short form alike. The declaration is judged by the core here, so a malformed one is refused at this call, with the core's code; after Start the controller learns of it at once.
func (*Runner) Relays ¶
Relays is the ids of the relay instances bound on this runner now, read without the controller.
func (*Runner) Send ¶
func (r *Runner) Send(relayID, channel string, message []byte, opts ...SendOption) (*SendVerdict, error)
Send sends message to the entry channel of relayID, through the controller under the same role check as Control, answering its verdict; a Local send answers nil.
func (*Runner) Start ¶
Start connects and starts serving: everything up to the first poll, and nothing that blocks after it. Go owns SIGTERM and SIGINT and hands the first to the core, which drains and exits; a closed standard input ends the runner the same way.
func (*Runner) UnregisterFactory ¶
UnregisterFactory undoes a registration. After Start the core refuses a relay type with live instances on this runner.
type RunnerOption ¶
type RunnerOption func(*runnerOptions)
RunnerOption configures CreateRunner and StartLocal.
func WithLogger ¶
func WithLogger(logger *slog.Logger) RunnerOption
WithLogger hands the runner the application's logger: the SDK's diagnostics and the core's notices go there, and nothing reaches standard error past it.
type SendOption ¶
type SendOption func(*sendOptions)
SendOption qualifies one Send.
func Local ¶
func Local() SendOption
Local sends in process, without the controller: the message is on no disk, is lost if the runner stops before handling it, and the relay's input log does not cover it.
func MsgID ¶
func MsgID(id string) SendOption
MsgID stamps the message as flz.msg_id, so a relay whose input log still holds that id absorbs the repeat.
func SendKey ¶
func SendKey(key string) SendOption
SendKey sends to the partition group member whose range owns key.
type SendVerdict ¶
SendVerdict is what the controller did with a message: delivered, absorbed or suspended, on the relay it reached.
type ShortOptions ¶
type ShortOptions struct {
Input string
Codec ChannelCodec
Output string
Run any
Durable any
MaxDurationMs int64
Description string
}
ShortOptions are a short form's channels and class settings: the entry channel ("input" when empty) and its codec, the plugin output the tasklet's output reaches (none when empty), and the RelaySpec settings.
type SpawnHandle ¶
type SpawnHandle struct {
// contains filtered or unexported fields
}
SpawnHandle is the answer to one SpawnSteps request. Read it inside the invocation that made it: once that invocation completes the core releases the handle, a failure nobody read is logged once instead, and a later read fails. Reading is optional.
func (*SpawnHandle) TryResult ¶
func (h *SpawnHandle) TryResult() (*SpawnResult, error)
TryResult is the answer if it has arrived, or nil while it is pending. It never waits.
func (*SpawnHandle) Wait ¶
func (h *SpawnHandle) Wait() (SpawnResult, error)
Wait waits for the controller's answer, up to the core's own bound. A spawn that reached no instance fails with the controller's code (such as relay.already_running) or the core's (spawn.timeout, spawn.unavailable).
type SpawnOption ¶
type SpawnOption func(*spawnOptions)
SpawnOption qualifies one SpawnSteps.
func IfRunning ¶
func IfRunning(policy string) SpawnOption
IfRunning says what a running instance under SpawnID gets: "deliver" (the default) feeds it the payload, "error" leaves it alone and the read fails.
func SpawnID ¶
func SpawnID(id string) SpawnOption
SpawnID names the instance, so a reissued request reaches the same one.
type SpawnOutcome ¶
type SpawnOutcome string
SpawnOutcome is what a spawn request did.
const ( Spawned SpawnOutcome = "spawned" Delivered SpawnOutcome = "delivered" SkippedOnReplay SpawnOutcome = "skipped_on_replay" )
type SpawnResult ¶
type SpawnResult struct {
ID string `json:"id"`
Outcome SpawnOutcome `json:"outcome"`
}
SpawnResult is the instance a spawn request reached, and how.
type Spec ¶
type Spec struct {
Name string
// A static key set; the tasklet implements CellsFor to route an input.
CellKeys []string
// Evict an idle dynamic cell after this long; 0 never.
IdleTTLSeconds int64
MaxCells int
// Serve the cell's change sequence as Now().
LogicalClock bool
// The per-cell mailbox capacity; nil is the core's default. A pointer, so
// a capacity of 0 can be written and refused by name.
MailboxCapacity *int
// The schema version the state and change records are written at; 0 is 1.
SchemaVersion uint32
// The oldest version still read; 0 is SchemaVersion.
MinReadableSchemaVersion uint32
// The pending timers one cell may hold; 0 is the core's default.
MaxTimersPerCell int
// The cell log size that asks for a snapshot; 0 is the controller's default.
CompactAfterBytes int64
}
Spec is everything a tasklet declares that is not behaviour, read once when the relay wiring it registers, never per message. Name is required: it is part of every cell's durable path, so renaming the Go type never moves saved state. A zero field leaves the core's default.
The cell mode is not declared here: a tasklet fed through KeyBy is dynamic, one with CellKeys static, and any other single.
type StartResult ¶
StartResult is the relay a start reached, and whether it started it.
type Stream ¶
type Stream[T any] struct { // contains filtered or unexported fields }
Stream is one edge under construction, carrying values of type T. It is a value: every call answers a new stream, so a shared prefix can branch without its arms colliding.
func Call ¶
Call ends this edge's chain in a call to another relay, and answers the stream of its Response channel, the entry channel `<channel>.response`. Every value reaching the call, after this chain's transforms and key, is one request. A call is not an edge, so the Response stream may feed the calling tasklet.
func Input ¶
func Input[T any](c *ChannelBuilder, name string, opts ...InputOptions) Stream[T]
Input declares a controller-fed entry channel whose payloads decode into T.
func InputDecoded ¶
func InputDecoded[T any](c *ChannelBuilder, name string, decode func([]byte) (T, error), opts ...InputOptions) Stream[T]
InputDecoded declares an entry channel whose payloads decode is the author's own.
func Into ¶
Into wires the stream into a tasklet whose input is the stream's element type, and answers the tasklet's output stream.
func IntoNamed ¶
IntoNamed is Into under an explicit node identity, for a second instance of one tasklet type.
func MergeIntoNamed ¶
MergeIntoNamed is MergeInto under an explicit node identity.
func RouteLatest ¶
func RouteLatest[D, T any](c *ChannelBuilder, documents Stream[D], traffic Stream[T], key func(T) string) Stream[Routed[D]]
RouteLatest turns a relay-wide document stream into per-key deliveries: every key seen on traffic receives each distinct document once, on that key's own next traffic item. Delivering on the key's own traffic keeps every key one this member owns after a rescale; the price is one tick of latency, and a key with no traffic receives nothing.
func RouteLatestNamed ¶
func RouteLatestNamed[D, T any](c *ChannelBuilder, documents Stream[D], traffic Stream[T], key func(T) string, nodeName string) Stream[Routed[D]]
RouteLatestNamed is RouteLatest under an explicit node identity, for a second router in one relay.
func (Stream[T]) Branch ¶
Branch fans out: each arm receives this same edge, so Branch builds exactly the topology the separate statements would.
func (Stream[T]) Filter ¶
Filter drops the values pred rejects; a dropped value is consumed and reaches no handler.
func (Stream[T]) KeyBy ¶
KeyBy routes by a computed key: the consumer becomes a dynamic keyed tasklet.
func (Stream[T]) Keyed ¶
Keyed stamps `flz.cell` / `flz.seq` / `flz.key` onto this channel's plugin frames.
func (Stream[T]) Output ¶
func (s Stream[T]) Output(name string, codec ...ChannelCodec) Stream[T]
Output terminates this edge's channel on the plugin layer. A name written here is the channel's name; "" leaves it derived. Without a codec a string or []byte is sent as it stands and anything else as JSON.
func (Stream[T]) OutputEncoded ¶
OutputEncoded is Output with the plugin frame's bytes written by encode.
func (Stream[T]) RetryBackoffMs ¶
RetryBackoffMs is the channel's backoff between attempts.
type Tasklet ¶
Tasklet is one processing step: a type with a Spec and a Run. A value leaves it only through ctx.Emit. Run returning nil completes the item; any other error is retried up the channel's retry ladder, and one wrapped by NonRetryable parks at once. A panic is recovered and retried as an error carrying its text.
A hook is declared by implementing it: InitState, Changes, OnTimer, EventTime, CellsFor, Compensate, MigrateState and MigrateChange, each with the tasklet's own I, S and O.
type TimerFiring ¶
TimerFiring is a fired timer, as OnTimer receives it. ctx.Now() inside the hook equals ScheduledAt, so a chained TimerAfter is replay-stable.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
flz-native
command
Command flz-native downloads the prebuilt core library the SDK links through cgo, checks it against the release's checksums, and prints the CGO_LDFLAGS line that points Go at it:
|
Command flz-native downloads the prebuilt core library the SDK links through cgo, checks it against the release's checksums, and prints the CGO_LDFLAGS line that points Go at it: |
|
Package flezhatest drives one tasklet without a controller, for an author's own tests: the SDK's own dispatch path over a one-tasklet relay, so what a test proves is what the runner does.
|
Package flezhatest drives one tasklet without a controller, for an author's own tests: the SDK's own dispatch path over a one-tasklet relay, so what a test proves is what the runner does. |
|
internal
|
|
|
check
Package check is the seam the conformance run judges a relay through: the SDK fills Derived at init, and the test app reads the declaration the core derived for a relay, with nothing registered and no runner.
|
Package check is the seam the conformance run judges a relay through: the SDK fills Derived at init, and the test app reads the declaration the core derived for a relay, with nothing registered and no runner. |
|
codec
Package codec is the `Activation` / `ActivationResult` boundary contract in Go: postcard, field for field as `crates/flz_core/src/schema.rs` declares it, at native.SchemaVersion.
|
Package codec is the `Activation` / `ActivationResult` boundary contract in Go: postcard, field for field as `crates/flz_core/src/schema.rs` declares it, at native.SchemaVersion. |
|
contract
Package contract finds the contract set: the fixtures under `test/fixtures` and the error catalogue every SDK is held to, which live in the core's tree.
|
Package contract finds the contract set: the fixtures under `test/fixtures` and the error catalogue every SDK is held to, which live in the core's tree. |
|
harness
Package harness is the seam between the SDK and its test harness: the SDK fills New at init, and package flezhatest drives one tasklet through it with the SDK's own dispatch path, never a second implementation of it.
|
Package harness is the seam between the SDK and its test harness: the SDK fills New at init, and package flezhatest drives one tasklet through it with the SDK's own dispatch path, never a second implementation of it. |
|
native
Package native is the Go binding of the core's C ABI: one function per entry point of `test/fixtures/abi_surface.txt`, called through cgo against the static `libflz_core_ffi.a`.
|
Package native is the Go binding of the core's C ABI: one function per entry point of `test/fixtures/abi_surface.txt`, called through cgo against the static `libflz_core_ffi.a`. |
|
The conformance run: every row of `test/fixtures/reference_topologies.txt` driven through THIS SDK's builder, so what is measured is what an author of a Go relay writes.
|
The conformance run: every row of `test/fixtures/reference_topologies.txt` driven through THIS SDK's builder, so what is measured is what an author of a Go relay writes. |