TenantAtlas/app/Services/Onboarding/OnboardingLockService.php
2026-02-01 12:20:18 +01:00

90 lines
2.8 KiB
PHP

<?php
namespace App\Services\Onboarding;
use App\Models\OnboardingSession;
use App\Models\User;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;
class OnboardingLockService
{
public function acquire(OnboardingSession $session, User $user, int $ttlSeconds = 600): bool
{
return DB::transaction(function () use ($session, $user, $ttlSeconds): bool {
$session = OnboardingSession::query()->lockForUpdate()->findOrFail($session->getKey());
if ($this->isLockedByOther($session, $user)) {
return false;
}
$session->forceFill([
'locked_by_user_id' => $user->getKey(),
'locked_until' => Carbon::now()->addSeconds($ttlSeconds),
])->save();
return true;
});
}
public function renew(OnboardingSession $session, User $user, int $ttlSeconds = 600): bool
{
return DB::transaction(function () use ($session, $user, $ttlSeconds): bool {
$session = OnboardingSession::query()->lockForUpdate()->findOrFail($session->getKey());
if ((int) $session->locked_by_user_id !== (int) $user->getKey()) {
return false;
}
$session->forceFill([
'locked_until' => Carbon::now()->addSeconds($ttlSeconds),
])->save();
return true;
});
}
public function release(OnboardingSession $session, User $user): bool
{
return DB::transaction(function () use ($session, $user): bool {
$session = OnboardingSession::query()->lockForUpdate()->findOrFail($session->getKey());
if ((int) $session->locked_by_user_id !== (int) $user->getKey()) {
return false;
}
$session->forceFill([
'locked_by_user_id' => null,
'locked_until' => null,
])->save();
return true;
});
}
public function takeover(OnboardingSession $session, User $newOwner, int $ttlSeconds = 600): void
{
DB::transaction(function () use ($session, $newOwner, $ttlSeconds): void {
$session = OnboardingSession::query()->lockForUpdate()->findOrFail($session->getKey());
$session->forceFill([
'locked_by_user_id' => $newOwner->getKey(),
'locked_until' => Carbon::now()->addSeconds($ttlSeconds),
])->save();
});
}
private function isLockedByOther(OnboardingSession $session, User $user): bool
{
if ($session->locked_by_user_id === null || $session->locked_until === null) {
return false;
}
if ($session->locked_until->isPast()) {
return false;
}
return (int) $session->locked_by_user_id !== (int) $user->getKey();
}
}