Download the PHP package ruudk/absurd-php-sdk without Composer
On this page you can find all versions of the php package ruudk/absurd-php-sdk. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download ruudk/absurd-php-sdk
More information about ruudk/absurd-php-sdk
Files in ruudk/absurd-php-sdk
Package absurd-php-sdk
Short Description PHP SDK for Absurd: a Durable Execution Engine for Postgres
License MIT
Informations about the package absurd-php-sdk
Absurd SDK for PHP
PHP SDK for Absurd: a PostgreSQL-based durable task execution system.
Absurd is the simplest durable execution workflow system you can think of. It's entirely based on Postgres and nothing else. It's almost as easy to use as a queue, but it handles scheduling and retries, and it does all of that without needing any other services to run in addition to Postgres.
Note: This PHP SDK is still in its early stages. Absurd itself has been running in production at Earendil since its initial release.
What is Durable Execution?
Durable execution (or durable workflows) is a way to run long-lived, reliable functions that can survive crashes, restarts, and network failures without losing state or duplicating work. Instead of running your logic in memory, a durable execution system decomposes a task into smaller pieces (step functions) and records every step and decision.
How It Works
This SDK uses PHP Fibers to provide a clean, synchronous-looking
API for durable workflows. When you call methods like $ctx->step(), $ctx->awaitEvent(), or $ctx->sleepFor(), the
Fiber suspends execution, allowing the SDK to checkpoint progress to the database. When the task resumes (after a crash,
timeout, or event), execution continues from exactly where it left off.
This means you can write workflow code that looks like normal sequential PHP code, while the SDK handles all the complexity of persistence, retries, and resumption behind the scenes.
Installation
Quick Start
Client Configuration
The Absurd constructor accepts a Connection instance instead of a raw PDO object. Wrap your PDO with
PdoConnection (or implement your own adapter, e.g. for Doctrine DBAL):
The serializer defaults to JsonSerializer (no extra dependencies). Pass SymfonySerializer if you need typed object
deserialization:
Custom Database Connection
Implement Connection\Connection to integrate with any database layer (e.g. Doctrine DBAL):
Queue Management
Task Registration
Spawning Tasks
Retry Strategies
Task Context Methods
Inside a task handler, you have access to TaskContext with these methods:
Emitting Events
Cancelling Tasks
Running tasks will stop at their next checkpoint, heartbeat, or await event call.
Retrying Tasks
Force a retry of a failed or cancelled task:
Use the BeforeRetryEvent to modify retry options from a listener (same pattern as BeforeSpawnEvent).
Retrieving Task Info
Worker Configuration
Worker Concurrency Model
PHP workers process tasks sequentially within a single process. The batchSize option controls how many tasks are
claimed from the database in each poll, but they are still executed one at a time. This design ensures:
- Predictable resource usage per worker
- Simple error isolation (one task failure doesn't affect others)
- No need for complex thread-safety considerations
For concurrent task processing, run multiple worker processes:
Or use a process manager like Supervisor:
Events
Use a PSR-14 EventDispatcherInterface for lifecycle hooks and error handling.
Available Events
| Event | Dispatched when |
|---|---|
WorkerStartedEvent |
Worker begins polling |
WorkerStoppedEvent |
Worker stops |
WorkerRunningEvent |
After each poll cycle (idle or after batch completion) |
TaskStartedEvent |
A task is picked up for execution |
TaskCompletedEvent |
A task finishes (includes suspended tasks) |
TaskFailedEvent |
A task throws an unhandled exception |
TaskErrorEvent |
Any error occurs (task or worker level) |
BeforeSpawnEvent |
Before a task is spawned (options are mutable) |
BeforeRetryEvent |
Before a task is retried (options are mutable) |
TaskExecutionEvent |
Wraps task execution (for context propagation) |
Typed Payloads
With a serializer that supports type hydration (like the shipped SymfonySerializer), you can use typed objects as task
parameters:
Idempotency Keys
Use idempotency keys to prevent duplicate task creation:
Use task ID for deriving idempotency keys for external APIs:
Local Development
Prerequisites
- Docker and Docker Compose
- GitHub CLI (
gh) - for downloading Absurd binaries
Quick Start
After running make up:
- PostgreSQL is available at
localhost:54329 - Habitat UI (task dashboard) is available at http://localhost:7890
Running the Examples
The SDK includes two comprehensive examples:
E-commerce Order Fulfillment
Demonstrates checkpoints, events, sub-tasks, and trace propagation in a realistic order processing scenario.
AI Agent with Tool Calling
Demonstrates a durable AI agent workflow based on this blog post. The agent loops through conversation steps, calling tools as needed, with each iteration durably checkpointed.
Features:
- Loop-based agent with automatic checkpointing per iteration
- OpenAI integration with tool calling (get_weather, search_web, calculate)
- Automatic recovery from crashes - resumes from last checkpoint
- Durable conversation state stored in PostgreSQL
Make Commands
| Command | Description |
|---|---|
make help |
Show available commands |
make setup |
Download absurdctl binary |
make up |
Start PostgreSQL, initialize Absurd, and run Habitat |
make down |
Stop containers |
make clean |
Remove binaries and database volumes |
Production Setup
For production, initialize Absurd in your PostgreSQL database:
API Reference
Absurd Class
| Method | Description |
|---|---|
registerTask(name, handler, options?) |
Register a task handler |
spawn(taskName, params, options?, queue?) |
Spawn a new task |
retryTask(taskId, options?, queue?) |
Retry a failed or cancelled task |
getTask(taskId, queueName?) |
Get task info by ID |
emitEvent(eventName, payload?, queueName?) |
Emit an event |
cancelTask(taskId, queueName?) |
Cancel a running task |
claimTasks(options?) |
Claim tasks for processing |
startWorker(options?) |
Start a worker |
createQueue(queueName?) |
Create a queue |
dropQueue(queueName?) |
Drop a queue |
listQueues() |
List all queues |
executeTask(task, claimTimeout, ...) |
Execute a claimed task |
TaskContext Class
| Method | Description |
|---|---|
step(name, value) |
Execute a checkpointed step |
beginStep(name) |
Begin a split step, returns a StepHandle |
completeStep(handle, value) |
Complete a split step, returns the value (cached on replay) |
awaitEvent(eventName, options?) |
Wait for an event |
sleepFor(stepName, duration) |
Sleep for a duration (seconds) |
sleepUntil(stepName, wakeAt) |
Sleep until a specific time |
emitEvent(eventName, payload?) |
Emit an event from within a task |
heartbeat(seconds?) |
Extend the task lease |
SpawnResult Class
| Property | Type | Description |
|---|---|---|
taskId |
string | Unique task identifier |
runId |
string | Current run identifier |
attempt |
int | Current attempt number |
created |
bool | True if newly created, false if from idempotency cache |