--- id: entity-rag-index-job title: Сущность IndexJob doc_type: domain_entity domain: rag status: draft owner: system-analyst source_of_truth: code related_docs: - arch-rag-package - logic-rag-indexing - entity-rag-session - api-rag-session-job related_code: - src/app/modules/rag/job_store.py - src/app/modules/rag/indexing_service.py - src/app/modules/rag/persistence/job_repository.py - src/app/modules/rag/persistence/schema_repository.py entities: - IndexJob - RagSession tags: - rag - indexing - job - domain-entity --- # Сущность IndexJob ## Summary - Domain: rag - Purpose: представить асинхронную задачу индексации и её наблюдаемый статус. - Entity role: operational entity для выполнения snapshot/change indexing. - Main attributes: `index_job_id`, `rag_session_id`, `status`, `indexed_files`, `failed_files`, `cache_hit_files`, `cache_miss_files`, `error`. - Lifecycle: `queued -> running -> done|error`. - Invariants: job всегда принадлежит одной `RagSession`, статус хранится как enum `IndexJobStatus`. - Related APIs: создание job косвенно через session endpoints, чтение через job status endpoint и SSE endpoint. - Related logic: `IndexingOrchestrator`, retry, EventBus publishing. - Source of truth: `src/app/modules/rag/job_store.py`, `src/app/modules/rag/indexing_service.py`. ## Назначение `IndexJob` хранит технический прогресс и итог выполнения индексации. Он нужен, чтобы API модуля мог вернуть результат не синхронно, а через опрос статуса и подписку на события. ## Контекст Job создаётся на каждую snapshot- или changes-операцию. Сервис индексации обновляет его counters и публикует события прогресса в EventBus под ключом `index_job_id`. ## Роль в доменной модели Это операционная сущность, которая связывает пользовательский запрос на индексацию с фактическим процессом обработки файлов. Она не хранит сам индекс, но управляет прозрачностью выполнения и ошибками. ## Атрибуты | attribute | type | required | description | constraints | |-----------|------|----------|-------------|-------------| | `index_job_id` | `str` | yes | уникальный идентификатор задачи | primary key, non-empty | | `rag_session_id` | `str` | yes | ссылка на целевую RAG-сессию | non-empty | | `status` | `IndexJobStatus` | yes | текущее состояние задачи | `queued`, `running`, `done`, `error` | | `indexed_files` | `int` | yes | число успешно обработанных файлов | `>= 0` | | `failed_files` | `int` | yes | число файлов с ошибками | `>= 0` | | `cache_hit_files` | `int` | yes | число файлов, обслуженных из cache | `>= 0` | | `cache_miss_files` | `int` | yes | число файлов, потребовавших embeddings | `>= 0` | | `error` | `ErrorPayload \| None` | no | информация о необработанной временной ошибке после retry | optional | ## Состояния и жизненный цикл ### Основные состояния - `queued` - `running` - `done` - `error` ### Переходы состояний 1. `IndexJobStore.create` создаёт job в состоянии `queued`. 2. `IndexingOrchestrator._run_with_project_lock` переводит job в `running`. 3. Успешная индексация переводит job в `done` и заполняет counters. 4. Ошибка после исчерпания retry переводит job в `error` и заполняет `ErrorPayload`. ## Инварианты и ограничения - Job не мигрирует между `rag_session_id`. - Финальные counters сохраняются в БД перед публикацией terminal event. - Ошибки уровня `TimeoutError`, `ConnectionError`, `OSError` считаются временными и оборачиваются в `index_retry_exhausted` только после retry exhaustion. ## Связи с другими сущностями | entity | relation | description | |--------|----------|-------------| | `RagSession` | many-to-one | каждая задача относится к одной сессии | | `RagDocument` | indirect | job обновляет набор документов сессии, но не владеет ими напрямую | ## Использование в системе ### Related API - `POST /api/rag/sessions` - `POST /api/rag/sessions/{rag_session_id}/changes` - `GET /api/rag/sessions/{rag_session_id}/jobs/{index_job_id}` - `GET /api/rag/sessions/{rag_session_id}/jobs/{index_job_id}/events` ### Related UI - Прямого UI в репозитории не обнаружено. ### Related logic - `logic-rag-indexing` ### Related integrations - EventBus SSE stream - PostgreSQL таблица `rag_index_jobs` ## Функциональные требования - Job должна создаваться до запуска фоновой задачи. - Публичный API обязан проверять принадлежность job указанной `rag_session_id`. - Progress events должны публиковаться в формате, достаточном для фронта или внешнего клиента. ## Нефункциональные требования ### Audit / history - `created_at` и `updated_at` сохраняются в таблице `rag_index_jobs`. ### Security - Доступ к job опирается на проверку связи `job.rag_session_id == requested rag_session_id`. ### Observability - SSE stream отдаёт `index_status`, `index_progress`, `terminal`. ## Связанный код ### Files - `src/app/modules/rag/job_store.py` - `src/app/modules/rag/indexing_service.py` - `src/app/modules/rag/persistence/job_repository.py` - `src/app/modules/rag/persistence/schema_repository.py` ### Symbols - `IndexJob` - `IndexJobStore.create` - `IndexJobStore.get` - `IndexJobStore.save` - `IndexingOrchestrator._run_with_project_lock` ## Связанные документы - `arch-rag-package` - `logic-rag-indexing` - `entity-rag-session` - `api-rag-session-job` ## История изменений | Date | Source | Changes | |------|--------|---------| | 2026-03-13 | code | Добавлено описание lifecycle и контракта сущности `IndexJob`. |