add sync-to-cache pipeline, publish events on new threads
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
71
backend/src/services/cache-sync.test.ts
Normal file
71
backend/src/services/cache-sync.test.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { describe, expect, test, beforeEach } from "bun:test";
|
||||
import { syncThreadsToCache } from "./cache-sync";
|
||||
import { createDatabase, getThreads, getMessagesForThread } from "../db/index";
|
||||
import { EventBus } from "./eventbus";
|
||||
import type { ThreadSummary, Message } from "./notmuch";
|
||||
import type { Database } from "bun:sqlite";
|
||||
|
||||
let db: Database;
|
||||
let bus: EventBus;
|
||||
|
||||
beforeEach(() => {
|
||||
db = createDatabase(":memory:");
|
||||
bus = new EventBus();
|
||||
});
|
||||
|
||||
const mockThreads: ThreadSummary[] = [
|
||||
{
|
||||
threadId: "t001",
|
||||
subject: "Q1 Planning",
|
||||
authors: "Alice, Bob",
|
||||
totalMessages: 2,
|
||||
tags: ["inbox", "unread"],
|
||||
timestamp: 1709884532,
|
||||
},
|
||||
];
|
||||
|
||||
const mockMessages: Message[] = [
|
||||
{
|
||||
messageId: "msg001@example.com",
|
||||
from: "Alice <alice@example.com>",
|
||||
to: "user@example.com",
|
||||
subject: "Q1 Planning",
|
||||
date: "Fri, 08 Mar 2024 10:15:32 +0100",
|
||||
inReplyTo: "",
|
||||
references: "",
|
||||
body: "Hey, let's plan Q1.\n",
|
||||
tags: ["inbox", "unread"],
|
||||
timestamp: 1709884532,
|
||||
},
|
||||
{
|
||||
messageId: "msg003@example.com",
|
||||
from: "Bob <bob@example.com>",
|
||||
to: "alice@example.com",
|
||||
subject: "Re: Q1 Planning",
|
||||
date: "Fri, 08 Mar 2024 10:16:40 +0100",
|
||||
inReplyTo: "msg001@example.com",
|
||||
references: "msg001@example.com",
|
||||
body: "Sounds good.\n",
|
||||
tags: ["inbox"],
|
||||
timestamp: 1709884600,
|
||||
},
|
||||
];
|
||||
|
||||
describe("syncThreadsToCache", () => {
|
||||
test("populates database from thread/message data", () => {
|
||||
const events: unknown[] = [];
|
||||
bus.subscribe((e) => events.push(e));
|
||||
|
||||
syncThreadsToCache(db, bus, "personal", mockThreads, new Map([["t001", mockMessages]]));
|
||||
|
||||
const threads = getThreads(db, "personal");
|
||||
expect(threads).toHaveLength(1);
|
||||
expect(threads[0].subject).toBe("Q1 Planning");
|
||||
|
||||
const messages = getMessagesForThread(db, "t001");
|
||||
expect(messages).toHaveLength(2);
|
||||
|
||||
expect(events.length).toBeGreaterThan(0);
|
||||
expect(events[0]).toEqual(expect.objectContaining({ type: "threads_updated" }));
|
||||
});
|
||||
});
|
||||
51
backend/src/services/cache-sync.ts
Normal file
51
backend/src/services/cache-sync.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import type { Database } from "bun:sqlite";
|
||||
import type { EventBus } from "./eventbus";
|
||||
import type { ThreadSummary, Message } from "./notmuch";
|
||||
import { insertThread, insertMessage } from "../db/index";
|
||||
|
||||
export function syncThreadsToCache(
|
||||
db: Database,
|
||||
bus: EventBus,
|
||||
accountId: string,
|
||||
threads: ThreadSummary[],
|
||||
messagesMap: Map<string, Message[]>,
|
||||
): void {
|
||||
const transaction = db.transaction(() => {
|
||||
for (const thread of threads) {
|
||||
insertThread(db, {
|
||||
threadId: thread.threadId,
|
||||
subject: thread.subject,
|
||||
authors: thread.authors,
|
||||
totalMessages: thread.totalMessages,
|
||||
tags: thread.tags.join(","),
|
||||
timestamp: thread.timestamp,
|
||||
accountId,
|
||||
});
|
||||
|
||||
const messages = messagesMap.get(thread.threadId) ?? [];
|
||||
for (const msg of messages) {
|
||||
insertMessage(db, {
|
||||
messageId: msg.messageId,
|
||||
threadId: thread.threadId,
|
||||
fromHeader: msg.from,
|
||||
toHeader: msg.to,
|
||||
subject: msg.subject,
|
||||
date: msg.date,
|
||||
inReplyTo: msg.inReplyTo,
|
||||
body: msg.body,
|
||||
tags: msg.tags.join(","),
|
||||
timestamp: msg.timestamp,
|
||||
accountId,
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
transaction();
|
||||
|
||||
bus.publish({
|
||||
type: "threads_updated",
|
||||
accountId,
|
||||
threadCount: threads.length,
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user