fix: RAG embedding_queue ON CONFLICT + пересоздание finance views

- enqueueEmbedding: onConflictDoNothing без предиката не находил
  частичный уникальный индекс embedding_queue_pending_entity_idx
  (WHERE processed_at IS NULL) — каждая постановка в очередь индексации
  падала. Добавлен where: isNull(processedAt).
- finance ensureViews: CREATE OR REPLACE VIEW не умеет менять тип столбца
  (stavkands text↔varchar во внешней БД omegaprom) — заменено на
  DROP VIEW IF EXISTS + CREATE VIEW (зависимых объектов нет).
This commit is contained in:
2026-08-06 15:10:38 +03:00
parent 47869971e6
commit 5ff2aaa023
2 changed files with 13 additions and 3 deletions

View File

@@ -67,8 +67,11 @@ export async function ensureViews(): Promise<void> {
}
if (incomeExists) {
// CREATE OR REPLACE VIEW не умеет менять типы столбцов (тип stavkands в источнике
// изменился text ↔ varchar) — пересоздаём view целиком. Зависимых объектов нет.
await query(`DROP VIEW IF EXISTS vw_income_effective`);
await query(`
CREATE OR REPLACE VIEW vw_income_effective AS
CREATE VIEW vw_income_effective AS
SELECT t.*, o.category_id as _override_category_id
FROM "${config.incomeTable}" t
LEFT JOIN income_category_overrides o ON o.record_id = t.id::text
@@ -76,8 +79,9 @@ export async function ensureViews(): Promise<void> {
}
if (expenseExists) {
await query(`DROP VIEW IF EXISTS vw_expense_effective`);
await query(`
CREATE OR REPLACE VIEW vw_expense_effective AS
CREATE VIEW vw_expense_effective AS
SELECT t.*, o.category_id as _override_category_id
FROM "${config.expenseTable}" t
LEFT JOIN expense_category_overrides o ON o.record_id = t.id::text

View File

@@ -489,7 +489,13 @@ export class SystemStorage extends RolesStorage {
operation,
createdAt: new Date(),
})
.onConflictDoNothing({ target: [embeddingQueue.organizationId, embeddingQueue.entityType, embeddingQueue.entityId] });
.onConflictDoNothing({
target: [embeddingQueue.organizationId, embeddingQueue.entityType, embeddingQueue.entityId],
// Уникальный индекс embedding_queue_pending_entity_idx частичный
// (WHERE processed_at IS NULL) — без этого предиката Postgres не находит
// подходящий constraint и весь INSERT падает с ошибкой.
where: isNull(embeddingQueue.processedAt),
});
}
async getPendingEmbeddingQueue(