Change слит PR #29; спеки обновлены (subject'ы files.tabular_uploaded, files.img_uploaded, files.tabular_parsed). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012vJkmBGKKqMoEMzvsXG3y2
39 lines
3.9 KiB
Markdown
39 lines
3.9 KiB
Markdown
## MODIFIED Requirements
|
||
|
||
### Requirement: Подтверждение запроса до обработки
|
||
Сервис SHALL быть подписан на `files.tabular_uploaded` в queue group `tabular-parser`. Получив запрос, проходящий
|
||
`recognition-request.schema.json`, сервис SHALL до чтения файла из S3 опубликовать в `files.tabular_parsed` конверт
|
||
`status = processing` с `job_id`, `file_id`, `service {name: "tabular-parser", version}` и заголовком
|
||
`Nats-Msg-Id = ack:<job_id>:<attempt>`. Повторный запрос с `job_id`, который уже обрабатывается или обработан этим
|
||
процессом, SHALL получить повторный ack и MUST NOT обрабатываться второй раз.
|
||
|
||
#### Scenario: Ack раньше результата
|
||
- **WHEN** опубликован запрос из `docs/contracts/examples/request-tabular.json`
|
||
- **THEN** первым сообщением сервиса в `files.tabular_parsed` является конверт `processing`, и только затем — результат
|
||
|
||
#### Scenario: Повторный запрос во время обработки
|
||
- **WHEN** тот же запрос доставлен второй раз, пока первый обрабатывается
|
||
- **THEN** публикуется второй ack `processing`, файл из S3 повторно не читается, результат публикуется один раз
|
||
|
||
### Requirement: Результат по контракту
|
||
После подтверждения сервис SHALL прочитать объект `s3.key` из бакета `s3.bucket`, вызвать парсер, записать файл результата
|
||
(по `recognition-result.schema.json`) в `results/{file_id}/{job_id}/result.json` и опубликовать конверт результата (по
|
||
`recognition-result-message.schema.json`) с заголовком `Nats-Msg-Id = result:<job_id>:<attempt>`. При неудаче публикации
|
||
сервис SHALL повторить её до трёх раз с паузой, затем залогировать ошибку.
|
||
|
||
#### Scenario: Запрос с заглушкой парсера (Срез 0)
|
||
- **WHEN** воркеру явно передана заглушка `NullParser` (только тесты воркера; реализация по умолчанию — реальный парсер),
|
||
запрос подтверждён и объект существует в `uploads/`
|
||
- **THEN** в `files.tabular_parsed` появляется конверт `status = error`, `error.code = NOT_IMPLEMENTED`, `job_id`/`file_id`
|
||
из запроса, `metrics.duration_ms ≥ 0`; файл результата может отсутствовать
|
||
|
||
#### Scenario: Запрос с реальным парсером
|
||
- **WHEN** запрос подтверждён и объект в `uploads/` существует, но не является книгой Excel (сигнатура не XLS/XLSX/XLSB)
|
||
- **THEN** в `files.tabular_parsed` появляется конверт `status = error`, `error.code = UNSUPPORTED_FORMAT` (повреждённая
|
||
книга — `UNREADABLE`), `job_id`/`file_id` из запроса, `metrics.duration_ms ≥ 0`; файл результата может отсутствовать;
|
||
корректная ОСВ в том же потоке даёт `done` (см. «Парсер — заменяемый интерфейс»)
|
||
|
||
#### Scenario: Повтор публикации
|
||
- **WHEN** первая публикация конверта результата завершается ошибкой соединения, вторая — успешно
|
||
- **THEN** конверт опубликован один раз с тем же `Nats-Msg-Id`, обработка не повторяется
|