mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-18 19:21:23 +02:00
fix(ai): P1 batch — N+1 queries, vault-locked, debug hardening, timeout
Four P1 fixes from the AI Workbench audit: #3 N+1 junction queries → batch lookups: - TagLinkOps gains getTagIdsForMany(entityIds) — single where(field).anyOf(ids).toArray() instead of N calls. - filterBySceneScopeBatch() uses a pre-fetched Map<id, tagId[]>. - All 4 module queries (notes, todo, contacts, calendar) migrated. - 500 notes now = 2 Dexie queries (records + junctions) instead of 501. #4 Vault-locked detection in readLocalNote: - Catches VaultLockedError from decryptRecords. - Throws descriptive "Vault ist gesperrt" instead of returning null. - Tools surface it as a clear error to the planner ("bitte Vault entsperren") instead of "Notiz nicht gefunden". #5 Debug log hardening: - Resolved-input content truncated to 500 chars before storage. - Time-based purge: entries older than 7 days auto-deleted. - Reduces privacy exposure if device is stolen/profile synced. #6 Timeout 90s → 180s: - 5 LLM calls on slow models (Ollama/GPU) regularly hit 90s. - 180s gives comfortable headroom for the reasoning loop. Audit doc updated with status markers. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
93358ed002
commit
a480393bfd
9 changed files with 131 additions and 22 deletions
|
|
@ -42,6 +42,13 @@ export interface TagLinkOpsConfig {
|
|||
export interface TagLinkOps {
|
||||
/** Get all tag IDs linked to an entity */
|
||||
getTagIds(entityId: string): Promise<string[]>;
|
||||
/**
|
||||
* Batch variant: fetch tag IDs for many entities in ONE Dexie query.
|
||||
* Returns a Map<entityId, tagId[]>. Entities with no tags are absent
|
||||
* from the map (not present with empty array). Use this in list views
|
||||
* and scope filters to avoid N+1 queries.
|
||||
*/
|
||||
getTagIdsForMany(entityIds: string[]): Promise<Map<string, string[]>>;
|
||||
/** Add a tag to an entity (no-op if already linked) */
|
||||
addTag(entityId: string, tagId: string): Promise<void>;
|
||||
/** Remove a tag from an entity (soft-delete) */
|
||||
|
|
@ -66,6 +73,20 @@ export function createTagLinkOps(config: TagLinkOpsConfig): TagLinkOps {
|
|||
return links.map((l) => l.tagId);
|
||||
},
|
||||
|
||||
async getTagIdsForMany(entityIds: string[]): Promise<Map<string, string[]>> {
|
||||
if (entityIds.length === 0) return new Map();
|
||||
const all = await config.table().where(entityIdField).anyOf(entityIds).toArray();
|
||||
const active = all.filter((r) => !r.deletedAt);
|
||||
const result = new Map<string, string[]>();
|
||||
for (const link of active) {
|
||||
const eid = link[entityIdField] as string;
|
||||
const arr = result.get(eid);
|
||||
if (arr) arr.push(link.tagId);
|
||||
else result.set(eid, [link.tagId]);
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
async addTag(entityId: string, tagId: string): Promise<void> {
|
||||
const existing = await getActive(entityId);
|
||||
if (existing.some((l) => l.tagId === tagId)) return;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue