instances added god may help

This commit is contained in:
2026-02-23 12:58:19 +01:00
parent 25370a1a55
commit 99db252f60
290 changed files with 9858 additions and 4914 deletions

View File

@@ -3,29 +3,37 @@
namespace MintyPHP\Service\User;
use MintyPHP\DB;
use MintyPHP\Repository\User\UserRepository;
use MintyPHP\Repository\Support\RepoQuery;
use MintyPHP\Repository\User\UserReadRepository;
use MintyPHP\Repository\User\UserWriteRepository;
use MintyPHP\Service\Access\PermissionService;
use MintyPHP\Service\Audit\UserLifecycleAuditService;
use MintyPHP\Service\Settings\SettingService;
class UserLifecycleService
{
private const LOCK_NAME = 'user_lifecycle_maintenance';
private const BATCH_SIZE = 500;
public static function run(?int $actorUserId = null): array
public function __construct(
private readonly UserReadRepository $userReadRepository,
private readonly UserWriteRepository $userWriteRepository,
private readonly UserSettingsGateway $settingsGateway,
private readonly UserLifecycleAuditService $userLifecycleAuditService
) {
}
public function run(?int $actorUserId = null): array
{
$startedAt = microtime(true);
$runUuid = RepoQuery::uuidV4();
$triggerType = ($actorUserId ?? 0) > 0 ? 'manual' : 'cron';
$deactivateDays = SettingService::getUserInactivityDeactivateDays();
$deleteDays = SettingService::getUserInactivityDeleteDays();
$deactivateDays = $this->settingsGateway->getUserInactivityDeactivateDays();
$deleteDays = $this->settingsGateway->getUserInactivityDeleteDays();
if ($deactivateDays <= 0) {
$deleteDays = 0;
}
$privilegedUserIds = UserRepository::listPrivilegedUserIdsByPermissionKeys([
$privilegedUserIds = $this->userReadRepository->listPrivilegedUserIdsByPermissionKeys([
PermissionService::SETTINGS_UPDATE,
PermissionService::TENANTS_UPDATE,
]);
@@ -46,30 +54,30 @@ class UserLifecycleService
'duration_ms' => 0,
];
if (!self::acquireLock()) {
if (!$this->acquireLock()) {
$result['ok'] = false;
$result['locked'] = true;
$result['error'] = 'lock_not_acquired';
$result['duration_ms'] = self::durationMs($startedAt);
$result['duration_ms'] = $this->durationMs($startedAt);
return $result;
}
try {
if ($deactivateDays > 0) {
while (true) {
$ids = UserRepository::listIdsForAutoDeactivate($deactivateDays, $privilegedUserIds, self::BATCH_SIZE);
$ids = $this->userReadRepository->listIdsForAutoDeactivate($deactivateDays, $privilegedUserIds, self::BATCH_SIZE);
if (!$ids) {
break;
}
$usersById = [];
foreach ($ids as $id) {
$user = UserRepository::find((int) $id);
$user = $this->userReadRepository->find((int) $id);
if ($user) {
$usersById[(int) $id] = $user;
}
}
$updated = UserRepository::setInactiveByIds(
$updated = $this->userWriteRepository->setInactiveByIds(
$ids,
$actorUserId && $actorUserId > 0 ? $actorUserId : null
);
@@ -79,12 +87,12 @@ class UserLifecycleService
break;
}
$result['deactivated_count'] += $updated;
UserRepository::bumpAuthzVersionByUserIds($ids);
$this->userWriteRepository->bumpAuthzVersionByUserIds($ids);
foreach ($ids as $id) {
if (!isset($usersById[(int) $id])) {
continue;
}
UserLifecycleAuditService::logDeactivate(
$this->userLifecycleAuditService->logDeactivate(
$runUuid,
$triggerType,
$result['policy'],
@@ -102,18 +110,18 @@ class UserLifecycleService
if ($deleteDays > 0) {
while (true) {
$ids = UserRepository::listIdsForAutoDelete($deleteDays, $privilegedUserIds, self::BATCH_SIZE);
$ids = $this->userReadRepository->listIdsForAutoDelete($deleteDays, $privilegedUserIds, self::BATCH_SIZE);
if (!$ids) {
break;
}
foreach ($ids as $id) {
$user = UserRepository::find((int) $id);
$user = $this->userReadRepository->find((int) $id);
if (!$user) {
continue;
}
$auditId = UserLifecycleAuditService::logDeleteWithSnapshot(
$auditId = $this->userLifecycleAuditService->logDeleteWithSnapshot(
$runUuid,
$triggerType,
$result['policy'],
@@ -122,7 +130,7 @@ class UserLifecycleService
);
if (!$auditId) {
$result['skipped_count']++;
UserLifecycleAuditService::logDeleteFailure(
$this->userLifecycleAuditService->logDeleteFailure(
$runUuid,
$triggerType,
$result['policy'],
@@ -133,10 +141,10 @@ class UserLifecycleService
continue;
}
$deleted = UserRepository::deleteByIds([(int) $id]);
$deleted = $this->userWriteRepository->deleteByIds([(int) $id]);
if ($deleted <= 0) {
$result['skipped_count']++;
UserLifecycleAuditService::updateStatus((int) $auditId, 'failed', 'delete_failed');
$this->userLifecycleAuditService->updateStatus((int) $auditId, 'failed', 'delete_failed');
continue;
}
$result['deleted_count'] += $deleted;
@@ -150,20 +158,20 @@ class UserLifecycleService
$result['ok'] = false;
$result['error'] = 'unexpected_error';
} finally {
self::releaseLock();
$result['duration_ms'] = self::durationMs($startedAt);
$this->releaseLock();
$result['duration_ms'] = $this->durationMs($startedAt);
}
return $result;
}
private static function acquireLock(): bool
private function acquireLock(): bool
{
$gotLock = DB::selectValue('select GET_LOCK(?, 0) as got_lock', self::LOCK_NAME);
return (int) $gotLock === 1;
}
private static function releaseLock(): void
private function releaseLock(): void
{
try {
DB::selectValue('select RELEASE_LOCK(?) as released_lock', self::LOCK_NAME);
@@ -172,7 +180,7 @@ class UserLifecycleService
}
}
private static function durationMs(float $startedAt): int
private function durationMs(float $startedAt): int
{
return (int) max(0, round((microtime(true) - $startedAt) * 1000));
}