3 Commits
Author SHA1 Message Date
zeekayandHanzo Dev 679ae61163 feat(transport): address the engine and the SDK, so both can use a socket
The engine took a PORT and the SDK an Options.HostPort, so neither end
could use a unix socket for traffic that never leaves the host. The
field name was not the only obstacle: luxfi/zap bound net.Listen("tcp",
":port") and reached a peer with net.DialTimeout("tcp", addr), so a path
was refused at the dialer with "missing port in address" and could not
be bound at all. That is fixed upstream (luxfi/zap Address + Network);
this pins the commit until it is tagged.

EmbedConfig.Address, Embedded.Address, ServeGated(addr) and
client.Options.Address each take ONE address, because a port is a detail
of one transport rather than a thing every listener has. A path binds or
dials a unix socket; anything else is host:port.

TestDialRequiresHostPort became TestDialRequiresAddress: Dial needs an
address, and asserts a socket path is refused for being absent rather
than for being portless. TestE2E_UnixSocket runs a real workflow over a
socket end to end, and TestE2E_UnixSocketRebind proves the socket is
unlinked on stop so a restart binds cleanly.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-28 16:27:19 -07:00
zeekay a9d72f6b95 feat(sdk/workflow): real wall-clock timers + edge-triggered Select
NewTimer used to collapse any duration to zero — production workflows
with schedule-level timers (24h dunning, weekly roll-up) fired on
the next dispatch loop tick. Selector busy-spun at 1 kHz.

Real timer.Timer behind each workflow.NewTimer; Selector.Await
blocks on fan-in over Future.readyCh channels. StubEnv becomes
test-only; the production dispatch env in pkg/sdk/worker uses the
real impl.

Closes red-review §5.2 and §5.9.
2026-04-23 12:29:21 -07:00
zeekay e0171b4015 feat(sdk/workflow): native Context/Future/Selector/Channel surface
Ports the workflow-code-facing API that base/plugins/tasks and
commerce/infra rely on today, with zero go.temporal.io or grpc
imports. Wire shape mirrors Temporal exactly so call-site migration
is a pure import-path swap.

Package layout (pkg/sdk/workflow):
  env.go       — CoroutineEnv interface, the one seam the worker
                 (pkg/sdk/worker, separately) must satisfy; Info,
                 SelectCase, CancelFunc. NewContextFromEnv is the
                 single entry point user ctx flows through.
  context.go   — Context interface (Deadline/Done/Err/Value), ctx
                 chain with WithCancel / WithValue / WithActivityOptions;
                 GetLogger, Now, Sleep, GetInfo.
  future.go    — Future + settleable impl. NewFuture / Settle split
                 so both the worker and the in-memory stub drive
                 completion through the same concrete. EncodePayload
                 is the Phase-1 JSON codec; Phase 2 swaps for ZAP.
  channel.go   — ReceiveChannel / Channel; unbuffered + buffered
                 chanImpl backing both user channels and signal
                 queues. Send/Receive/ReceiveAsync/Close.
  selector.go  — Selector with AddFuture / AddReceive / AddDefault;
                 Select delegates to env.Select and dispatches to
                 the matched callback.
  timer.go     — NewTimer schedules a durable timer Future.
  signal.go    — GetSignalChannel returns shared-by-name signal queues.
  activity.go  — ActivityOptions mirror of Temporal shape;
                 WithActivityOptions attaches per-call opts;
                 ExecuteActivity reads opts from ctx and dispatches.
  reflect.go   — Sole reflect use site (activity name resolution).
  stub.go      — StubEnv: synchronous, in-memory CoroutineEnv for
                 unit-testing workflow code without a worker.
                 OnActivity(...).Return(...), SignalAsync, AdvanceClock,
                 Cancel. Used throughout workflow_test.go.
  workflow_test.go — 27 tests exercising Context, cancel scopes,
                 Now/Sleep, timers, activities (success/error/nil),
                 signal channels, user channels, Selector (future/
                 receive/default), and an end-to-end AgentTaskWorkflow-
                 shaped test that mirrors base/plugins/tasks.

Phase 1 determinism caveats (documented in env.go):
  * No event-sourced replay yet — crashes restart from the top with
    the original input. Same idempotency contract as Temporal.
  * Payloads encoded as JSON, not the canonical ZAP codec.
  * time.Now / rand / goroutines inside workflow code remain banned;
    CI linter comes in a follow-up.

go vet clean. 27 tests pass including -race.
go list -deps reports zero go.temporal.io or google.golang.org/grpc.
2026-04-23 10:34:17 -07:00