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(); } }