mesh: persist destination (to) on captured rx history records

This commit is contained in:
2026-09-25 15:02:21 +00:00
parent b677c05681
commit 34e7bfe0bb
2 changed files with 44 additions and 5 deletions
+42 -4
View File
@@ -594,6 +594,7 @@ describe('MeshService message history', () => {
id: 1,
dir: 'rx',
from: KAMIL_NUM,
to: 42, // destination persisted on rx records (broadcast addr for broadcasts)
text: 'ping',
channel: 2,
at: expect.any(Number),
@@ -715,10 +716,9 @@ describe('MeshService opencode notifier', () => {
// MeshService with a mocked OpencodeService wired in (structural cast — only notify() is used)
function makeSvc(): MeshService {
return new MeshService(
undefined,
{ notify: notifyMock } as unknown as OpencodeService,
);
return new MeshService(undefined, {
notify: notifyMock,
} as unknown as OpencodeService);
}
it('notifies via the opencode service when an rx text lands on the notify channel (default 3)', async () => {
@@ -1318,6 +1318,44 @@ describe('MeshService SQLite persistence', () => {
}
});
it('persists the destination (to) of captured rx packets on poller tick', async () => {
const bridge = await startBridge();
process.env.MESH_HOST = '127.0.0.1';
process.env.MESH_PORT = String(bridge.port);
process.env.MESH_POLL_MS = '50';
const db = new DatabaseSync(':memory:');
initMessagesTable(db);
const svc = new MeshService(db);
try {
svc.onModuleInit();
await waitFor(
() => bridge.sockets.length === 1 && svc.status().connected,
);
bridge.sockets[0].write(textPacketFrame(KAMIL_NUM, 42, 'ping', 3));
// the poller tick must pick it up — no flushHistory() call here
await waitFor(
() =>
(
db.prepare('SELECT COUNT(*) AS n FROM messages').get() as {
n: number;
}
).n === 1,
);
const row = db
.prepare('SELECT * FROM messages WHERE id = ?')
.get(1) as Record<string, unknown>;
expect(row.dir).toBe('rx');
expect(row.from_node).toBe(KAMIL_NUM);
expect(row.to_node).toBe(42); // rx rows carry the destination now (no schema change — to_node existed for tx)
} finally {
delete process.env.MESH_POLL_MS;
svc.onModuleDestroy();
bridge.close();
}
});
it('reflects the ACK status update in the database after the next tick', async () => {
const bridge = await startBridge();
process.env.MESH_HOST = '127.0.0.1';
+2 -1
View File
@@ -37,7 +37,7 @@ export interface MessageRecord {
dir: 'rx' | 'tx';
/** sender node num — rx only */
from?: number;
/** destination node num (broadcast addr for broadcasts) — tx only */
/** destination node num (broadcast addr for broadcasts) — captured rx packets and all tx records */
to?: number;
text: string;
channel: number;
@@ -626,6 +626,7 @@ export class MeshService implements OnModuleInit, OnModuleDestroy {
id: pkt.id,
dir: 'rx',
from: pkt.from,
to: pkt.to, // destination (broadcast addr for broadcasts) — lets a later reply tell DM vs broadcast apart
text,
channel: pkt.channel ?? 0,
at: Date.now(),