param( [string]$DatabaseContainer = 'supabase_db_d3ro-voice' ) $ErrorActionPreference = 'Stop' $userId = '20000000-0000-4000-8000-000000000099' $runId = [guid]::NewGuid().ToString('N') $firstTransactionId = "race-transaction-first-$runId" $secondTransactionId = "race-transaction-second-$runId" function Invoke-D3roSql { param([Parameter(Mandatory)][string]$Sql) $output = $Sql | docker exec -i $DatabaseContainer psql -v ON_ERROR_STOP=1 -U postgres -d postgres -t -A if ($LASTEXITCODE -ne 0) { throw 'D3RO PostgreSQL command failed' } return ($output -join "`n").Trim() } $setup = @" DELETE FROM auth.users WHERE id = '$userId'; INSERT INTO auth.users ( id, aud, role, email, encrypted_password, email_confirmed_at, raw_app_meta_data, raw_user_meta_data, created_at, updated_at ) VALUES ( '$userId', 'authenticated', 'authenticated', 'reward-race@example.invalid', crypt('fixture-password', gen_salt('bf')), now(), '{"provider":"email","providers":["email"]}'::jsonb, '{}'::jsonb, now(), now() ); UPDATE public.subscriptions SET tier = 'free', status = 'active', overage_credits = 0 WHERE user_id = '$userId'; "@ try { [void](Invoke-D3roSql -Sql $setup) $firstSql = @" BEGIN; SELECT public.grant_verified_ad_reward( '$userId', 'admob:race', 'rewarded_video_quota', '5224354917', '$firstTransactionId', 50 ); SELECT pg_sleep(2); COMMIT; "@ $secondSql = @" SELECT public.grant_verified_ad_reward( '$userId', 'admob:race', 'rewarded_video_quota', '5224354917', '$secondTransactionId', 50 ); "@ $first = Start-Job -ScriptBlock { param($Container, $Sql) $Sql | docker exec -i $Container psql -v ON_ERROR_STOP=1 -U postgres -d postgres -t -A if ($LASTEXITCODE -ne 0) { throw 'first reward connection failed' } } -ArgumentList $DatabaseContainer, $firstSql Start-Sleep -Milliseconds 200 $second = Start-Job -ScriptBlock { param($Container, $Sql) $Sql | docker exec -i $Container psql -v ON_ERROR_STOP=1 -U postgres -d postgres -t -A if ($LASTEXITCODE -ne 0) { throw 'second reward connection failed' } } -ArgumentList $DatabaseContainer, $secondSql $firstOutput = (Receive-Job -Job $first -Wait -AutoRemoveJob | Out-String) $secondOutput = (Receive-Job -Job $second -Wait -AutoRemoveJob | Out-String) if ($firstOutput -notmatch '"granted": true') { throw "first callback was not granted: $firstOutput" } if ($secondOutput -notmatch '"reason": "cooldown"') { throw "second callback was not serialized into cooldown: $secondOutput" } $verification = Invoke-D3roSql -Sql @" SELECT (SELECT count(*) FROM public.ad_reward_claims WHERE user_id = '$userId')::text || ':' || (SELECT overage_credits FROM public.subscriptions WHERE user_id = '$userId')::text; "@ if ($verification -ne '1:50') { throw "reward race changed more than one claim/balance: $verification" } Write-Output 'mobile_reward_race_ok claims=1 credits=50 second=cooldown' } finally { [void](Invoke-D3roSql -Sql @" DELETE FROM public.ad_reward_receipts WHERE transaction_id IN ('$firstTransactionId', '$secondTransactionId'); DELETE FROM auth.users WHERE id = '$userId'; "@) }