feat: add durable ASR-to-patient extraction and guarded review

This commit is contained in:
2026-10-08 15:08:42 +08:00
parent 8bb4bd07ae
commit 13948f5982
34 changed files with 2377 additions and 56 deletions
+20 -11
View File
@@ -17,20 +17,29 @@ namespace app\common\service\followupaudio {
}
namespace {
require dirname(__DIR__) . '/vendor/autoload.php';
$app = new \think\App(dirname(__DIR__) . '/');
$app->initialize();
$app->config->set([
'default' => 'mysql', 'connections' => ['mysql' => [
'type' => 'mysql', 'hostname' => '127.0.0.1', 'hostport' => 23316,
'database' => 'followup_audio_test', 'username' => 'root', 'password' => 'followup_audio_isolated_test',
'charset' => 'utf8mb4', 'prefix' => 'far_', 'debug' => false,
]],
], 'database');
require dirname(__DIR__) . '/vendor/topthink/framework/src/helper.php';
$port = (int) getenv('FOLLOWUP_AUDIO_TEST_MYSQL_PORT');
if ($port <= 0 || $port === 3306 || getenv('FOLLOWUP_AUDIO_TEST_ALLOW_DISPOSABLE') !== '1') {
throw new \RuntimeException('Explicit local disposable MySQL port and acknowledgement required');
}
$database = 'fa_upload_' . bin2hex(random_bytes(6));
$password = (string) getenv('FOLLOWUP_AUDIO_TEST_MYSQL_PASSWORD');
$pdo = new \PDO("mysql:host=127.0.0.1;port={$port};charset=utf8mb4", 'root', $password, [\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION]);
$pdo->exec("CREATE DATABASE `{$database}` CHARACTER SET utf8mb4");
$app = new \think\App(); // No initialize(), .env or deployment database configuration.
$config = new \think\Config(); \think\Container::getInstance()->instance('config', $config);
$manager = new \think\DbManager();
$manager->setConfig(['default' => 'mysql', 'connections' => ['mysql' => [
'type' => 'mysql', 'hostname' => '127.0.0.1', 'hostport' => $port,
'database' => $database, 'username' => 'root', 'password' => $password,
'charset' => 'utf8mb4', 'prefix' => 'far_', 'debug' => false,
]]]);
\think\Container::getInstance()->instance('think\DbManager', $manager);
set_exception_handler(static function (\Throwable $e): void { fwrite(STDERR, get_class($e) . ': ' . $e->getMessage() . PHP_EOL . $e->getTraceAsString() . PHP_EOL); exit(1); });
$dir = sys_get_temp_dir() . '/followup-upload-test-' . bin2hex(random_bytes(8));
mkdir($dir, 0700, true);
$app->config->set(['private_dir' => $dir . '/private', 'max_bytes' => 524288000,
'max_seconds' => 3600, 'chunk_bytes' => 65536, 'ffprobe' => '/opt/homebrew/bin/ffprobe'], 'followup_audio');
'max_seconds' => 3600, 'chunk_bytes' => 65536, 'ffprobe' => 'ffprobe'], 'followup_audio');
$db = \think\facade\Db::class;
$db::execute('CREATE TABLE IF NOT EXISTS far_followup_audio_upload (
id VARCHAR(64) PRIMARY KEY, diagnosis_id BIGINT NOT NULL, actor_id BIGINT NOT NULL,
@@ -108,7 +117,7 @@ namespace {
$ok($upload::session($id)['status'] === 'deleted', 'missing directory after DB rollback can be reconciled');
echo "Followup audio private upload: {$checks} checks passed\n";
} finally {
foreach ($ids as $id) { $db::name('followup_audio_upload')->where('id', $id)->delete(); }
$pdo->exec('DROP DATABASE `' . $database . '`');
$files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST);
foreach ($files as $f) { $f->isDir() && !$f->isLink() ? rmdir($f->getPathname()) : unlink($f->getPathname()); }
rmdir($dir);