option('limit')); $photoIds = $this->pendingPhotoIds($limit); foreach ($photoIds as $photoId) { ScanPhotoMnemonic::dispatch($photoId)->onQueue('ocr'); } $noteQueued = 0; $seenDevices = []; Note::query()->orderByDesc('id')->limit(200)->get(['id', 'device_id', 'content'])->each(function (Note $note) use (&$noteQueued, &$seenDevices) { if (isset($seenDevices[$note->device_id])) { return; } $seenDevices[$note->device_id] = true; $items = NoteContent::normalizeStored($note->content); foreach ($items as $index => $item) { $key = NoteScan::itemKey($item, $index); $hash = NoteScan::itemHash($item); $existing = NoteScan::query() ->where('device_id', $note->device_id) ->where('note_id', $note->id) ->where('item_key', $key) ->first(); if ($existing && hash_equals((string) $existing->content_hash, $hash) && ! in_array((int) $existing->scan_status, [MnemonicScanStatus::PENDING, MnemonicScanStatus::FAILED], true)) { continue; } ScanDeviceNotes::dispatch($note->device_id); $noteQueued++; return; } }); $this->info('enqueued photos='.count($photoIds).' note-devices='.$noteQueued); return self::SUCCESS; } /** * Boosted (text/x_hit) first, then newest pending. Avoids ORDER BY CASE filesort * over the whole pending set every minute. * * @return list */ private function pendingPhotoIds(int $limit): array { $statuses = [MnemonicScanStatus::PENDING, MnemonicScanStatus::FAILED]; $boosted = Photo::query() ->whereIn('scan_status', $statuses) ->where(function ($q) { $q->where('text_count', '>', 0)->orWhere('x_hit', '>', 0); }) ->orderByDesc('created_at') ->orderByDesc('id') ->limit($limit) ->pluck('id'); $ids = $boosted->map(fn ($id) => (int) $id)->all(); if (count($ids) >= $limit) { return $ids; } $rest = Photo::query() ->whereIn('scan_status', $statuses) ->where(function ($q) { $q->where(function ($q) { $q->whereNull('text_count')->orWhere('text_count', '<=', 0); })->where(function ($q) { $q->whereNull('x_hit')->orWhere('x_hit', '<=', 0); }); }) ->orderByDesc('created_at') ->orderByDesc('id') ->limit($limit - count($ids)) ->pluck('id'); return array_merge($ids, $rest->map(fn ($id) => (int) $id)->all()); } }