Overview
The Activity class is the base class for all durable activities. Activities represent individual units of work that can fail and retry independently within a workflow.
Traits Used
Dispatchable - Enables dispatching activities to queues
InteractsWithQueue - Provides queue interaction methods
Queueable - Makes activities queueable
RouteDependencyResolverTrait - Resolves method dependencies
SerializesModels - Handles model serialization
Properties
Number of times the activity should be attempted (defaults to unlimited)
Maximum number of exceptions allowed before failing (defaults to unlimited)
Maximum execution time in seconds (0 means no timeout)
Unique key for the activity instance
Constructor
public function __construct(
public int $index,
public string $now,
public StoredWorkflow $storedWorkflow,
...$arguments
)
Creates a new activity instance with workflow context and execution arguments.
The index position of this activity in the workflow execution history
The timestamp when the activity was scheduled
The parent workflow’s persisted state
Variable arguments passed to the activity execute method
Example
use Workflow\Activity;
class ProcessPaymentActivity extends Activity
{
public function execute(float $amount, string $currency = 'USD')
{
// Activity logic here
}
}
// Constructor is called internally by the framework
$activity = new ProcessPaymentActivity($index, $now, $storedWorkflow, 100.00, 'USD');
Methods
backoff()
public function backoff()
Defines the backoff strategy for retrying failed activities.
Returns: Array of seconds to wait between retry attempts: [1, 2, 5, 10, 15, 30, 60, 120]
Example
public function backoff()
{
return [5, 10, 30, 60]; // Custom backoff strategy
}
uniqueId()
public function uniqueId()
Returns a unique identifier for this activity instance, combining workflow ID and index.
Returns: String in format "{workflow_id}:{index}"
Example
$id = $activity->uniqueId();
// Returns: "01234567-89ab-cdef-0123-456789abcdef:5"
workflowId()
public function workflowId()
Returns the parent workflow’s ID.
Returns: The stored workflow ID
Example
$workflowId = $activity->workflowId();
// Returns: "01234567-89ab-cdef-0123-456789abcdef"
webhookUrl()
public function webhookUrl(string $signalMethod = ''): string
Generates a webhook URL for starting workflows or sending signals.
Optional signal method name. If empty, returns workflow start URL
Returns: Absolute URL for the webhook endpoint
Example
use Workflow\Activity;
class SendEmailActivity extends Activity
{
public function execute(string $email)
{
// Get workflow start URL
$startUrl = $this->webhookUrl();
// Get signal URL
$signalUrl = $this->webhookUrl('confirmEmail');
// Send email with URLs
Mail::send('email.confirmation', [
'confirmUrl' => $signalUrl,
], function($message) use ($email) {
$message->to($email);
});
}
}
handle()
Main activity execution handler. Calls the execute() method and handles exceptions.
Returns: The result of the execute() method
Note: This method is called internally by the framework. You should define the execute() method instead.
Example
// Framework calls handle() internally
// You define the execute() method:
class ProcessPaymentActivity extends Activity
{
public function execute(float $amount)
{
// Your activity logic
return PaymentGateway::charge($amount);
}
}
middleware()
public function middleware()
Defines queue middleware for the activity. By default, applies WithoutOverlappingMiddleware and ActivityMiddleware.
Returns: Array of middleware instances
Example
public function middleware()
{
return [
new RateLimited('activities'),
new WithoutOverlapping($this->uniqueId()),
];
}
failed()
public function failed(Throwable $throwable): void
Called when the activity permanently fails after all retries. Dispatches an exception event.
The exception that caused the failure
Example
public function failed(Throwable $throwable): void
{
parent::failed($throwable);
// Custom failure handling
Log::error('Activity failed', [
'activity' => static::class,
'workflow_id' => $this->workflowId(),
'error' => $throwable->getMessage(),
]);
}
heartbeat()
public function heartbeat(): void
Sends a heartbeat signal for long-running activities. Updates timeout tracking and sets process alarm.
Example
use Workflow\Activity;
class LongRunningActivity extends Activity
{
public $timeout = 300; // 5 minutes
public function execute(array $items)
{
foreach ($items as $item) {
$this->heartbeat(); // Reset timeout
// Process item (takes time)
$this->processItem($item);
}
}
private function processItem($item)
{
// Long-running operation
}
}
Complete Example
use Workflow\Activity;
use Illuminate\Support\Facades\Http;
use Workflow\Exceptions\NonRetryableException;
class ProcessPaymentActivity extends Activity
{
public $tries = 5;
public $timeout = 30;
public function backoff()
{
return [1, 5, 15, 30, 60];
}
public function execute(float $amount, string $paymentMethod)
{
try {
$response = Http::timeout($this->timeout)
->post('https://api.payment-gateway.com/charge', [
'amount' => $amount,
'method' => $paymentMethod,
]);
if ($response->failed()) {
// Invalid payment method - don't retry
if ($response->status() === 400) {
throw new NonRetryableException(
'Invalid payment method'
);
}
// Temporary error - will retry
throw new \Exception('Payment gateway error');
}
return $response->json();
} catch (\Throwable $e) {
if ($e instanceof NonRetryableException) {
throw $e;
}
// Log and rethrow for retry
\Log::warning('Payment attempt failed', [
'attempt' => $this->attempts(),
'error' => $e->getMessage(),
]);
throw $e;
}
}
public function failed(Throwable $throwable): void
{
parent::failed($throwable);
// Notify admin of payment failure
\Mail::to('[email protected]')->send(
new PaymentFailedNotification($throwable)
);
}
}