invoker

package
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 23, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

Documentation

Overview

Package invoker defines packtrail's agnostic node-invocation contract. The engine never speaks a wire protocol directly: every task/branch node is executed through an Invoker. This is the single seam that makes packtrail reusable beyond any one ecosystem — a project plugs in its own Invoker (an agent caller, an HTTP client, a NATS request/reply worker) and inherits all of packtrail's durability, retries, fan-in policies, choice routing, signals and timers.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Cache

type Cache struct {
	// contains filtered or unexported fields
}

Cache is an Invoker decorator that makes invocations idempotent under packtrail's at-least-once delivery. Every step is driven by a durable work message; if an engine crashes after invoking a node but before persisting the advance/ack, the work item is redelivered and the node would otherwise run twice — double side effects (a re-billed LLM call, a duplicate write, a second e-mail).

Cache keys a stored Result by (execution, node, attempt). A redelivery of the same attempt is served from the cache and never reaches the delegate, while a genuine retry (a new attempt number) gets a fresh key and does re-run, exactly as the node's retry policy intends. Transport errors are never cached, so a failed call is always retried.

Cache solves the engine-side double-dispatch window. It cannot make a non-deterministic task deterministic; an Invoker with external side effects it cannot see should still carry its own idempotency key where it can.

func NewCache

func NewCache(kv jetstream.KeyValue, delegate Invoker) *Cache

NewCache wraps delegate so its results are deduplicated through kv.

func (*Cache) Invoke

func (c *Cache) Invoke(ctx context.Context, req Request) (Result, error)

Invoke returns a cached Result for this (execution, node, attempt) if present; otherwise it calls the delegate and caches a non-error result before returning it.

type Func

type Func func(ctx context.Context, req Request) (Result, error)

Func adapts a plain function to the Invoker interface.

func (Func) Invoke

func (f Func) Invoke(ctx context.Context, req Request) (Result, error)

Invoke implements Invoker.

type Invoker

type Invoker interface {
	Invoke(ctx context.Context, req Request) (Result, error)
}

Invoker executes a single node invocation. Implementations must be safe for concurrent use: the engine invokes many nodes in parallel.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry dispatches an invocation to a registered Invoker by kind (Request.Invoker). It is itself an Invoker, so the engine holds exactly one Invoker regardless of how many kinds are configured.

func NewRegistry

func NewRegistry() *Registry

NewRegistry returns an empty Registry.

func (*Registry) Has

func (r *Registry) Has(kind string) bool

Has reports whether kind is registered.

func (*Registry) Invoke

func (r *Registry) Invoke(ctx context.Context, req Request) (Result, error)

Invoke routes req to the Invoker registered under req.Invoker.

func (*Registry) Register

func (r *Registry) Register(kind string, inv Invoker)

Register binds kind to inv, replacing any previous binding for kind.

type Request

type Request struct {
	Invoker     string          `json:"invoker"`      // invoker kind selected for this node
	Target      string          `json:"target"`       // invoker-specific target (resolved)
	ExecutionID string          `json:"execution_id"` // owning execution
	NodeID      string          `json:"node_id"`      // node being executed
	Payload     json.RawMessage `json:"payload"`      // shared execution context
	Attempt     int             `json:"attempt"`      // 0-based attempt number
	Deadline    time.Time       `json:"deadline"`     // hard deadline for this attempt
}

Request is everything an Invoker needs to execute one node invocation. It is transport-agnostic: Target is interpreted by the chosen Invoker (a subject, an agent name, a URL, …) and any {execution_id} placeholder is already resolved.

type Result

type Result struct {
	Status  Status          `json:"status"`
	Payload json.RawMessage `json:"payload,omitempty"`
	Error   string          `json:"error,omitempty"`
}

Result is what an Invoker returns. A non-nil error from Invoke is treated as a transient transport failure (equivalent to StatusRetry) and is never cached.

type Status

type Status string

Status is the outcome an Invoker reports for a single invocation. The string values intentionally match the built-in nats-task wire contract so transports can map onto them directly.

const (
	// StatusOK means the node succeeded; Result.Payload is the new shared context.
	StatusOK Status = "ok"
	// StatusError means the node failed permanently; the engine does not retry.
	StatusError Status = "error"
	// StatusRetry means the node asks to be retried per its node retry policy.
	StatusRetry Status = "retry"
	// StatusPending means the node was dispatched asynchronously and will be
	// settled later via Engine.CompleteActivity. The engine parks the execution
	// (waiting) and frees its work slot; Result.Payload is ignored. Use this for
	// long-running activities (e.g. an agent call) so the engine does not block.
	StatusPending Status = "pending"
)

Directories

Path Synopsis
Package natstask is packtrail's built-in Invoker: a NATS request/reply caller that speaks the pkg/protocol envelope.
Package natstask is packtrail's built-in Invoker: a NATS request/reply caller that speaks the pkg/protocol envelope.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL