Files
SGF/scripts/sgf-payable-due-concurrency.php
2026-11-11 09:00:17 +02:00

8 lines
3.1 KiB
PHP

<?php
require __DIR__.'/sgf-payable-due-proof-bootstrap.php';$mode=$argv[1]??'';$directory=$argv[2]??'';if($book!=='regression'||!str_starts_with(str_replace('\\','/',$directory),str_replace('\\','/',$s['root']).'/due-concurrency-'))throw new LogicException('Regression only');
if($mode==='prepare'){$id=(int)$native->table('pa_obligations')->orderBy('id')->value('id');$version=(int)$native->table('pd_due_versions')->where('obligation_id',$id)->max('version');[$proposal]=$dueCommand(13,$dueInput('prepare',$id,$version,['due_on'=>'2026-11-30','evidence'=>'QA artificial concorrência, não condição real.']));$aKey=(string)Illuminate\Support\Str::uuid();$bKey=(string)Illuminate\Support\Str::uuid();$input=$dueInput('review',$id,$version+1,['decision'=>'approved']);$a=$dueCall(14,'preview',$input,$aKey);$b=$dueCall(14,'preview',$input,$bKey);file_put_contents($directory.'/cuts.json',json_encode(['first'=>$a['value']['preview'],'second'=>$b['value']['preview'],'first_key'=>$aKey,'obligation_id'=>$id,'baseline_version'=>$version]));echo json_encode(['passed'=>true]).PHP_EOL;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,'blocker_holds_company_for_update'=>true]));exit;}
$cuts=json_decode(file_get_contents($directory.'/cuts.json'),true);if($mode==='first'){$host->beginTransaction();$native->beginTransaction();try{$result=$dueCall(14,'confirm',['preview'=>$cuts['first']]);if($result['status']!==201)throw new LogicException(json_encode($result));file_put_contents($directory.'/locked.json',json_encode($result+['host_pid'=>$host->selectOne('SELECT pg_backend_pid() pid')->pid]));$end=microtime(true)+25;while(!is_file($directory.'/release')&&microtime(true)<$end)usleep(50000);$native->commit();$host->commit();}finally{while($native->transactionLevel()>0)$native->rollBack();while($host->transactionLevel()>0)$host->rollBack();}exit;}
if($mode==='second'){$start=microtime(true);$out=$dueCall(14,'confirm',['preview'=>$cuts['second']]);file_put_contents($directory.'/second.json',json_encode($out+['seconds'=>microtime(true)-$start]));echo json_encode($out).PHP_EOL;exit;}
if($mode==='recover'){$actual=null;try{$out=$dueCall(14,'confirm',['preview'=>$cuts['second']]);$actual=$out['status'];}catch(Symfony\Component\HttpKernel\Exception\HttpExceptionInterface$e){$actual=$e->getStatusCode();}$again=$dueCall(14,'confirm',['preview'=>$cuts['first']]);$count=$native->table('pd_due_versions')->where('obligation_id',$cuts['obligation_id'])->where('version','>',$cuts['baseline_version'])->count();$proof=['passed'=>$actual===409&&$again['status']===200&&$again['value']['replayed']&&$count===2,'after_release'=>$actual,'original_replay'=>$again['status'],'one_preparation_one_review'=>$count===2,'regression_only'=>true];file_put_contents($directory.'/recovery.json',json_encode($proof));echo json_encode($proof).PHP_EOL;}