Files
SGF/scripts/sgf-assets-concurrency.php
2026-11-11 15:04:01 +02:00

9 lines
3.0 KiB
PHP

<?php
require __DIR__.'/sgf-assets-proof-bootstrap.php';$mode=$argv[1]??'';$directory=$argv[2]??'';if($book!=='regression'||!str_starts_with(str_replace('\\','/',$directory),str_replace('\\','/',$s['root']).'/assets-concurrency-'))throw new LogicException('Regression only');
$http=function($token)use($faCall){try{return$faCall(16,'confirm',['preview'=>$token]);}catch(Symfony\Component\HttpKernel\Exception\HttpExceptionInterface$e){return['status'=>$e->getStatusCode()];}};
if($mode==='prepare'){$key=(string)Str::uuid();$a=['operation'=>'establish','code'=>'QA-CONCURRENT-'.strtoupper(substr($key,0,8)),'description'=>'Activo artificial de concurrência sem lançamento','origin_reference'=>'QA-CONCURRENT-OPEN-'.strtoupper(substr($key,0,8)),'cost'=>'1200.00','residual'=>'0.00','available_on'=>'2026-10-01','location'=>'QA-SALA-A','custodian'=>'QA-CUSTODIA-A','evidence'=>'Conferência sintética simultânea do mesmo cadastro.'];$faCommand(15,$faInput('asset',$key,0,$a));$first=$faCall(16,'preview',$faInput('asset',$key,1,['decision'=>'approved'],'review'))['value']['preview'];$second=$faCall(16,'preview',$faInput('asset',$key,1,['decision'=>'refused'],'review'))['value']['preview'];file_put_contents($directory.'/cuts-private.json',json_encode(['first'=>$first,'second'=>$second,'record_key'=>$key]));exit;}
if($mode==='inspect'){$pid=json_decode(file_get_contents($directory.'/locked.json'),true)['host_pid'];$rows=$host->select('SELECT pid,wait_event_type,wait_event,pg_blocking_pids(pid) blockers FROM pg_stat_activity WHERE ? = ANY(pg_blocking_pids(pid))',[$pid]);file_put_contents($directory.'/blocking.json',json_encode(['blocker_host_pid'=>$pid,'waiters'=>$rows,'company_for_update'=>true]));exit;}$cuts=json_decode(file_get_contents($directory.'/cuts-private.json'),true);
if($mode==='first'){$host->beginTransaction();try{$out=$http($cuts['first']);if($out['status']!==200)throw new LogicException('First review failed');file_put_contents($directory.'/locked.json',json_encode(['host_pid'=>$host->selectOne('SELECT pg_backend_pid() pid')->pid]));$end=microtime(true)+25;while(!is_file($directory.'/release')&&microtime(true)<$end)usleep(50000);$host->commit();}finally{while($host->transactionLevel()>0)$host->rollBack();}exit;}
if($mode==='second'){$start=microtime(true);$out=$http($cuts['second']);file_put_contents($directory.'/second.json',json_encode(['status'=>$out['status'],'seconds'=>microtime(true)-$start]));exit;}
if($mode==='recover'){$second=$http($cuts['second']);$replay=$http($cuts['first']);$versions=$host->table('fa_versions')->where('record_key',$cuts['record_key'])->count();$commands=$host->table('fa_commands')->whereRaw("input->>'record_key'=?",[$cuts['record_key']])->count();$out=['passed'=>$second['status']===409&&$replay['status']===200&&$replay['value']['replayed']&&$versions===2&&$commands===2,'after_release'=>$second['status'],'original_replay'=>$replay['status'],'versions'=>$versions,'receipts'=>$commands,'regression_only'=>true];file_put_contents($directory.'/recovery.json',json_encode($out));echo json_encode($out).PHP_EOL;}