make(\Illuminate\Contracts\Console\Kernel::class)->bootstrap(); \App\Shared\Testing\TestingDatabaseGuard::assertSafe(); $fixture = json_decode(file_get_contents('C:/laragon/data/sgf-tempo/secrets/browser-fixture.json'), true, 32, JSON_THROW_ON_ERROR); $base = ['operation' => 'b1.confirm', 'actor' => $fixture['manager_id'], 'tenant' => $fixture['tenant'], 'company' => $fixture['company'], 'unit' => $fixture['unit'], 'version' => 1]; app(\App\Shared\Context\CompanyContext::class)->selectFor($base['actor'], $base['tenant'], $base['company'], $base['unit']); $workflow = app(\App\Modules\Services\ServiceWorkflow::class); $save = fn ($area, $data) => $workflow->save($area, null, $base['actor'], $data, (string) Str::uuid())['id']; $client = $save('clients', ['name' => 'Cliente concorrência B1 sintético']); $service = $save('services', ['name' => 'Serviço concorrência B1 sintético']); $source = $save('service_drafts', ['client_id' => $client, 'lines' => [['service_id' => $service, 'quantity' => '1', 'unit_price' => '12.50']]]); $reports = []; foreach (['same_key', 'different_keys'] as $mode) { $draft = $save('billing_drafts', ['source_id' => $source]); $key = (string) Str::uuid(); $input = $base + ['id' => $draft, 'key' => $key]; $first = new Process([PHP_BINARY, 'scripts/a-concurrency-worker.php', '--env=testing'], base_path(), null, json_encode($input + ['hold' => true])); $secondInput = $input; if ($mode === 'different_keys') { $secondInput['key'] = (string) Str::uuid(); } $second = new Process([PHP_BINARY, 'scripts/a-concurrency-worker.php', '--env=testing'], base_path(), null, json_encode($secondInput)); $before = DB::table('a_events')->where('type', 'b1.billing_draft.confirmed_internal')->count(); $first->start(); if (! $first->waitUntil(fn ($type, $buffer) => str_contains($buffer, 'LOCK_ACQUIRED'))) { throw new RuntimeException('Concurrent lock not established.'); } $second->start(); $first->wait(); $second->wait(); $results = []; foreach ([$first, $second] as $process) { if (! $process->isSuccessful()) { throw new RuntimeException('Synthetic worker failed.'); } $lines = array_values(array_filter(explode("\n", trim($process->getOutput())), fn ($line) => str_starts_with($line, '{'))); $results[] = json_decode(end($lines), true, 32, JSON_THROW_ON_ERROR); } if ($results[0]['status'] !== 200 || $results[1]['status'] !== 200 || $results[0]['result']['id'] !== $results[1]['result']['id'] || ! $results[1]['result']['replayed'] || DB::table('a_events')->where('type', 'b1.billing_draft.confirmed_internal')->count() !== $before + 1 || DB::table('b_internal_confirmations')->where('billing_draft_id', $draft)->count() !== 1) { throw new RuntimeException('Confirmation deduplication failed.'); } $reports[$mode] = ['parallel_processes' => true, 'company_lock_overlap' => true, 'same_confirmation' => true, 'new_confirmations' => 1, 'new_events' => 1, 'second_replayed' => true]; } file_put_contents(base_path('docs/proofs/b1-concurrency.json'), json_encode(['database' => 'sgf_tempo_test', 'results' => $reports], JSON_PRETTY_PRINT|JSON_THROW_ON_ERROR)); echo "B1 concurrent confirmations passed with identical and different keys: one confirmation/event per draft.\n";