mirror of
https://github.com/hanzoai/tasks.git
synced 2026-10-04 02:04:03 +00:00
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]>
109 lines
4.1 KiB
Go
109 lines
4.1 KiB
Go
// Package client is the Hanzo Tasks workflow client. Native ZAP transport,
|
|
// zero go.temporal.io/* and zero google.golang.org/grpc imports.
|
|
//
|
|
// The wire is ZAP framed per schema/tasks.zap. Opcodes 0x0060-0x009F are
|
|
// owned by this package; 0x0050-0x005F stay reserved for the legacy
|
|
// one-shot/schedule surface owned by pkg/tasks.
|
|
//
|
|
// v1 wire note: request and response payloads are transported as a single
|
|
// bytes field holding JSON. Native ZAP serde for every RPC in schema/tasks.zap
|
|
// replaces JSON in a follow-up without changing opcodes.
|
|
package client
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/hanzoai/tasks/pkg/sdk/temporal"
|
|
)
|
|
|
|
// Options configures Dial. Fields mirror the upstream Temporal Options
|
|
// surface so callers can swap import paths without changing arguments.
|
|
type Options struct {
|
|
// Address is where the Hanzo Tasks frontend exposes its ZAP
|
|
// transport. A filesystem path dials a unix socket — the right shape
|
|
// for service-to-service traffic that never leaves the host, and one
|
|
// that needs no port. Anything else is a host:port TCP address.
|
|
// Required unless Transport is injected.
|
|
Address string
|
|
|
|
// Namespace scopes every RPC issued by the returned Client. Empty
|
|
// string is rewritten to "default" at Dial time.
|
|
Namespace string
|
|
|
|
// Identity is sent as the caller identity on long-poll / worker RPCs.
|
|
// Optional; defaults to "hanzo-tasks-sdk".
|
|
Identity string
|
|
|
|
// DialTimeout bounds the initial ZAP connect. Zero means "no bound".
|
|
DialTimeout time.Duration
|
|
|
|
// CallTimeout bounds a single request/response round trip. Zero
|
|
// means "no bound per call" — callers are expected to pass their
|
|
// own ctx deadline.
|
|
CallTimeout time.Duration
|
|
|
|
// Transport overrides the default ZAP transport. Primarily for
|
|
// testing — leave nil in production.
|
|
Transport Transport
|
|
|
|
// Token supplies the caller's IAM identity to an identity-gated Tasks
|
|
// frontend (a ServeGated listener running RequireIdentity). It is called
|
|
// per request so a short-lived client_credentials bearer refreshes
|
|
// transparently; the returned token rides every JSON-body RPC (client
|
|
// lifecycle + worker Subscribe) as auth_token, and the frontend scopes the
|
|
// request to the token owner's org. nil (default) sends no auth_token —
|
|
// correct for an ungated / loopback frontend. Binary worker respond frames
|
|
// stay task_token-gated and carry none.
|
|
Token TokenSource
|
|
}
|
|
|
|
// TokenSource returns the bearer to present to an identity-gated Tasks frontend.
|
|
// Use StaticToken for a fixed token; a client_credentials caller returns a fresh
|
|
// bearer per call (cache with expiry) so a long-lived worker never presents an
|
|
// expired identity.
|
|
type TokenSource func(ctx context.Context) (string, error)
|
|
|
|
// StaticToken adapts a fixed bearer to a TokenSource.
|
|
func StaticToken(tok string) TokenSource {
|
|
return func(context.Context) (string, error) { return tok, nil }
|
|
}
|
|
|
|
// StartWorkflowOptions mirrors the upstream StartWorkflowOptions struct
|
|
// for ExecuteWorkflow. Only the fields currently mapped onto the wire
|
|
// (schema/tasks.zap StartWorkflowRequest + Timeouts + RetryPolicy) are
|
|
// meaningful; unlisted fields are ignored by the v1 wire.
|
|
type StartWorkflowOptions struct {
|
|
// ID is the workflow ID. Empty string asks the server to generate
|
|
// one (returned as WorkflowRun.GetID()).
|
|
ID string
|
|
|
|
// TaskQueue is required; workers poll this queue for tasks.
|
|
TaskQueue string
|
|
|
|
// WorkflowExecutionTimeout is the total allowed wall-clock time
|
|
// across all runs (Continue-As-New chains).
|
|
WorkflowExecutionTimeout time.Duration
|
|
|
|
// WorkflowRunTimeout is the allowed wall-clock time for a single
|
|
// run.
|
|
WorkflowRunTimeout time.Duration
|
|
|
|
// WorkflowTaskTimeout bounds a single workflow-task attempt on a
|
|
// worker. Default on server is 10s.
|
|
WorkflowTaskTimeout time.Duration
|
|
|
|
// RetryPolicy overrides the workflow-level retry policy (distinct
|
|
// from per-activity retry).
|
|
RetryPolicy *temporal.RetryPolicy
|
|
|
|
// CronSchedule makes the workflow recurring. Empty string runs once.
|
|
CronSchedule string
|
|
|
|
// Memo is opaque metadata attached to the execution.
|
|
Memo map[string]any
|
|
|
|
// SearchAttributes are indexed by the visibility store.
|
|
SearchAttributes map[string]any
|
|
}
|