Event Service Agent Kata

Execution Module

← Back to Design Docs ← Documentation Home

Responsibility

Interfaces

Identity & Context

IDs Generated:

IDs Received (from StartExecution command):

Pattern:

```typescript ignore // Receive IDs from command const { tenantId, serviceCallId, requestSpec } = command

// Construct domain event (validated via Schema) const event = new ExecutionStarted({ tenantId, serviceCallId, startedAt: now, // DateTime.Utc })

// Publish with MessageMetadata Context yield * eventBus.publishExecutionStarted(event).pipe( Effect.provideService(MessageMetadata, { correlationId: command.correlationId, // Forward from command causationId: Option.some(commandEnvelopeId), // StartExecution envelope }), )


**Pattern** (execution-event-bus.adapter.ts - future implementation):

```typescript ignore
// Adapter extracts MessageMetadata from Context
const metadata = yield * MessageMetadata

// Generate envelope ID (UUID v7)
const envelopeId = yield * EnvelopeId.makeUUID7()

// Construct envelope via Schema class
const envelope: MessageEnvelope.Type = new MessageEnvelope({
	id: envelopeId,
	type: event._tag,
	payload: event,
	tenantId: event.tenantId,
	timestampMs: yield * clock.now(),
	correlationId: metadata.correlationId,
	causationId: metadata.causationId,
	aggregateId: Option.some(event.serviceCallId),
})

yield * eventBus.publish([envelope])

Rationale: Execution is stateless and doesn’t own any aggregates. All IDs flow through from Orchestration via StartExecution command. Adapter generates EnvelopeId (UUID v7) for broker deduplication. Workflow provides MessageMetadata Context, forwarding correlationId from command and setting causationId to command envelope ID. See ADR-0010 for identity generation strategy, ADR-0011 for schema patterns, and ADR-0013 for MessageMetadata Context pattern.

Behavior

– On StartExecution:

Notes

Resolve RequestSpec

Resolve RequestSpec

sequenceDiagram
  autonumber
  participant EXECUTION as Execution
  participant HTTP_CLIENT as HttpClientPort

  Note over EXECUTION,HTTP_CLIENT: solid = command/port, dashed = event
  link EXECUTION: Doc @ ./execution.md
  link HTTP_CLIENT: Port @ ../ports.md#httpclientport

  EXECUTION->>HTTP_CLIENT: execute(requestSpec)

Inputs/Outputs Recap

Sequence (StartExecution HTTP Outcome)

sequenceDiagram
  autonumber
  participant ORCHESTRATION as Orchestration
  participant EXECUTION as Execution
  participant HTTP_CLIENT as HttpClientPort
  participant EXTERNAL_SERVICE as External Service

  Note over ORCHESTRATION,EXECUTION: solid = command/port, dashed = event
  link ORCHESTRATION: Doc @ ./orchestration.md
  link EXECUTION: Doc @ ./execution.md

  ORCHESTRATION->>EXECUTION: StartExecution [command]
  EXECUTION-->>ORCHESTRATION: ExecutionStarted [event]
  EXECUTION->>HTTP_CLIENT: execute(requestSpec)
  HTTP_CLIENT->>EXTERNAL_SERVICE: request
  alt success
    EXTERNAL_SERVICE-->>HTTP_CLIENT: response(status, headers, body)
  HTTP_CLIENT-->>EXECUTION: ok(statusCode, headers, bodySnippet, durationMs)
  EXECUTION-->>ORCHESTRATION: ExecutionSucceeded [event]
  else failure/timeout
    EXTERNAL_SERVICE--x HTTP_CLIENT: error/timeout
  HTTP_CLIENT-->>EXECUTION: fail(kind, statusCode?, message, responseSnippet?, durationMs)
  EXECUTION-->>ORCHESTRATION: ExecutionFailed [event]
  end

State (Attempt lifecycle)

stateDiagram-v2
  [*] --> Starting: StartExecution received
  Starting --> Succeeded: Response ok
  Starting --> Failed: Timeout/Network/HttpError
  Succeeded --> [*]
  Failed --> [*]

Messages

Ports Used