reply

package
v1.18.1 Latest Latest
Warning

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

Go to latest
Published: Oct 12, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Overview

Package reply carries what a workflow did with a message back to a caller that is waiting for it.

A push source answers its caller as soon as the message is queued, so the caller never learns whether the workflow delivered it. A transport that wants to answer with the result instead calls Expect before it dispatches the message and waits; the engine, when it has finished with the message, calls Resolve. The two meet through an id carried in the message's metadata, so nothing between them — source wrappers, buffers, the router — has to know.

Both ends are in one process: a push source's transport and the engine that runs its workflow already have to be.

Index

Constants

View Source
const (
	HeaderConversationID = "X-Conversation-Id"
	MetaConversationID   = "conversation_id"
)

A conversation id ties the messages of one chat together, so a workflow can remember what was said earlier in it. A caller sends it with each message (HeaderConversationID) and the transport puts it in the message's metadata (MetaConversationID); a synchronous caller that sent none is given one in the answer, to send with its next message.

View Source
const (
	ConfigMode    = "response_mode"
	ConfigTimeout = "response_timeout"

	// ModeSync holds the caller until the workflow has finished with the
	// message. Anything else, including nothing, answers once it is queued.
	ModeSync = "sync"
)

Config keys a push source carries to say how it answers its caller.

View Source
const (
	// DefaultTimeout is how long a synchronous caller is held when the source
	// names no timeout, or one that does not parse.
	DefaultTimeout = 30 * time.Second
	// MaxTimeout caps what a source may ask for. A request held open is a
	// connection and a waiter held open.
	MaxTimeout = 5 * time.Minute
)
View Source
const MetaReplyID = "_hermod_reply_id"

MetaReplyID is the metadata key under which an awaited message carries the id its waiter is registered under.

Variables

View Source
var ErrTooManyPending = errors.New("too many requests are waiting for a workflow result")

ErrTooManyPending is returned by Expect when the limit on callers waiting at once is reached.

Functions

func IDOf

func IDOf(msg hermod.Message) (string, bool)

IDOf returns the reply id of an awaited message.

func ModeOf

func ModeOf(config map[string]string) (wait bool, timeout time.Duration)

ModeOf reads how a source answers from its configuration: whether the caller waits, and for how long.

A timeout that is missing, unreadable or not positive is the default, never "no timeout" and never a fall back to answering at once.

func NewConversationID added in v1.18.0

func NewConversationID() string

NewConversationID starts a conversation.

func Resolve

func Resolve(id string, o Outcome) bool

Resolve hands an outcome to the caller waiting under id, and reports whether there was one. A message is resolved once: the waiter is removed as it is answered, so a replayed message carrying the same id reaches nobody.

func Take

func Take(msg hermod.Message) (string, bool)

Take returns the reply id of an awaited message and removes it from the message. The engine calls it as it starts on a message: the id is how it finds the caller, and from there on it is nobody else's business — left on the message it is written to every sink and handed back in the record.

func ValidConversationID added in v1.18.0

func ValidConversationID(id string) bool

ValidConversationID reports whether id is 1 to 128 characters of letters, digits, '.', '_', ':' and '-'. The id comes from the caller and ends up in storage keys and response headers, so anything else is refused rather than escaped.

Types

type Outcome

type Outcome struct {
	Status Status
	// Error describes the failure. Empty for Delivered and Completed.
	Error string
	// Record is the message as the workflow left it, as JSON: what a sink was
	// sent when it was delivered, and the message itself otherwise.
	Record []byte
}

Outcome is what the waiting caller is told.

type Pending

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

Pending is one caller waiting for one message.

func Expect

func Expect(msg hermod.Message) (*Pending, error)

Expect marks msg as awaited and registers the caller as its waiter. Call it before the message is dispatched, and Cancel when done waiting.

func (*Pending) Cancel

func (p *Pending) Cancel()

Cancel stops waiting. An outcome that arrives afterwards is dropped. It is safe to call more than once and after the message was resolved.

func (*Pending) Wait

func (p *Pending) Wait(ctx context.Context) (Outcome, error)

Wait blocks until the engine resolves the message or ctx ends.

type Status

type Status string

Status says what the workflow did with a message.

const (
	// Delivered: written to every sink the workflow routed it to.
	Delivered Status = "delivered"
	// Completed: the workflow ran and had nothing to write — it has no sink, or
	// it is a dry run.
	Completed Status = "completed"
	// Filtered: the workflow ran and chose to deliver it nowhere — a filter
	// dropped it, or its outcome had no edge to follow.
	Filtered Status = "filtered"
	// DeadLettered: it failed and was parked in the dead-letter sink.
	DeadLettered Status = "dead_lettered"
	// Failed: it failed and is not preserved anywhere.
	Failed Status = "failed"
)

Jump to

Keyboard shortcuts

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