activityStub = Workflow::newActivityStub( OrderActivityInterface::class, ActivityOptions::new() ->withStartToCloseTimeout(CarbonInterval::minutes(5)) ->withRetryOptions( RetryOptions::new() ->withMaximumAttempts(3) ) ); } public function processOrder(int $orderId, array $simulationConfig = []): \Generator { $this->orderId = $orderId; $saga = new Workflow\Saga(); try { // Step 1: Validate the order $this->status = 'validating'; yield $this->activityStub->validateOrder($orderId, $simulationConfig); // Step 2: Check inventory availability $this->status = 'checking_inventory'; yield $this->activityStub->checkInventory($orderId, $simulationConfig); // Step 3: Process payment $this->status = 'processing_payment'; $paymentId = yield $this->activityStub->processPayment($orderId, $simulationConfig); // Register compensation: refund payment if later steps fail $saga->addCompensation(fn() => yield $this->activityStub->refundPayment($orderId, $paymentId)); // Step 4: Update inventory (decrement stock) $this->status = 'updating_inventory'; yield $this->activityStub->updateInventory($orderId, $simulationConfig); // Register compensation: restore inventory if later steps fail $saga->addCompensation(fn() => yield $this->activityStub->restoreInventory($orderId)); // Step 5: Notify warehouse $this->status = 'notifying_warehouse'; yield $this->activityStub->notifyWarehouse($orderId, $simulationConfig); // Register compensation: cancel warehouse notification if later steps fail $saga->addCompensation(fn() => yield $this->activityStub->cancelWarehouseNotification($orderId)); // Step 6: Wait for shipping confirmation signal $this->status = 'awaiting_shipment'; yield Workflow::await(fn() => $this->shippingConfirmed); // Step 7: Send tracking information $this->status = 'sending_tracking'; yield $this->activityStub->sendTrackingInfo($orderId, $this->trackingNumber, $simulationConfig); // All steps completed successfully $this->status = 'completed'; return [ 'success' => true, 'orderId' => $orderId, 'trackingNumber' => $this->trackingNumber, 'status' => $this->status, 'retryCount' => $this->retryCount, 'rateLimitHits' => $this->rateLimitHits, ]; } catch (\Throwable $e) { yield $saga->compensate(); $this->status = 'failed'; throw $e; } } public function confirmShipping(string $trackingNumber): void { $this->trackingNumber = $trackingNumber; $this->shippingConfirmed = true; } public function getOrderStatus(): array { return [ 'status' => $this->status, 'orderId' => $this->orderId, 'trackingNumber' => $this->trackingNumber, 'shippingConfirmed' => $this->shippingConfirmed, 'retryCount' => $this->retryCount, 'rateLimitHits' => $this->rateLimitHits, ]; } }