perf(access): TTL-кэш getAccessibleTaskIds с точечной инвалидацией
Шаг 0.12 плана production-готовности: - accessibleTasksCache (45с) per userId:orgId внутри storage-метода - инвалидация в storage-слое: роли, делегирования, form access, assignees, createTask/updateTask, appRole пользователя - 9 новых юнит-тестов (65/65 зелёные)
This commit is contained in:
@@ -11,6 +11,7 @@ import { eq, and, or, isNull, isNotNull, sql, desc } from "drizzle-orm";
|
||||
import { storage } from "../storage";
|
||||
import { notifyTaskAssigned } from "../utils/notifyAssignee";
|
||||
import { logAudit } from "../utils/audit";
|
||||
import { invalidateAccessibleTasksForUser } from "../utils/cache";
|
||||
|
||||
/**
|
||||
* Сервис замещения пользователей (delegation/substitution, референс — Pyrus).
|
||||
@@ -279,6 +280,7 @@ export async function cleanupStaleDelegates(taskId: number, organizationId: numb
|
||||
const activeDelegateId = await getActiveDelegate(row.delegatedFromUserId as number, task.formId, organizationId);
|
||||
if (activeDelegateId !== row.userId) {
|
||||
await db.delete(taskAssignees).where(eq(taskAssignees.id, row.id));
|
||||
invalidateAccessibleTasksForUser(row.userId, organizationId);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
@@ -360,6 +362,9 @@ export async function createDelegation(data: {
|
||||
createdBy: data.createdBy,
|
||||
})
|
||||
.returning();
|
||||
// Замещение меняет доступ заместителя (и потенциально отсутствующего)
|
||||
invalidateAccessibleTasksForUser(data.userId, data.organizationId);
|
||||
invalidateAccessibleTasksForUser(data.delegateUserId, data.organizationId);
|
||||
return { conflict: false, delegation };
|
||||
}
|
||||
|
||||
@@ -380,6 +385,10 @@ export async function updateDelegation(
|
||||
)
|
||||
)
|
||||
.returning();
|
||||
if (updated) {
|
||||
invalidateAccessibleTasksForUser(userId, organizationId);
|
||||
invalidateAccessibleTasksForUser(updated.delegateUserId, organizationId);
|
||||
}
|
||||
return updated ?? null;
|
||||
}
|
||||
|
||||
@@ -397,7 +406,11 @@ export async function deleteDelegation(
|
||||
eq(userDelegations.organizationId, organizationId)
|
||||
)
|
||||
)
|
||||
.returning({ id: userDelegations.id });
|
||||
.returning({ id: userDelegations.id, delegateUserId: userDelegations.delegateUserId });
|
||||
if (deleted.length > 0) {
|
||||
invalidateAccessibleTasksForUser(userId, organizationId);
|
||||
invalidateAccessibleTasksForUser(deleted[0].delegateUserId, organizationId);
|
||||
}
|
||||
return deleted.length > 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user