-
Notifications
You must be signed in to change notification settings - Fork 2
Useful Implementation Patterns
mpyw edited this page Sep 29, 2023
·
5 revisions
<?php
declare(strict_types=1);
namespace App\Services\Batch;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Support\Facades\DB;
use Mpyw\LaravelDatabaseAdvisoryLock\Contracts\LockFailedException as DatabaseLockFailedException;
use Mpyw\LaravelDatabaseAdvisoryLock\Contracts\SessionLock;
use App\Services\Bank\Exceptions\LockFailedException;
class BatchExecutor
{
private readonly SessionLock $lock;
public function __construct(
private readonly ConnetcionInterface $db,
) {
try {
// Keep locking as long as the instance exists.
$this->lock = $this->db->forSession()->lockOrFail(self::class);
} catch (DatabaseLockFailedException $e) {
// If necessary, wrap exceptions thrown by the library with your own domain-level exceptions.
throw new LockFailedException($e->getMessage(), previous: $e);
}
}
public function __destruct()
{
// The lock is released automatically on SessionLock::__destruct(), but written here for clarity.
$this->lock->release();
}
public function runFoo(): void
{
/* ... */
}
public function runBar(): void
{
/* ... */
}
public function runBaz(): void
{
/* ... */
}
}
function runBatchExclusively(): void
{
$batch = new BatchExecutor(DB::connection());
// Start Critical Section
$batch->runFoo();
$batch->runBar();
$batch->runBaz();
// End Critical Section
}