perf(sse+tasks): индекс SSE-соединений, getTaskTree на recursive CTE, батчи N+1

Шаги 1.4 и 1.5 плана production-готовности:
- SseConnectionIndex (byOrg/byUser), один heartbeat-таймер, протокол SSE не тронут
- getTaskTree/getTaskParentChain: WITH RECURSIVE CTE (было 1+2N запросов)
- sync initial/delta: Promise.all по формам
- embedding queue/reindex: батч-предзагрузки вместо поштучных запросов
- 8 новых тестов (96/96)
This commit is contained in:
2026-09-07 23:29:21 +03:00
parent 9528a8123a
commit 667a321341
10 changed files with 518 additions and 121 deletions

View File

@@ -204,6 +204,8 @@ export interface IStorage {
// Task Field Values
getTaskFieldValues(taskId: number, organizationId: number): Promise<TaskFieldValue[]>;
getTasksByIds(taskIds: number[], organizationId: number): Promise<Task[]>;
getTaskFieldValuesByTaskIds(taskIds: number[], organizationId: number): Promise<TaskFieldValue[]>;
createTaskFieldValue(insertValue: InsertTaskFieldValue): Promise<TaskFieldValue>;
updateTaskFieldValue(taskId: number, fieldId: number, organizationId: number, updates: Partial<TaskFieldValue>): Promise<TaskFieldValue>;
bulkUpsertTaskFieldValues(taskId: number, formId: number, updates: Array<{ fieldId: number; value: unknown }>): Promise<TaskFieldValue[]>;
@@ -216,6 +218,8 @@ export interface IStorage {
// Task Messages (Chat)
getTaskMessages(taskId: number, organizationId: number, afterId?: number): Promise<TaskMessageWithAuthor[]>;
getTaskMessage(messageId: number, organizationId: number): Promise<TaskMessageWithAuthor | undefined>;
getTaskMessagesByIds(messageIds: number[], organizationId: number): Promise<TaskMessage[]>;
getTaskMessagesByTaskIds(taskIds: number[], organizationId: number): Promise<TaskMessage[]>;
createTaskMessage(insertMessage: any, organizationId: number): Promise<any>;
updateTaskMessage(id: number, organizationId: number, updates: Partial<TaskMessage>): Promise<TaskMessage>;
deleteTaskMessage(id: number, organizationId: number): Promise<void>;