Skip to content

Useful Implementation Patterns

mpyw edited this page Sep 29, 2023 · 5 revisions

Exclusive Mutator Pattern

<?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 {
            $this->lock = $this->db->forSession()->lockOrFail(self::class);
        } catch (DatabaseLockFailedException $e) {
            throw new LockFailedException($e->getMessage(), previous: $e);
        }
    }

    public function __destruct()
    {
        $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
}
Clone this wiki locally