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

13 lines
2.9 KiB
PHP

<?php
use App\Modules\Finance\CashWorkspace;
require __DIR__.'/sgf-cash-proof-bootstrap.php';$dir=$s['root'].'/cash-concurrency';if(!is_dir($dir))mkdir($dir,0700,true);$file=$dir.'/progress.json';$mode=$argv[1]??'';
if($mode==='prepare'){
if(is_file($file))throw new LogicException('Reuse existing preparation');[$open]=$cashCommand('finance_prepare','prepare','open',['date'=>'2026-11-10','label'=>'Caixa QA concorrência','opening'=>'0.00','evidence'=>'Abertura zero para prova concorrente de Caixa.']);$cashCommand('finance_review','review','open',['decision'=>'approved'],$open['id']);[$receipt]=$cashCommand('finance_prepare','prepare','receipt',['date'=>'2026-11-10','receipt_id'=>$cashBinding['receipt_id'],'medium'=>'cash','evidence'=>'Classificação QA de numerário para prova concorrente.']);$cuts=[];foreach([1,2] as $i)$cuts[$i]=$cashPreview('finance_review','review','receipt',['decision'=>'approved'],$receipt['id'])['preview'];file_put_contents($file,json_encode(['cuts'=>$cuts,'proposal_id'=>$receipt['id'],'events_before'=>$host->table('cash_events')->count()]));
}elseif($mode==='first'){
$p=json_decode(file_get_contents($file),true);$actor=$selectCash('finance_review');$host->beginTransaction();try{$result=app(CashWorkspace::class)->confirm($actor,$p['cuts'][1]);file_put_contents($dir.'/locked','host company and current cash authority locked');$end=microtime(true)+20;while(!is_file($dir.'/release')&&microtime(true)<$end)usleep(50000);if(!is_file($dir.'/release'))throw new LogicException('Release missing');$host->commit();file_put_contents($dir.'/first.json',json_encode($result));}finally{while($host->transactionLevel()>0)$host->rollBack();}
}elseif($mode==='second'){
$p=json_decode(file_get_contents($file),true);$selectCash('finance_review');request()->request->replace(['preview'=>$p['cuts'][2]]);$start=microtime(true);$r=app(App\Modules\Finance\Http\CashController::class)->confirm(request(),app(CashWorkspace::class));file_put_contents($dir.'/second.json',json_encode(['status'=>$r->getStatusCode(),'elapsed_seconds'=>microtime(true)-$start]));
}elseif($mode==='recover'){
$p=json_decode(file_get_contents($file),true);$actor=$selectCash('finance_review');$w=app(CashWorkspace::class);$reject(fn()=>$w->confirm($actor,$p['cuts'][2]),409,'second cash confirmation refuses stale version after release');$first=$w->confirm($actor,$p['cuts'][1]);$ok($first['replayed']&&$host->table('cash_events')->count()===$p['events_before']+1,'one cash movement and original result recovered');file_put_contents($dir.'/result.json',json_encode(['passed'=>true,'second_during_lock'=>json_decode(file_get_contents($dir.'/second.json'),true),'after_release_status'=>409,'one_cash_movement'=>true,'first_key_replayed'=>true,'regression_only'=>true],JSON_PRETTY_PRINT));
}else throw new LogicException('Unknown phase');echo json_encode(['passed'=>true,'phase'=>$mode,'proof'=>$dir.'/result.json']).PHP_EOL;