registry->steps($recipe); $ver = $this->registry->version($recipe); DB::transaction(function () use ($tenantId, $recipe, $steps, $ver, $logger) { $runId = DB::table('tenant_bootstrap_runs')->insertGetId([ 'tenant_id' => $tenantId, 'recipe' => $recipe, 'recipe_version' => $ver, 'status' => 'RUNNING', 'steps' => json_encode([]), 'log' => json_encode([]), 'created_at' => now(), 'updated_at' => now(), ]); $done = []; try { foreach ($steps as $step) { /** @var \App\Services\TenantBootstrap\Contracts\TenantBootstrapStep $step */ $logger->info('start step', ['key' => $step->key()]); $step->run($tenantId); $done[] = $step->key(); $logger->info('end step', ['key' => $step->key()]); DB::table('tenant_bootstrap_runs')->where('id', $runId)->update([ 'steps' => json_encode($done), 'log' => json_encode($logger->dump(), JSON_UNESCAPED_UNICODE), 'updated_at' => now(), ]); } DB::table('tenant_bootstrap_runs')->where('id', $runId)->update([ 'status' => 'SUCCESS', 'log' => json_encode($logger->dump(), JSON_UNESCAPED_UNICODE), 'updated_at' => now(), ]); } catch (\Throwable $e) { $logger->error('step failed', ['exception' => $e->getMessage()]); DB::table('tenant_bootstrap_runs')->where('id', $runId)->update([ 'status' => 'FAILED', 'log' => json_encode($logger->dump(), JSON_UNESCAPED_UNICODE), 'updated_at' => now(), ]); throw $e; } }); } }