1. Go to this page and download the library: Download rasuvaeff/yii3-outbox library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
rasuvaeff / yii3-outbox example snippets
use DateTimeImmutable;
use Psr\Clock\ClockInterface;
use Rasuvaeff\Yii3Outbox\InMemoryStorage;
use Rasuvaeff\Yii3Outbox\Outbox;
$clock = new class implements ClockInterface {
public function now(): DateTimeImmutable { return new DateTimeImmutable(); }
};
$outbox = new Outbox(storage: $storage, clock: $clock);
$message = $outbox->record(
type: 'order.created',
payload: json_encode(['orderId' => 42]),
aggregateId: 'order-42',
);
$db->transaction(static function () use ($orders, $outbox, $order, $json): void {
$orders->insert($order);
$outbox->record(
type: 'order.created',
payload: $json,
aggregateId: $order->id,
);
});
use Rasuvaeff\Yii3Outbox\MessageIdGeneratorInterface;
// symfony/uid
final readonly class Uuid7IdGenerator implements MessageIdGeneratorInterface
{
public function generate(): string
{
return \Symfony\Component\Uid\Uuid::v7()->toRfc4122();
}
}
// ramsey/uuid — equally monotonic within the same millisecond
final readonly class RamseyUuid7IdGenerator implements MessageIdGeneratorInterface
{
public function generate(): string
{
return \Ramsey\Uuid\Uuid::uuid7()->toString();
}
}
$outbox = new Outbox(storage: $storage, clock: $clock, idGenerator: new Uuid7IdGenerator());
use Rasuvaeff\Yii3Outbox\StorageInterface;
use Rasuvaeff\Yii3Outbox\OutboxMessage;
final class DbStorage implements StorageInterface
{
public function save(OutboxMessage $message): void
{
// INSERT INTO outbox ... ON CONFLICT(id) DO UPDATE ...
// Must run on the caller's connection so it commits with the business write.
}
public function claim(array $types = [], int $limit = 1000): array
{
// Atomically: SELECT ids of status = 'pending' [AND type IN (:types)]
// LIMIT :limit FOR UPDATE SKIP LOCKED
// then UPDATE outbox SET status = 'processing', claimed_by = :worker
// WHERE id IN (...) — and return the claimed rows.
// Every claimed message must end up markPublished(), markFailed(),
// or save($msg->withStatus(Pending)); none may stay Processing.
}
public function findPending(array $types = [], int $limit = 1000): array
{
// SELECT * FROM outbox WHERE status = 'pending'
// [AND type IN (:types)] LIMIT :limit -- empty $types = all types
// Read-only: no atomicity, so two workers would both get the same rows.
// For retry support, also return status = 'pending' with attempts > 0
}
public function markPublished(OutboxMessage $message): void
{
// UPDATE outbox SET status = 'published' WHERE id = ?
}
public function markFailed(OutboxMessage $message): void
{
// UPDATE outbox SET status = 'failed' WHERE id = ?
}
public function getById(string $id): ?OutboxMessage
{
// SELECT * FROM outbox WHERE id = ?
}
}
use Rasuvaeff\Yii3Outbox\RetryAwareStorageInterface;
final class DbStorage implements RetryAwareStorageInterface
{
public function claimReady(
DateTimeImmutable $readyThreshold,
int $maxAttempts,
array $types = [],
int $limit = 1000,
): array {
// Same atomic claim as claim(), with one more condition:
// AND (attempts >= :maxAttempts
// OR last_attempt_at IS NULL
// OR last_attempt_at <= :readyThreshold)
}
// ... the rest of StorageInterface unchanged
}
use Rasuvaeff\Yii3Outbox\PublisherInterface;
use Rasuvaeff\Yii3Outbox\OutboxMessage;
use Rasuvaeff\Yii3Outbox\PublishException;
final class RabbitPublisher implements PublisherInterface
{
public function publish(OutboxMessage $message): void
{
try {
// publish to RabbitMQ, Kafka, etc.
} catch (\Throwable $e) {
throw new PublishException(
message: $e->getMessage(),
outboxMessage: $message,
previous: $e,
);
}
}
}
use Rasuvaeff\Yii3Outbox\Processor;
use Rasuvaeff\Yii3Outbox\RetryPolicy;
$processor = new Processor(
storage: $storage,
publisher: $publisher,
retryPolicy: new RetryPolicy(maxAttempts: 3, delaySeconds: 60),
clock: $clock,
batchSize: 100,
);
$result = $processor->process();
// $result->published — successfully published
// $result->failed — publish failures and messages that ran out of attempts
// $result->skipped — claimed but not yet ready for retry; always 0 against
// a RetryAwareStorageInterface, which never claims them
$policy = new RetryPolicy(maxAttempts: 3, delaySeconds: 60);
$policy->shouldRetry($message); // bool — attempts remaining?
$policy->isReadyForRetry($message, $now); // bool — delay elapsed?
$policy->readyThreshold($now); // DateTimeImmutable — the same question
// as a boundary a storage can filter on
use Rasuvaeff\Yii3Outbox\InMemoryStorage;
$storage = new InMemoryStorage();
$storage->save($message);
$pending = $storage->findPending();
$storage->count();
$storage->clear();
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.