feat(push): smart push queueing with page-visibility fast path and app-ping/pong fallback
This commit is contained in:
+22
-5
@@ -21,6 +21,7 @@ export function initDB(config: AppConfig): void {
|
||||
endpoint TEXT PRIMARY KEY,
|
||||
p256dh TEXT NOT NULL,
|
||||
auth TEXT NOT NULL,
|
||||
device_id TEXT,
|
||||
created_at TEXT DEFAULT (datetime('now')),
|
||||
last_used TEXT
|
||||
);
|
||||
@@ -80,6 +81,13 @@ export function initDB(config: AppConfig): void {
|
||||
db.exec("ALTER TABLE session_reviews ADD COLUMN parent_adapter TEXT NOT NULL DEFAULT 'claude'");
|
||||
}
|
||||
|
||||
// Migration: add device_id column to push_subscriptions if missing
|
||||
const pushInfo = db.pragma('table_info(push_subscriptions)') as { name: string }[];
|
||||
if (!pushInfo.some(c => c.name === 'device_id')) {
|
||||
db.exec("ALTER TABLE push_subscriptions ADD COLUMN device_id TEXT DEFAULT NULL");
|
||||
}
|
||||
db.exec("CREATE INDEX IF NOT EXISTS idx_push_device ON push_subscriptions(device_id)");
|
||||
|
||||
// Migration: add end_anchor_message_id column to session_reviews if missing
|
||||
if (!reviewInfo.some(c => c.name === 'end_anchor_message_id')) {
|
||||
db.exec("ALTER TABLE session_reviews ADD COLUMN end_anchor_message_id TEXT DEFAULT NULL");
|
||||
@@ -109,6 +117,7 @@ function getDB(): BetterSqlite3.Database {
|
||||
|
||||
interface PreparedStatements {
|
||||
pushSubsSave: BetterSqlite3.Statement;
|
||||
pushSubsRemoveByDevice: BetterSqlite3.Statement;
|
||||
pushSubsRemove: BetterSqlite3.Statement;
|
||||
pushSubsGetAll: BetterSqlite3.Statement;
|
||||
pushSubsMarkUsed: BetterSqlite3.Statement;
|
||||
@@ -139,12 +148,16 @@ function stmts(): PreparedStatements {
|
||||
_stmts = {
|
||||
// push_subscriptions
|
||||
pushSubsSave: d.prepare(`
|
||||
INSERT INTO push_subscriptions (endpoint, p256dh, auth)
|
||||
VALUES (?, ?, ?)
|
||||
INSERT INTO push_subscriptions (endpoint, p256dh, auth, device_id)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON CONFLICT(endpoint) DO UPDATE SET
|
||||
p256dh = excluded.p256dh,
|
||||
auth = excluded.auth
|
||||
auth = excluded.auth,
|
||||
device_id = excluded.device_id
|
||||
`),
|
||||
pushSubsRemoveByDevice: d.prepare(
|
||||
`DELETE FROM push_subscriptions WHERE device_id = ? AND endpoint != ?`
|
||||
),
|
||||
pushSubsRemove: d.prepare(
|
||||
`DELETE FROM push_subscriptions WHERE endpoint = ?`
|
||||
),
|
||||
@@ -243,13 +256,17 @@ export interface PushSubRow {
|
||||
endpoint: string;
|
||||
p256dh: string;
|
||||
auth: string;
|
||||
device_id: string | null;
|
||||
created_at: string;
|
||||
last_used: string | null;
|
||||
}
|
||||
|
||||
export const pushSubs = {
|
||||
save(endpoint: string, p256dh: string, auth: string): void {
|
||||
stmts().pushSubsSave.run(endpoint, p256dh, auth);
|
||||
save(endpoint: string, p256dh: string, auth: string, deviceId: string | null): void {
|
||||
stmts().pushSubsSave.run(endpoint, p256dh, auth, deviceId ?? null);
|
||||
if (deviceId) {
|
||||
stmts().pushSubsRemoveByDevice.run(deviceId, endpoint);
|
||||
}
|
||||
},
|
||||
|
||||
remove(endpoint: string): void {
|
||||
|
||||
Reference in New Issue
Block a user