Gateway: status route with per-route results, test push, reconnect and unpair
Gateway / check (push) Successful in 9s
Gateway / image (push) Successful in 24s

This commit is contained in:
gib committed 2026-11-01 15:04:30 -05:00
1 parent e6fd2b8f51
commit 9707daf1fe
9 files changed
+398 -55

No files matched your search

+6 -32
View File
@@ -9,7 +9,8 @@ import { createRoutes } from "./api.ts";
import { loadConfig } from "./config.ts";
import { openDb } from "./db.ts";
import { Hub } from "./hub.ts";
import { Notifier, type SendPush } from "./notify.ts";
import { Notifier } from "./notify.ts";
import { Pusher } from "./push.ts";
import { SummaryCache } from "./views.ts";
const HOST_SYNC_MS = 15_000;
@@ -17,6 +18,7 @@ const TOKEN_CHECK_MS = 6 * 60 * 60_000;
const log = (message: string) => console.log(`${new Date().toISOString()} ${message}`);
const startedAt = new Date().toISOString();
const config = loadConfig();
mkdirSync(dirname(config.dbPath), { recursive: true });
const db = openDb(config.dbPath);
@@ -24,37 +26,9 @@ const cache = new SummaryCache(log);
const apns = config.apns ? new Apns(config.apns) : null;
if (!apns) log("APNs is not configured. Pushes will only be logged.");
const sendPush: SendPush = async (push) => {
const devices = db.devices.active().filter((device) => device.apns_token && device.apns_env);
if (!apns || devices.length === 0) {
log(`push (not sent): [${push.category}] ${push.title}: ${push.body}`);
return;
}
const payload = {
aps: {
alert: { title: push.title, ...(push.subtitle ? { subtitle: push.subtitle } : {}), body: push.body },
sound: "default",
category: push.category,
"thread-id": push.data.threadId ?? push.data.hostId,
},
...push.data,
};
await Promise.all(
devices.map(async (device) => {
const result = await apns.send({
deviceToken: device.apns_token!,
environment: device.apns_env!,
payload,
collapseId: push.collapseId,
});
if (result.ok) return;
log(`APNs refused a push to ${device.name}: ${result.status} ${result.reason}`);
if (result.tokenInvalid) db.devices.clearPush(device.apns_token!);
}),
);
};
const pusher = new Pusher(db, apns, log);
const notifier = new Notifier(sendPush, cache, log);
const notifier = new Notifier(pusher.sendAll, cache, log);
const hub = new Hub(db, { onThreadChange: notifier.onThreadChange, onStatus: notifier.onHostStatus, log });
hub.sync();
setInterval(() => hub.sync(), HOST_SYNC_MS);
@@ -63,7 +37,7 @@ setInterval(() => notifier.checkTokenExpiry(hub.rows()), TOKEN_CHECK_MS);
const server = Bun.serve({
port: config.port,
routes: createRoutes({ db, hub, cache, log }),
routes: createRoutes({ db, hub, cache, pusher, startedAt, log }),
fetch: () => Response.json({ error: "Not found." }, { status: 404 }),
});
log(`WristCode gateway listening on :${server.port} with ${hub.list().length} host(s)`);