115 lines
4.0 KiB
PHP
115 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace App\Temporal\OrderFulfillment;
|
|
|
|
use Carbon\CarbonInterval;
|
|
use Temporal\Activity\ActivityOptions;
|
|
use Temporal\Common\RetryOptions;
|
|
use Temporal\Workflow;
|
|
|
|
class OrderFulfillmentWorkflow implements OrderFulfillmentWorkflowInterface
|
|
{
|
|
private string $status = 'pending';
|
|
private ?string $trackingNumber = null;
|
|
private bool $shippingConfirmed = false;
|
|
private int $orderId = 0;
|
|
private int $retryCount = 0;
|
|
private int $rateLimitHits = 0;
|
|
|
|
/** @var mixed Activity stub - untyped due to PHP SDK limitation */
|
|
private $activityStub;
|
|
|
|
public function __construct()
|
|
{
|
|
$this->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,
|
|
];
|
|
}
|
|
}
|