$context */ public function __construct( public int $tenantId, public int $userId, ?OperationRun $operationRun = null, public array $context = [], ) { $this->operationRun = $operationRun; } public function handle( OperationRunService $runs, TargetScopeConcurrencyLimiter $limiter, PolicySyncService $syncService, ): void { if (! $this->operationRun instanceof OperationRun) { throw new RuntimeException('OperationRun is required for tenant sync worker.'); } $this->operationRun->refresh(); if ($this->operationRun->status === 'completed') { return; } $lock = null; try { $tenant = Tenant::query()->whereKey($this->tenantId)->first(); if (! $tenant instanceof Tenant) { $runs->incrementSummaryCounts($this->operationRun, [ 'processed' => 1, 'failed' => 1, ]); $runs->appendFailures($this->operationRun, [[ 'code' => 'tenant.not_found', 'message' => 'Tenant '.$this->tenantId.' not found.', ]]); $runs->maybeCompleteBulkRun($this->operationRun); return; } $lock = $limiter->acquireSlot($tenant->getKey(), [ 'entra_tenant_id' => (string) ($tenant->tenant_id ?? $tenant->external_id), ]); if (! $lock) { $delay = (int) config('tenantpilot.bulk_operations.poll_interval_seconds', 3); $this->release(max(1, $delay)); return; } if (! $tenant->isActive()) { $runs->incrementSummaryCounts($this->operationRun, [ 'processed' => 1, 'skipped' => 1, ]); $runs->maybeCompleteBulkRun($this->operationRun); return; } $user = User::query()->whereKey($this->userId)->first(); if (! $user instanceof User || ! $user->canSyncTenant($tenant)) { $runs->incrementSummaryCounts($this->operationRun, [ 'processed' => 1, 'skipped' => 1, ]); $runs->maybeCompleteBulkRun($this->operationRun); return; } $supported = config('tenantpilot.supported_policy_types', []); $syncService->syncPolicies($tenant, $supported); $runs->incrementSummaryCounts($this->operationRun, [ 'processed' => 1, 'succeeded' => 1, ]); $runs->maybeCompleteBulkRun($this->operationRun); } catch (Throwable $e) { $runs->incrementSummaryCounts($this->operationRun, [ 'processed' => 1, 'failed' => 1, ]); $runs->appendFailures($this->operationRun, [[ 'code' => 'tenant.sync_failed', 'message' => $e->getMessage(), ]]); $runs->maybeCompleteBulkRun($this->operationRun); throw $e; } finally { $lock?->release(); } } }