Documentation
¶
Overview ¶
Package backgroundtask provides a shared lifecycle registry for long-running executions (sub-agents, shell commands, ...) that may outlive the tool call that launched them.
Manager coordinates TaskStore-backed submission, execution, and control. It is deliberately non-generic so one instance can serve heterogeneous executor domains under one task-ID space.
TaskEvent is append-only progress. Spec.OutputFile and Task.OutputFileErr describe an optional derived transcript projection; transcript failure never changes authoritative lifecycle status or replaces terminal ResultData.
Persistence providers should run the reusable suites in adk/backgroundtask/storetest before deployment.
Index ¶
- Constants
- Variables
- func NotifyParent(ctx context.Context, req *NotifyParentRequest) error
- func TaskCreatedSessionEventID(taskID string) string
- func TaskCreatedSessionEventSender[M adk.MessageType]() func(context.Context, *Task) error
- type AckCancelRequest
- type AllocateTaskIDRequest
- type AppendTaskEventRequest
- type AppendTaskEventResult
- type CloseOption
- type CommitStartRequest
- type CompleteTaskRequest
- type Config
- type ControlKind
- type ControlRequest
- type CreateTaskRequest
- type ExecutionDirective
- type ExecutionResult
- type ExecutionRuntime
- type Executor
- type ExecutorRegistry
- type FailTaskRequest
- type HeartbeatRequest
- type IDGenerator
- type InMemoryStore
- func (s *InMemoryStore) Ack(_ context.Context, receipt NotificationReceipt) error
- func (s *InMemoryStore) AckCancel(_ context.Context, req *AckCancelRequest) (*Task, error)
- func (s *InMemoryStore) AppendTaskEvent(_ context.Context, req *AppendTaskEventRequest) (*AppendTaskEventResult, error)
- func (s *InMemoryStore) CommitStart(_ context.Context, req *CommitStartRequest) (*Task, error)
- func (s *InMemoryStore) Complete(_ context.Context, req *CompleteTaskRequest) (*Task, error)
- func (s *InMemoryStore) Create(_ context.Context, req *CreateTaskRequest) (*Task, error)
- func (s *InMemoryStore) EnqueueTaskNotification(_ context.Context, taskID string, attempt int64, req *NotifyParentRequest) error
- func (s *InMemoryStore) Fail(_ context.Context, req *FailTaskRequest) (*Task, error)
- func (s *InMemoryStore) Get(_ context.Context, taskID string) (*Task, error)
- func (s *InMemoryStore) Heartbeat(_ context.Context, req *HeartbeatRequest) (*Task, error)
- func (s *InMemoryStore) ListPending(_ context.Context, req *ListPendingRequest) (*ListPendingResult, error)
- func (s *InMemoryStore) ListSuspended(_ context.Context, req *ListSuspendedRequest) (*ListSuspendedResult, error)
- func (s *InMemoryStore) ListTaskEvents(_ context.Context, req *ListTaskEventsRequest) (*ListTaskEventsResult, error)
- func (s *InMemoryStore) Receive(_ context.Context, req *ReceiveNotificationsRequest) (*ReceiveNotificationsResult, error)
- func (s *InMemoryStore) ReleaseSuspension(_ context.Context, req *ReleaseSuspensionRequest) (*Task, error)
- func (s *InMemoryStore) ReportTranscriptFailure(_ context.Context, req *ReportTranscriptFailureRequest) (*Task, error)
- func (s *InMemoryStore) RequestCancel(_ context.Context, req *RequestCancelRequest) (*Task, error)
- func (s *InMemoryStore) Resume(_ context.Context, req *ResumeRequest) (*Task, error)
- func (s *InMemoryStore) Start(_ context.Context, req *StartTaskRequest) (*Task, error)
- func (s *InMemoryStore) Suspend(_ context.Context, req *SuspendTaskRequest) (*Task, error)
- func (s *InMemoryStore) WaitForTaskVersion(ctx context.Context, req *WaitForTaskVersionRequest) (*Task, error)
- func (s *InMemoryStore) WaitInput(_ context.Context, req *WaitInputTaskRequest) (*Task, error)
- func (s *InMemoryStore) Yield(_ context.Context, req *YieldTaskRequest) (*Task, error)
- type InMemoryStoreConfig
- type LeaseExpiryPolicy
- type ListPendingRequest
- type ListPendingResult
- type ListSuspendedRequest
- type ListSuspendedResult
- type ListTaskEventsRequest
- type ListTaskEventsResult
- type Manager
- func (m *Manager) AllocateTaskID(ctx context.Context, request *AllocateTaskIDRequest) (string, error)
- func (m *Manager) Close(ctx context.Context, options ...CloseOption) error
- func (m *Manager) Execute(ctx context.Context, taskID string) error
- func (m *Manager) Get(ctx context.Context, taskID string) (*Task, error)
- func (m *Manager) ListPending(ctx context.Context, req *ListPendingRequest) (*ListPendingResult, error)
- func (m *Manager) ListSuspended(ctx context.Context, req *ListSuspendedRequest) (*ListSuspendedResult, error)
- func (m *Manager) ListTaskEvents(ctx context.Context, req *ListTaskEventsRequest) (*ListTaskEventsResult, error)
- func (m *Manager) ReleaseSuspension(ctx context.Context, taskID string) (*Task, error)
- func (m *Manager) RequestCancel(ctx context.Context, taskID string, options ...RequestCancelOption) (*Task, error)
- func (m *Manager) Resume(ctx context.Context, req *ResumeRequest) (*Task, error)
- func (m *Manager) Submit(ctx context.Context, spec Spec) (*Task, error)
- func (m *Manager) WaitForTaskVersion(ctx context.Context, req *WaitForTaskVersionRequest) (*Task, error)
- type Notification
- type NotificationDelivery
- type NotificationKind
- type NotificationOutbox
- type NotificationReceipt
- type NotificationWriter
- type NotifyParentRequest
- type ProgressEmission
- type ReceiveNotificationsRequest
- type ReceiveNotificationsResult
- type ReleaseSuspensionRequest
- type ReportTranscriptFailureRequest
- type RequestCancelOption
- type RequestCancelRequest
- type ResumeRequest
- type Spec
- type StartCommitRuntime
- type StartTaskRequest
- type Status
- type SuspendTaskRequest
- type Task
- type TaskCreatedSessionEvent
- type TaskEvent
- type TaskEventStore
- type TaskStore
- type WaitForTaskVersionRequest
- type WaitInputTaskRequest
- type YieldTaskRequest
Constants ¶
const SessionEventTaskCreated adk.SessionEventKind = "x.eino.background_task.created"
SessionEventTaskCreated is appended to a parent session after its background task has been durably created.
Variables ¶
var ( // ErrNotFound reports that a task or notification record does not exist. ErrNotFound = errors.New("backgroundtask: task not found") // ErrAlreadyExists reports that a task or registry entry already exists. ErrAlreadyExists = errors.New("backgroundtask: task already exists") // ErrVersionConflict reports that ExpectedVersion no longer matches the stored record. ErrVersionConflict = errors.New("backgroundtask: task version conflict") // ErrLeaseLost reports that an operation is no longer authorized by its lease. ErrLeaseLost = errors.New("backgroundtask: lease lost") // ErrIllegalTransition reports that a requested lifecycle transition is invalid. ErrIllegalTransition = errors.New("backgroundtask: illegal state transition") // ErrInvalidExecutionResult reports that an executor result or TaskStore // transition payload violates lifecycle result invariants. ErrInvalidExecutionResult = errors.New("backgroundtask: invalid execution result") // ErrAlreadyTerminal reports that a task has already reached a terminal status. ErrAlreadyTerminal = errors.New("backgroundtask: task is already terminal") // produce or locate a safe compatible checkpoint. Manager stops renewing the // current lease so expiry can redispatch from the last durable checkpoint. ErrDrainCheckpointUnavailable = errors.New("backgroundtask: drain checkpoint unavailable") // ErrCloseDeadlineRequired reports that Manager.Close was called with active // attempts but its context has no deadline. The Manager remains open. ErrCloseDeadlineRequired = errors.New("backgroundtask: close deadline is required while tasks are active") // ErrUnsupportedExecutorPayloadVersion reports that the selected executor // cannot decode the version of the persisted Spec.Payload envelope. ErrUnsupportedExecutorPayloadVersion = errors.New("backgroundtask: unsupported executor payload version") // ErrTaskEventIDConflict reports that one task-local EventID was replayed // with bytes different from the originally persisted event. ErrTaskEventIDConflict = errors.New("backgroundtask: task event id conflict") // ErrInvalidCursor reports that a pagination cursor is malformed or cannot // continue the requested task-event snapshot and ordering. ErrInvalidCursor = errors.New("backgroundtask: invalid cursor") // cannot route an application notification to a parent session. ErrNotificationUnavailable = errors.New( "backgroundtask: parent notification unavailable", ) // ErrNotificationEventIDConflict reports that a task-local notification // EventID was replayed with different Kind or Data. ErrNotificationEventIDConflict = errors.New( "backgroundtask: notification event id conflict", ) )
Functions ¶
func NotifyParent ¶
func NotifyParent(ctx context.Context, req *NotifyParentRequest) error
NotifyParent emits one idempotent application notification using authority bound to the current managed attempt context. It returns ErrNotificationUnavailable outside a managed attempt or when the configured TaskStore lacks NotificationWriter. Store errors are returned unchanged.
func TaskCreatedSessionEventID ¶
TaskCreatedSessionEventID returns the deterministic session-local EventID for taskID. Immediate Runner emission and outbox-based recovery must use the same ID so TaskCreated delivery is idempotent.
func TaskCreatedSessionEventSender ¶
TaskCreatedSessionEventSender creates a Config.SendTaskCreatedEvent callback. It emits through the active ChatModelAgent run so Runner remains the sole writer of the parent session timeline.
Types ¶
type AckCancelRequest ¶
type AckCancelRequest struct {
TaskID string
ExpectedVersion int64
// Reason is used when no durable cancellation reason was previously recorded.
Reason string
}
AckCancelRequest records active-attempt acknowledgement of cancellation.
type AllocateTaskIDRequest ¶
type AllocateTaskIDRequest struct {
Kind string
}
AllocateTaskIDRequest describes the task category used by the default ID generator. Kind is not persisted independently and must be empty or a 64-byte ASCII identifier segment containing letters, digits, '-' or '_'.
type AppendTaskEventRequest ¶
AppendTaskEventRequest appends one identified progress event for the active task attempt. EventID uniqueness is task-wide across attempts.
type AppendTaskEventResult ¶
AppendTaskEventResult reports whether the event was newly inserted. A byte-identical replay returns the original Event with Inserted false.
type CloseOption ¶
type CloseOption func(*closeOptions)
CloseOption configures Manager shutdown.
func WithDrainReason ¶
func WithDrainReason(reason string) CloseOption
WithDrainReason attaches an optional advisory reason to drain controls sent while closing a Manager. The reason is not persisted as terminal task state.
type CommitStartRequest ¶
CommitStartRequest records that the external operation for the current running attempt was established and persists its initial checkpoint.
type CompleteTaskRequest ¶
CompleteTaskRequest records successful task completion.
type Config ¶
type Config struct {
// Tasks is the authoritative task lifecycle provider. When nil, New installs
// an in-memory reference provider. Manager also discovers the optional
// NotificationWriter capability from this provider.
Tasks TaskStore
// TaskEvents persists append-only progress in the same task namespace and
// must fence appends against the active attempt authorized by Tasks. When
// nil, New reuses Tasks when it also implements TaskEventStore. If both are
// nil, the same in-memory reference provider supplies both capabilities.
TaskEvents TaskEventStore
// Executors resolves serialized task intent to local implementations.
Executors *ExecutorRegistry
// SendTaskCreatedEvent emits a TaskCreated timeline event after a task is
// durably created. It may be called concurrently. Tasks without a parent
// SessionID do not emit this event. Use TaskCreatedSessionEventSender so the
// active Runner assigns and persists the event in causal turn order.
SendTaskCreatedEvent func(context.Context, *Task) error
// IDGen, when set, decides the full ID of every task created by this Manager.
// If nil, Manager uses its default task-type-prefixed Base64URL ID.
//
// IDGen may be called concurrently by task submitters. It
// must return a non-empty ID. The returned ID must be unique among this
// Manager's registered tasks; a duplicate fails task creation.
IDGen IDGenerator
}
Config configures a Manager.
type ControlKind ¶
type ControlKind string
ControlKind identifies a Manager control signal sent to an executor.
const ( // ControlStop asks the executor to stop as soon as practical. Reason is the // optional durable cancellation reason. ControlStop ControlKind = "stop" // ControlDrain asks the executor to relinquish gracefully. The executor may // checkpoint and suspend or yield without a checkpoint according to its // recovery model. Reason is optional advisory operational context. ControlDrain ControlKind = "drain" // ControlTimeout asks the executor to fail with a non-empty deterministic reason. ControlTimeout ControlKind = "timeout" )
type ControlRequest ¶
type ControlRequest struct {
Kind ControlKind
Reason string
}
ControlRequest carries a Manager control signal to an executor. For ControlStop, Reason is optional and sourced from durable cancellation intent. It is optional and advisory for ControlDrain, and always non-empty for ControlTimeout.
type CreateTaskRequest ¶
type CreateTaskRequest struct {
Spec Spec
LeaseExpiryPolicy LeaseExpiryPolicy
}
CreateTaskRequest creates a task from immutable serialized intent and the recovery policy owned by its registered Executor. TaskStore assigns all lifecycle timestamps, including Task.CreatedAt.
type ExecutionDirective ¶
type ExecutionDirective string
ExecutionDirective is a non-lifecycle instruction returned by an Executor.
const ( // ExecutionDirectiveYield relinquishes a recoverable active attempt while // the logical operation continues outside the current Worker. ExecutionDirectiveYield ExecutionDirective = "yield" )
type ExecutionResult ¶
type ExecutionResult struct {
Directive ExecutionDirective
Status Status
Checkpoint []byte
Data []byte
Error string
}
ExecutionResult describes one legal executor outcome:
- Yield: DirectiveYield plus an optional Checkpoint; all lifecycle fields empty.
- Completed: StatusCompleted plus optional Data.
- Failed or Canceled: the corresponding status plus Error.
- WaitingInput or Suspended: the corresponding status plus Checkpoint.
Fields from different variants must not be combined.
type ExecutionRuntime ¶
type ExecutionRuntime interface {
// Controls returns a runtime-owned channel. Signals may be coalesced; the
// executor must stop selecting it when the attempt context ends.
Controls() <-chan ControlRequest
// EmitProgress appends replayable progress. An empty event ID requests a
// framework-generated stable ID. FirstEmission is false when the same ID and
// bytes were already accepted for the task.
EmitProgress(context.Context, string, []byte) (ProgressEmission, error)
// ReportTranscriptFailure records the first non-lifecycle failure of the
// optional derived transcript.
ReportTranscriptFailure(context.Context, error) error
}
ExecutionRuntime exposes concurrency-safe, attempt-scoped capabilities. Storage fencing fields remain private to the runtime.
type Executor ¶
type Executor interface {
// Key is a stable persisted routing key.
Key() string
// LeaseExpiryPolicy is immutable for tasks created by this executor.
LeaseExpiryPolicy() LeaseExpiryPolicy
// ValidateSpec is repeatable, side-effect free, and runs before persistence.
ValidateSpec(Spec) error
// ValidateExecution performs side-effect-free validation immediately before
// an attempt is claimed.
ValidateExecution(context.Context, *Task) error
// SupportsDrain reports whether Execute handles ControlDrain by returning a
// resumable suspended or yielded result.
SupportsDrain() bool
// Execute owns the attempt until it returns. It must observe ctx and runtime
// controls and return exactly one legal ExecutionResult variant.
Execute(context.Context, *Task, ExecutionRuntime) (*ExecutionResult, error)
}
Executor reconstructs and runs durable work from a task Spec.
type ExecutorRegistry ¶
type ExecutorRegistry struct {
// contains filtered or unexported fields
}
ExecutorRegistry resolves executors by ExecutorKey.
func NewExecutorRegistry ¶
func NewExecutorRegistry() *ExecutorRegistry
NewExecutorRegistry creates an empty executor registry.
func (*ExecutorRegistry) Keys ¶
func (r *ExecutorRegistry) Keys() []string
Keys returns the registered executor keys.
func (*ExecutorRegistry) LoadOrRegister ¶
func (r *ExecutorRegistry) LoadOrRegister(executor Executor) (Executor, bool, error)
LoadOrRegister atomically returns the executor registered under the candidate's key, registering the candidate when the key is not yet present.
func (*ExecutorRegistry) Register ¶
func (r *ExecutorRegistry) Register(executor Executor) error
Register adds an executor keyed by executor.Key().
type FailTaskRequest ¶
FailTaskRequest records failed task completion.
type HeartbeatRequest ¶
HeartbeatRequest reports liveness for an active attempt.
type IDGenerator ¶
type IDGenerator func(ctx context.Context, request *AllocateTaskIDRequest) (string, error)
IDGenerator returns the complete ID for a new task.
The generator sees the allocation request before the task is registered and may return a business-side identifier. Manager does not add the task-type prefix when IDGen is configured; callers that want one should include it in the returned ID.
type InMemoryStore ¶
type InMemoryStore struct {
// contains filtered or unexported fields
}
InMemoryStore is a deterministic reference implementation of TaskStore, TaskEventStore, NotificationWriter, and NotificationOutbox. It is a state-machine test double, not a durable backend.
func NewInMemoryStore ¶
func NewInMemoryStore(config *InMemoryStoreConfig) *InMemoryStore
NewInMemoryStore creates an in-memory reference task provider and outbox.
func (*InMemoryStore) Ack ¶
func (s *InMemoryStore) Ack(_ context.Context, receipt NotificationReceipt) error
Ack removes the notification authorized by a current unexpired receipt.
func (*InMemoryStore) AckCancel ¶
func (s *InMemoryStore) AckCancel(_ context.Context, req *AckCancelRequest) (*Task, error)
AckCancel commits terminal acknowledgement of durable cancellation intent.
func (*InMemoryStore) AppendTaskEvent ¶
func (s *InMemoryStore) AppendTaskEvent( _ context.Context, req *AppendTaskEventRequest, ) (*AppendTaskEventResult, error)
AppendTaskEvent fences by attempt before task-wide EventID deduplication.
func (*InMemoryStore) CommitStart ¶
func (s *InMemoryStore) CommitStart( _ context.Context, req *CommitStartRequest, ) (*Task, error)
CommitStart records the external-start boundary for the running attempt.
func (*InMemoryStore) Complete ¶
func (s *InMemoryStore) Complete(_ context.Context, req *CompleteTaskRequest) (*Task, error)
Complete commits successful terminal output.
func (*InMemoryStore) Create ¶
func (s *InMemoryStore) Create(_ context.Context, req *CreateTaskRequest) (*Task, error)
Create inserts one pending task and returns an independent snapshot.
func (*InMemoryStore) EnqueueTaskNotification ¶
func (s *InMemoryStore) EnqueueTaskNotification( _ context.Context, taskID string, attempt int64, req *NotifyParentRequest, ) error
EnqueueTaskNotification fences by attempt before task-wide EventID replay detection and atomically records replay metadata with its outbox item.
func (*InMemoryStore) Fail ¶
func (s *InMemoryStore) Fail(_ context.Context, req *FailTaskRequest) (*Task, error)
Fail commits terminal failure.
func (*InMemoryStore) Get ¶
Get returns an independent authoritative snapshot and resolves expired leases.
func (*InMemoryStore) Heartbeat ¶
func (s *InMemoryStore) Heartbeat(_ context.Context, req *HeartbeatRequest) (*Task, error)
Heartbeat renews the current active attempt lease.
func (*InMemoryStore) ListPending ¶
func (s *InMemoryStore) ListPending(_ context.Context, req *ListPendingRequest) (*ListPendingResult, error)
ListPending returns task-ID-ordered pending snapshots.
func (*InMemoryStore) ListSuspended ¶
func (s *InMemoryStore) ListSuspended( _ context.Context, req *ListSuspendedRequest, ) (*ListSuspendedResult, error)
ListSuspended returns task-ID-ordered suspended snapshots.
func (*InMemoryStore) ListTaskEvents ¶
func (s *InMemoryStore) ListTaskEvents( _ context.Context, req *ListTaskEventsRequest, ) (*ListTaskEventsResult, error)
ListTaskEvents returns one snapshot-stable append-order page.
func (*InMemoryStore) Receive ¶
func (s *InMemoryStore) Receive(_ context.Context, req *ReceiveNotificationsRequest) (*ReceiveNotificationsResult, error)
Receive leases visible notifications with fresh opaque receipts.
func (*InMemoryStore) ReleaseSuspension ¶
func (s *InMemoryStore) ReleaseSuspension(_ context.Context, req *ReleaseSuspensionRequest) (*Task, error)
ReleaseSuspension returns a suspended task to pending.
func (*InMemoryStore) ReportTranscriptFailure ¶
func (s *InMemoryStore) ReportTranscriptFailure(_ context.Context, req *ReportTranscriptFailureRequest) (*Task, error)
ReportTranscriptFailure records the first derived-transcript error.
func (*InMemoryStore) RequestCancel ¶
func (s *InMemoryStore) RequestCancel(_ context.Context, req *RequestCancelRequest) (*Task, error)
RequestCancel records first-write cancellation intent.
func (*InMemoryStore) Resume ¶
func (s *InMemoryStore) Resume(_ context.Context, req *ResumeRequest) (*Task, error)
Resume stores one opaque input and returns a waiting task to pending.
func (*InMemoryStore) Start ¶
func (s *InMemoryStore) Start(_ context.Context, req *StartTaskRequest) (*Task, error)
Start claims a pending task and creates a fenced active attempt.
func (*InMemoryStore) Suspend ¶
func (s *InMemoryStore) Suspend(_ context.Context, req *SuspendTaskRequest) (*Task, error)
Suspend commits a checkpointed planned pause.
func (*InMemoryStore) WaitForTaskVersion ¶
func (s *InMemoryStore) WaitForTaskVersion(ctx context.Context, req *WaitForTaskVersionRequest) (*Task, error)
WaitForTaskVersion blocks until the stored task has a Version greater than req.AfterVersion. WaitForTaskVersion waits until Task.Version exceeds AfterVersion.
func (*InMemoryStore) WaitInput ¶
func (s *InMemoryStore) WaitInput(_ context.Context, req *WaitInputTaskRequest) (*Task, error)
WaitInput commits a checkpointed wait for external input.
func (*InMemoryStore) Yield ¶
func (s *InMemoryStore) Yield(_ context.Context, req *YieldTaskRequest) (*Task, error)
Yield relinquishes an attempt and returns the task to pending.
type InMemoryStoreConfig ¶
type InMemoryStoreConfig struct {
// ActiveAttemptTimeout defaults to 30 seconds.
ActiveAttemptTimeout time.Duration
// MaxValueBytes defaults to 1 MiB and bounds each checkpoint, successful
// result, resume input, and task-event data value.
MaxValueBytes int64
}
InMemoryStoreConfig configures the in-memory reference task provider.
type LeaseExpiryPolicy ¶
type LeaseExpiryPolicy string
LeaseExpiryPolicy controls how TaskStore resolves an expired active attempt.
const ( // LeaseExpiryRetry returns the task to pending for another durable attempt. LeaseExpiryRetry LeaseExpiryPolicy = "retry" // LeaseExpiryFail terminally fails work that cannot be reconstructed after process loss. LeaseExpiryFail LeaseExpiryPolicy = "fail" )
type ListPendingRequest ¶
ListPendingRequest lists pending task candidates for the given executor keys. Results use stable task-ID order. Cursor continues after the previous page; it is scoped to the same provider and filter. Limit defaults to 100 and is capped at 1000.
type ListPendingResult ¶
ListPendingResult contains independent task snapshots. NextCursor is empty when the current traversal is exhausted.
type ListSuspendedRequest ¶
ListSuspendedRequest lists suspended tasks with the same ordering, cursor, filter, and limit rules as ListPendingRequest.
type ListSuspendedResult ¶
ListSuspendedResult contains independent task snapshots. NextCursor is empty when the current traversal is exhausted.
type ListTaskEventsRequest ¶
ListTaskEventsRequest requests one snapshot-stable page of task events. NewestFirst selects reverse append order; Cursor continues the same task, direction, and snapshot established by the first page. Limit defaults to 100 and is capped at 1000; callers may change Limit between pages. An empty first page has no continuation cursor.
type ListTaskEventsResult ¶
ListTaskEventsResult contains an independently owned page and an opaque continuation cursor. NextCursor is empty when the captured snapshot has been exhausted.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager owns TaskStore-backed lifecycle and worker coordination.
func New ¶
New creates a Manager. A nil Config installs the in-memory reference stores and a new executor registry. When Tasks is supplied without TaskEvents, Tasks must also implement TaskEventStore. The context is reserved for constructor symmetry; Manager does not retain it or derive task lifetime from it.
func (*Manager) AllocateTaskID ¶
func (m *Manager) AllocateTaskID(ctx context.Context, request *AllocateTaskIDRequest) (string, error)
AllocateTaskID allocates an opaque ID for a task category.
func (*Manager) Close ¶
func (m *Manager) Close(ctx context.Context, options ...CloseOption) error
Close performs bounded graceful shutdown. When any attempt is active, ctx must have a deadline or Close returns ErrCloseDeadlineRequired without closing the Manager. Drainable attempts receive ControlDrain and may suspend or yield according to their executor contract; non-drainable attempts may finish until the deadline and are then durably canceled. Deadline expiry cannot force an uncooperative executor to return; Manager remains closed to new submissions, while read and cancellation methods remain available.
func (*Manager) ListPending ¶
func (m *Manager) ListPending(ctx context.Context, req *ListPendingRequest) (*ListPendingResult, error)
ListPending is the read-only dispatch boundary. A worker may select and dispatch a task ID from this result; only Execute performs start authorization. Ordering, cursor, limit, and snapshot ownership follow ListPendingRequest.
func (*Manager) ListSuspended ¶
func (m *Manager) ListSuspended( ctx context.Context, req *ListSuspendedRequest, ) (*ListSuspendedResult, error)
ListSuspended returns checkpointed tasks that require an explicit release before workers may claim them again. Pagination follows ListPendingRequest.
func (*Manager) ListTaskEvents ¶
func (m *Manager) ListTaskEvents( ctx context.Context, req *ListTaskEventsRequest, ) (*ListTaskEventsResult, error)
ListTaskEvents reads one snapshot-stable page of task events.
func (*Manager) ReleaseSuspension ¶
ReleaseSuspension returns a suspended task to pending so a worker can claim a new attempt from its persisted checkpoint.
func (*Manager) RequestCancel ¶
func (m *Manager) RequestCancel( ctx context.Context, taskID string, options ...RequestCancelOption, ) (*Task, error)
RequestCancel records cancellation intent and signals a local active attempt. An optional reason is durable and first-write across repeated requests. Process-local non-recoverable work may wait for terminal acknowledgement; recoverable work may return the still-running snapshot after intent is durable.
func (*Manager) Resume ¶
Resume persists opaque input for a task waiting on external input. The concrete executor must defensively validate the persisted input before use; Manager intentionally does not know executor-specific resume schemas.
func (*Manager) Submit ¶
Submit validates serialized intent, persists a pending task, and emits its TaskCreated parent-session event before returning success. If event emission fails after persistence, Submit returns the task with the error; retrying the identical Spec on the same Manager retries that failed emission. Other duplicate task IDs return ErrAlreadyExists.
func (*Manager) WaitForTaskVersion ¶
func (m *Manager) WaitForTaskVersion(ctx context.Context, req *WaitForTaskVersionRequest) (*Task, error)
WaitForTaskVersion blocks until the authoritative task snapshot has a Version greater than req.AfterVersion. Task progress events do not advance Version and therefore do not satisfy the wait.
type Notification ¶
type Notification struct {
ID string
TaskID string
SessionID string
Version int64
Kind NotificationKind
Data []byte
CreatedAt time.Time
}
Notification is one durable session-routed lifecycle or application event. Lifecycle records have empty Data; consumers load authoritative task state by TaskID when needed. Application Data is opaque and independently owned.
type NotificationDelivery ¶
type NotificationDelivery struct {
Record Notification
Receipt NotificationReceipt
}
NotificationDelivery contains a notification and its acknowledgement receipt.
type NotificationKind ¶
type NotificationKind string
NotificationKind identifies the lifecycle transition that created a notification.
const ( // NotificationTaskCreated reports that a parent-owned task was created. It // is the durable recovery source for TaskCreated session-event delivery. NotificationTaskCreated NotificationKind = "task_created" // NotificationWaitingInput reports that a task is paused waiting for resume input. NotificationWaitingInput NotificationKind = "waiting_input" // NotificationCompleted reports that a task completed successfully. NotificationCompleted NotificationKind = "completed" // NotificationFailed reports that a task failed. NotificationFailed NotificationKind = "failed" // NotificationCanceled reports that a task was canceled. NotificationCanceled NotificationKind = "canceled" )
type NotificationOutbox ¶
type NotificationOutbox interface {
Receive(context.Context, *ReceiveNotificationsRequest) (*ReceiveNotificationsResult, error)
Ack(context.Context, NotificationReceipt) error
}
NotificationOutbox leases task notifications for dispatch. The NotificationTaskCreated record is the durable recovery source for reconciling a TaskCreated parent-session event if the creating process exits before Runner persists its immediate timeline emission. Ack must accept only the opaque receipt for the notification's current unexpired lease; an expired or superseded receipt must not acknowledge the notification. Receive normalizes limits to default 100 and maximum 1000. Both sides copy receipt bytes, and successful notification records remain until acknowledged.
type NotificationReceipt ¶
type NotificationReceipt []byte
NotificationReceipt is an opaque token authorizing acknowledgement of one notification during its current lease. Callers and providers must copy its bytes and must not mutate a receipt after passing it across the SPI.
type NotificationWriter ¶
type NotificationWriter interface {
EnqueueTaskNotification(
ctx context.Context,
taskID string,
attempt int64,
req *NotifyParentRequest,
) error
}
NotificationWriter atomically authorizes and enqueues application notifications from the exact active task attempt. Implementations derive the immutable parent SessionID from the stored Spec, fence attempt, lease, and cancellation before replay lookup, and retain replay metadata for at least the task lifetime. Notification.Version captures the current Task version without advancing it. Implementations copy request Data before retaining it.
type NotifyParentRequest ¶
type NotifyParentRequest struct {
EventID string
Kind NotificationKind
Data []byte
}
NotifyParentRequest describes one application notification emitted by the current durable attempt. EventID is task-local, idempotent, required, and limited to 1024 bytes. Kind is required, limited to 64 bytes, and must not use a lifecycle kind or the reserved "eino." prefix. Data is opaque and limited to 256 KiB. Bounds are measured in bytes.
type ProgressEmission ¶
type ProgressEmission struct {
EventID string
// FirstEmission is false for an idempotent replay of an event already
// accepted for this task.
FirstEmission bool
}
ProgressEmission reports the stable identity and replay status of one executor progress event.
type ReceiveNotificationsRequest ¶
ReceiveNotificationsRequest leases visible notifications from an outbox. Limit defaults to 100 and is capped at 1000. LeaseDuration must be positive.
type ReceiveNotificationsResult ¶
type ReceiveNotificationsResult struct {
Deliveries []NotificationDelivery
}
ReceiveNotificationsResult contains leased notification deliveries.
type ReleaseSuspensionRequest ¶
ReleaseSuspensionRequest returns a suspended task to pending.
type ReportTranscriptFailureRequest ¶
ReportTranscriptFailureRequest records the first failure of an optional derived transcript. It does not change task lifecycle status; later reports preserve the first recorded error.
type RequestCancelOption ¶
type RequestCancelOption func(*requestCancelOptions)
RequestCancelOption configures durable cancellation intent.
func WithCancellationReason ¶
func WithCancellationReason(reason string) RequestCancelOption
WithCancellationReason records an optional durable reason for stopping a task. The first cancellation request wins.
type RequestCancelRequest ¶
type RequestCancelRequest struct {
TaskID string
ExpectedVersion int64
// Reason is optional and first-write for repeated cancellation requests.
Reason string
}
RequestCancelRequest records durable cancellation intent. Active work remains running until its attempt acknowledges cancellation. Retry-capable work whose lease was lost remains pending until a recovery attempt stops the operation.
type ResumeRequest ¶
ResumeRequest stores input for the current waiting checkpoint and returns the task to pending. ExpectedVersion binds the input to that exact request. The command remains durable across retry-capable attempt loss until execution reaches another waiting or suspended checkpoint, or a terminal state.
type Spec ¶
type Spec struct {
ID string
ExecutorKey string
Kind string
Payload []byte
Description string
OutputFile string
SessionID string
NotifySession bool
}
Spec is immutable serialized task intent supplied by the caller. Payload and all returned byte slices must be copied across provider boundaries. OutputFile names an optional derived transcript destination; it is not authoritative task output. Providers may impose documented size bounds such as InMemoryStoreConfig.
type StartCommitRuntime ¶
StartCommitRuntime is an optional execution capability for atomically recording that an executor established its external operation. Manager runtimes implement it; keeping it separate preserves ExecutionRuntime source compatibility for custom executors and test doubles.
type StartTaskRequest ¶
StartTaskRequest asks the TaskStore to authorize a new active attempt.
type Status ¶
type Status string
Status represents the durable lifecycle status of a task.
const ( // StatusPending indicates the task is durable and available for claim. StatusPending Status = "pending" // StatusRunning indicates the task is currently executing. StatusRunning Status = "running" // StatusWaitingInput indicates execution is checkpointed pending external input. StatusWaitingInput Status = "waiting_input" // StatusSuspended indicates execution is checkpointed for a planned pause. // It is not claimable until Manager.ReleaseSuspension returns it to pending. StatusSuspended Status = "suspended" // StatusCompleted indicates the task finished successfully. StatusCompleted Status = "completed" // StatusFailed indicates the task terminated with an error. StatusFailed Status = "failed" // StatusCanceled indicates the task acknowledged an external stop request. StatusCanceled Status = "canceled" )
type SuspendTaskRequest ¶
SuspendTaskRequest checkpoints a task for a planned suspension.
type Task ¶
type Task struct {
// Spec is the immutable serialized intent for this task.
Spec Spec
// LeaseExpiryPolicy is the immutable recovery policy selected by the
// registered Executor when the task is created.
LeaseExpiryPolicy LeaseExpiryPolicy
// Status is the current lifecycle status.
Status Status
// Checkpoint is the latest durable executor checkpoint.
Checkpoint []byte
// ResultData is the terminal successful output. It is meaningful only when
// Status is StatusCompleted.
ResultData []byte
// ResultError is the terminal failure or cancellation reason. It is meaningful
// only when Status is StatusFailed or StatusCanceled.
ResultError string
// OutputFileErr records the first failure while producing the optional output transcript.
OutputFileErr string
// PendingResume is the durable resume command for the current checkpoint.
// Retry-capable attempt loss or yield preserves it for idempotent replay. A
// subsequent wait-input or suspended checkpoint, or a terminal transition,
// consumes it.
PendingResume []byte
// Version is the CAS version of this durable record.
Version int64
// Attempt counts successful claims.
Attempt int64
// CancelRequestedAt records durable explicit stop intent while Status remains
// StatusRunning until the active attempt acknowledges it as StatusCanceled.
CancelRequestedAt *time.Time
// CancelReason is the optional first-write reason accompanying durable stop
// intent. It becomes ResultError when the task reaches StatusCanceled.
CancelReason string
// CreatedAt is the TaskStore-assigned creation time.
CreatedAt time.Time
// UpdatedAt is the TaskStore mutation time.
UpdatedAt time.Time
// DoneAt is the time the task reached a terminal state. Nil if still running.
DoneAt *time.Time
}
Task represents one independently owned snapshot. Providers and callers must deep-copy mutable slices and time pointers when snapshots cross their boundary; mutating a returned Task must never alter persisted state.
type TaskCreatedSessionEvent ¶
type TaskCreatedSessionEvent struct {
TaskID string `json:"task_id"`
}
TaskCreatedSessionEvent is the extension payload for SessionEventTaskCreated.
type TaskEvent ¶
TaskEvent is one immutable task-progress event. EventID is an opaque, task-local replay identity and does not encode event chronology.
type TaskEventStore ¶
type TaskEventStore interface {
AppendTaskEvent(context.Context, *AppendTaskEventRequest) (*AppendTaskEventResult, error)
ListTaskEvents(context.Context, *ListTaskEventsRequest) (*ListTaskEventsResult, error)
}
TaskEventStore persists append-ordered task progress independently from lifecycle snapshots. AppendTaskEvent must fence writes by the active attempt before task-wide EventID replay detection, retain replay metadata across attempts for at least the task lifetime, and not advance Task.Version. ListTaskEvents must keep each cursor on the snapshot captured by its first page and order events by append position, reversed when NewestFirst is true. Event data and result pages are independently owned. Successful events and cursor positions remain readable for at least the lifetime of their task.
type TaskStore ¶
type TaskStore interface {
Create(context.Context, *CreateTaskRequest) (*Task, error)
Get(context.Context, string) (*Task, error)
ListPending(context.Context, *ListPendingRequest) (*ListPendingResult, error)
ListSuspended(context.Context, *ListSuspendedRequest) (*ListSuspendedResult, error)
Start(context.Context, *StartTaskRequest) (*Task, error)
Heartbeat(context.Context, *HeartbeatRequest) (*Task, error)
CommitStart(context.Context, *CommitStartRequest) (*Task, error)
ReportTranscriptFailure(context.Context, *ReportTranscriptFailureRequest) (*Task, error)
Complete(context.Context, *CompleteTaskRequest) (*Task, error)
Fail(context.Context, *FailTaskRequest) (*Task, error)
WaitInput(context.Context, *WaitInputTaskRequest) (*Task, error)
Suspend(context.Context, *SuspendTaskRequest) (*Task, error)
Yield(context.Context, *YieldTaskRequest) (*Task, error)
AckCancel(context.Context, *AckCancelRequest) (*Task, error)
RequestCancel(context.Context, *RequestCancelRequest) (*Task, error)
Resume(context.Context, *ResumeRequest) (*Task, error)
ReleaseSuspension(context.Context, *ReleaseSuspensionRequest) (*Task, error)
WaitForTaskVersion(context.Context, *WaitForTaskVersionRequest) (*Task, error)
}
TaskStore persists authoritative task snapshots and semantic lifecycle transitions.
Every returned Task and mutable field is independently owned by the caller. ListPending and ListSuspended follow their request ordering, cursor, and limit contracts; malformed cursors return ErrInvalidCursor. When the provider also implements NotificationOutbox, Create atomically enqueues NotificationTaskCreated for every task with a parent SessionID.
RequestCancel on active work keeps StatusRunning, sets CancelRequestedAt and the first-write optional CancelReason, and advances Version. Once cancellation is requested, Heartbeat, Complete, Fail, WaitInput, Suspend, and Yield must reject the attempt; only AckCancel may terminally acknowledge it. CommitStart records the successful external-start boundary while retaining StatusRunning, requires a non-empty initial checkpoint envelope, advances Version, and must reject a second start commit while that checkpoint remains present. Yield changes running to pending, stores its optional checkpoint atomically, preserves PendingResume for idempotent replay, and emits no lifecycle notification. Retry-capable lease expiry also preserves PendingResume. A later WaitInput, Suspend, or terminal transition consumes it. On retry-capable work, cancel intent that outlives an attempt remains pending so a recovery attempt can stop the external operation before acknowledging cancellation. Non-recoverable lease expiry resolves cancellation directly.
type WaitForTaskVersionRequest ¶
WaitForTaskVersionRequest identifies a task and the latest snapshot version observed by the caller. Task progress events do not advance Version.
type WaitInputTaskRequest ¶
WaitInputTaskRequest checkpoints a task that is waiting for external input.
type YieldTaskRequest ¶
YieldTaskRequest relinquishes an active recoverable attempt and returns the task to pending without implying that the underlying operation was suspended. An empty Checkpoint retains the task's latest boundary checkpoint. Any pending resume command is also retained for idempotent replay.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package local executes non-serializable process-local closures as managed tasks.
|
Package local executes non-serializable process-local closures as managed tasks. |
|
Package shell adapts recoverable logical commands to managed background tools.
|
Package shell adapts recoverable logical commands to managed background tools. |
|
Package storetest provides reusable conformance suites for background-task persistence providers.
|
Package storetest provides reusable conformance suites for background-task persistence providers. |
|
Package subagent provides a durable backgroundtask executor for ADK sub-agent runs.
|
Package subagent provides a durable backgroundtask executor for ADK sub-agent runs. |
|
Package tool adapts explicitly capable external tools to durable background tasks.
|
Package tool adapts explicitly capable external tools to durable background tasks. |
|
tooltest
Package tooltest provides conformance checks for managed background tool implementations.
|
Package tooltest provides conformance checks for managed background tool implementations. |