Skip to content

Commit ab28966

Browse files
committed
chore: refresh worker docs and source defaults
1 parent b50b9ba commit ab28966

4 files changed

Lines changed: 40 additions & 103 deletions

File tree

README.md

Lines changed: 38 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,63 @@
11
# processing-worker
22

3-
![CI](https://img.shields.io/badge/CI-GitHub_Actions-2088FF?logo=githubactions&logoColor=white)
4-
![CD](https://img.shields.io/badge/CD-GitHub_Deploy-2ea44f?logo=github&logoColor=white)
5-
![Container](https://img.shields.io/badge/Container-GHCR-2496ED?logo=docker&logoColor=white)
3+
Сервис нормализации и ingest для пайплайна NPPWEB.
64

7-
Сервис асинхронной обработки и нормализации собранных данных.
8-
9-
## Что делает этот репозиторий
5+
## Что делает
106

117
- читает `source.raw.v1` из RabbitMQ;
128
- валидирует raw-события;
139
- нормализует payload до формата `source.normalized.v1`;
14-
- отправляет ingest mutation `ingestNormalizedItem` в `backend-api` с заголовком `x-ingest-token`;
15-
- после успешного ingest публикует нормализованные события в `source.normalized.v1`;
16-
- при transient ошибках отправляет сообщение в retry queue, а poison messages складывает в DLQ.
17-
18-
## Черновая реализация
19-
20-
- consumer RabbitMQ (`src/messaging/queue-client.ts`);
21-
- нормализатор (`src/normalize.ts`);
22-
- валидация raw/normalized схем через Ajv;
23-
- GraphQL-клиент отправки в backend (`src/backend-client.ts`);
24-
- Dockerfile и CI workflow.
10+
- отправляет `ingestNormalizedItem` в `npp-backend` с заголовком `x-ingest-token`;
11+
- публикует успешные нормализованные события в `source.normalized.v1`;
12+
- при transient ошибках использует retry queue, а poison messages отправляет в DLQ.
2513

2614
## Переменные окружения
2715

28-
- `RABBITMQ_URL` - адрес RabbitMQ.
29-
- `QUEUE_RAW_EVENT` - основная очередь входящих raw-событий, по умолчанию `source.raw.v1`.
30-
- `QUEUE_RETRY_EVENT` - очередь retry, по умолчанию `source.raw.retry.v1`.
31-
- `QUEUE_DEAD_LETTER_EVENT` - очередь dead-letter, по умолчанию `source.raw.dlq.v1`.
32-
- `QUEUE_NORMALIZED_EVENT` - очередь нормализованных событий, по умолчанию `source.normalized.v1`.
33-
- `API_BASE_URL` - базовый URL `backend-api`, по умолчанию `http://localhost:3000`.
34-
- `GRAPHQL_PATH` - GraphQL path, по умолчанию `/graphql`.
35-
- `API_GRAPHQL_URL` - явный GraphQL URL. Если задан, имеет приоритет над `API_BASE_URL + GRAPHQL_PATH`.
36-
- `API_INGEST_TOKEN` - токен для заголовка `x-ingest-token`. Должен совпадать с `INGEST_API_TOKEN` в `backend-api`.
37-
- `SHARED_CONTRACTS_DIR` - путь к `shared-contracts`.
38-
- `RETRY_ATTEMPTS`, `RETRY_BASE_DELAY_MS`, `PREFETCH`, `LOG_LEVEL` - параметры обработки и логирования.
16+
- `RABBITMQ_URL`
17+
- `QUEUE_RAW_EVENT`
18+
- `QUEUE_RETRY_EVENT`
19+
- `QUEUE_DEAD_LETTER_EVENT`
20+
- `QUEUE_NORMALIZED_EVENT`
21+
- `API_BASE_URL`
22+
- `GRAPHQL_PATH`
23+
- `API_GRAPHQL_URL`
24+
- `API_INGEST_TOKEN`
25+
- `SHARED_CONTRACTS_DIR`
26+
- `RETRY_ATTEMPTS`
27+
- `RETRY_BASE_DELAY_MS`
28+
- `PREFETCH`
29+
30+
По умолчанию `SHARED_CONTRACTS_DIR` указывает на `../contracts`.
3931

4032
## Локальный запуск
4133

4234
```bash
35+
cd ../infra
4336
cp .env.example .env
37+
docker compose --env-file .env -f docker-compose.yml -f docker-compose.apps.yml up -d rabbitmq backend-api
38+
39+
cd ../processing-worker
4440
npm install
4541
npm run start:dev
4642
```
4743

48-
Для Docker Compose сервис ожидает:
49-
50-
- RabbitMQ на `RABBITMQ_URL`;
51-
- `backend-api` на `API_BASE_URL` или `API_GRAPHQL_URL`;
52-
- смонтированный `shared-contracts` в `SHARED_CONTRACTS_DIR`.
53-
5444
## Ожидаемые очереди
5545

56-
- `source.raw.v1` - входящие события.
57-
- `source.raw.retry.v1` - delayed retry queue.
58-
- `source.raw.dlq.v1` - dead-letter queue.
59-
- `source.normalized.v1` - успешно обработанные нормализованные события.
46+
- `source.raw.v1`
47+
- `source.raw.retry.v1`
48+
- `source.raw.dlq.v1`
49+
- `source.normalized.v1`
6050

61-
## Как проверить обработку
51+
## Проверка качества
6252

63-
1. Опубликуй валидное сообщение в `source.raw.v1`.
64-
2. В логах worker должны появиться строки `connected to rabbitmq`, `consuming queue`, `raw event validated`, `normalized event created`, `ingest success`, `published normalized event`, `message acknowledged`.
65-
3. Проверь, что сообщение появилось в `source.normalized.v1`, а запись создалась в `backend-api`.
66-
4. Для transient ошибки временно выключи `backend-api`: worker должен логировать `ingest failed` и `retry scheduled`, а не падать.
67-
5. Для poison message отправь невалидный JSON или payload, нарушающий schema: worker должен логировать `message dead-lettered`, сообщение должно уйти в `source.raw.dlq.v1`.
53+
```bash
54+
npm run check
55+
npm run test
56+
npm run build
57+
```
6858

69-
## Связи с другими репозиториями
59+
## Связи
7060

71-
- получает события от `scraper-service`;
72-
- использует схемы из `shared-contracts`;
73-
- отправляет результаты в `backend-api`.
61+
- получает события от `scrape-helper`;
62+
- использует схемы из `contracts`;
63+
- отправляет результаты в `npp-backend`.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "processing-worker",
33
"version": "1.0.0",
44
"private": true,
5-
"description": "Production-ready normalization worker for AIMSORA with retry/DLQ handling and strict contract validation.",
5+
"description": "Production-ready normalization worker for NPPWEB with retry/DLQ handling and strict contract validation.",
66
"scripts": {
77
"build": "tsc -p tsconfig.json",
88
"start": "node dist/main.js",

src/config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const envSchema = z.object({
1111
QUEUE_RETRY_EVENT: z.string().default("source.raw.retry.v1"),
1212
QUEUE_DEAD_LETTER_EVENT: z.string().default("source.raw.dlq.v1"),
1313
QUEUE_NORMALIZED_EVENT: z.string().default("source.normalized.v1"),
14-
SHARED_CONTRACTS_DIR: z.string().default("../shared-contracts"),
14+
SHARED_CONTRACTS_DIR: z.string().default("../contracts"),
1515
RETRY_ATTEMPTS: z.coerce.number().int().positive().default(5),
1616
RETRY_BASE_DELAY_MS: z.coerce.number().int().positive().default(5000),
1717
PREFETCH: z.coerce.number().int().positive().default(10)

src/normalize.spec.ts

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -3,59 +3,6 @@ import { normalizeRawEvent } from "./normalize";
33
import type { RawSourceEvent } from "./types";
44

55
describe("normalizeRawEvent", () => {
6-
it("normalizes demo-source payload", () => {
7-
const input: RawSourceEvent = {
8-
eventId: "evt-1",
9-
runKey: "demo-run",
10-
source: "demo-source",
11-
collectedAt: "2026-03-30T10:00:00.000Z",
12-
url: "https://example.org",
13-
payloadVersion: "v1",
14-
artifacts: [],
15-
raw: {
16-
externalId: "demo-1",
17-
title: "Поставка оборудования",
18-
customer: "АО Демонстрационная АЭС",
19-
amount: 1200
20-
}
21-
};
22-
23-
const normalized = normalizeRawEvent(input);
24-
25-
expect(normalized.externalId).toBe("demo-1");
26-
expect(normalized.title).toBe("Поставка оборудования");
27-
expect(normalized.customer).toBe("АО Демонстрационная АЭС");
28-
expect(normalized.amount).toBe(1200);
29-
expect(normalized.sourceUrl).toBe("https://example.org");
30-
});
31-
32-
it("normalizes find-tender payload using ocid", () => {
33-
const input: RawSourceEvent = {
34-
eventId: "evt-2",
35-
runKey: "find-tender-run",
36-
source: "find-tender",
37-
collectedAt: "2026-03-30T10:00:00.000Z",
38-
url: "https://www.find-tender.service.gov.uk/Notice/008889-2026",
39-
payloadVersion: "v1",
40-
artifacts: [],
41-
raw: {
42-
ocid: "ocds-h6vhtk-061410",
43-
title: "E-Disclosure Services",
44-
buyer: "Care Quality Commission",
45-
supplier: "KLDISCOVERY LIMITED",
46-
amount: 150000,
47-
currency: "GBP"
48-
}
49-
};
50-
51-
const normalized = normalizeRawEvent(input);
52-
53-
expect(normalized.externalId).toBe("ocds-h6vhtk-061410");
54-
expect(normalized.title).toBe("E-Disclosure Services");
55-
expect(normalized.customer).toBe("Care Quality Commission");
56-
expect(normalized.sourceUrl).toContain("find-tender.service.gov.uk");
57-
});
58-
596
it("normalizes eis payload using procurement-specific fields", () => {
607
const input: RawSourceEvent = {
618
eventId: "evt-3",

0 commit comments

Comments
 (0)