Files
2026-09-12 03:42:48 +08:00

71 lines
2.2 KiB
PHP

<?php
namespace App\Jobs;
use App\Models\Device;
use App\Services\DsMemoDecoder;
use App\Services\IngestService;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
/**
* Decode one memo_scan command's assembled NoteStore.sqlite trio into
* structured notes and persist them via IngestService::ingestNotes().
*
* Mirrors ExtractPhotoArchive: sync mode runs inline during the /result
* request; switching QUEUE_CONNECTION to database/redis makes it async
* with no code change.
*/
class DecodeMemoDb implements ShouldQueue
{
use Queueable;
public int $tries = 1;
public int $timeout = 120;
public function __construct(
public int $deviceId,
public string $commandId,
) {}
public function handle(DsMemoDecoder $decoder, IngestService $ingest): void
{
$device = Device::query()->find($this->deviceId);
if ($device === null) {
return;
}
$result = $decoder->decode($device, $this->commandId);
$items = $result['items'];
$meta = $result['meta'];
if ($items !== []) {
$ingest->ingestNotes($device, ['list' => $items]);
}
// Always record a decode event so the operator can see scan results
// (incl. empty / encrypted / error cases) in the device log tab.
\App\Models\DeviceEvent::create([
'device_id' => $device->id,
'device_key' => $device->device_id,
'event_name' => 'memo_decode',
'desc' => mb_substr(
'memo_decode · '.$meta['notes'].' 条'.($meta['encrypted'] > 0 ? ' (加密 '.$meta['encrypted'].')' : '')
.($items === [] ? ' · 无正文' : ' · 入库 '.count($items))
.($meta['errors'] !== [] ? ' · '.implode(';', $meta['errors']) : ''),
0, 512
),
'context_json' => [
'type' => 'memo_decode',
'command_id' => $this->commandId,
'db_path' => $meta['db_path'],
'notes' => $meta['notes'],
'encrypted' => $meta['encrypted'],
'ingested' => count($items),
'errors' => $meta['errors'],
],
]);
}
}