notify: only "the app is gone" deletes a device row
reported from the field on the first real push: it failed with BadDeviceToken and the server deleted the registration. the build was production-signed and the row said sandbox — a configuration mismatch, with the device and the app both perfectly fine. pruning there destroys the evidence. the phone re-registers on next launch, the row comes back looking healthy, and the next send fails identically; you can lose a day to that loop without ever seeing what is actually wrong. so the one set becomes three. Unregistered/UNREGISTERED/NOT_FOUND prune — apple and google are saying the app is uninstalled. BadDeviceToken, DeviceTokenNotForTopic, TopicDisallowed, INVALID_ARGUMENT and SENDER_ID_MISMATCH are OURS: the row is kept and the log says what to check. everything else is transient and still counts toward three strikes. INVALID_ARGUMENT was the sharpest one. it is how fcm reports a malformed MESSAGE — including a non-string in `data`, which is the mistake this codebase is most likely to make and already has a test for. deleting on it meant one bug in the payload builder would wipe every android device from the registry on a single send, presenting as "android push stopped working" with nothing left to explain why. misconfigured is also not counted as a strike. not deleting is not enough on its own — a persistent mismatch would reach three failures and delete the row anyway, which is the same bug with a slower fuse. the apns log now names the mismatch rather than the reason code, since the code alone sends people to look at the device: it prints the row's environment and topic and says to check the SHIPPED artefact rather than the intermediate build, which is exactly where this one hid.
This commit is contained in:
+5
-2
@@ -17,6 +17,7 @@ import { isWsProviderAllowed } from './servers/permissions/authorize';
|
||||
import { isTokenBlacklisted, getUserById } from 'officerdb';
|
||||
import { terminalWebsocket } from './servers/api/terminal/websocket';
|
||||
import { chatWebsocket } from './servers/api/chat/websocket';
|
||||
import { chatNotifyWebsocket } from './servers/api/chat/notify-delivery';
|
||||
import { taskRunnerWebsocket } from './servers/api/tasks/task-executor';
|
||||
import { pipelineWebsocket } from './servers/api/tasks/pipeline-executor';
|
||||
// import { desktopWebsocket } from './servers/api/desktop/websocket';
|
||||
@@ -53,7 +54,7 @@ type WSData = {
|
||||
userId: number;
|
||||
email: string;
|
||||
username: string;
|
||||
provider: 'terminal' | 'chat' | 'task-runner' | 'pipeline' | 'desktop' | 'sidecar';
|
||||
provider: 'terminal' | 'chat' | 'chat-notify' | 'task-runner' | 'pipeline' | 'desktop' | 'sidecar';
|
||||
sessionId?: string;
|
||||
cwd?: string;
|
||||
command?: string;
|
||||
@@ -142,6 +143,7 @@ const handlers: Record<string, any> = {
|
||||
terminal: terminalWebsocket,
|
||||
'dev-proxy': devProxyWebsocket,
|
||||
chat: chatWebsocket,
|
||||
'chat-notify': chatNotifyWebsocket,
|
||||
'task-runner': taskRunnerWebsocket,
|
||||
pipeline: pipelineWebsocket,
|
||||
// desktop: desktopWebsocket,
|
||||
@@ -292,7 +294,7 @@ console.log(
|
||||
async function upgradeWs(
|
||||
req: Request,
|
||||
server: any,
|
||||
provider: 'terminal' | 'chat' | 'task-runner' | 'pipeline' | 'desktop',
|
||||
provider: 'terminal' | 'chat' | 'chat-notify' | 'task-runner' | 'pipeline' | 'desktop',
|
||||
) {
|
||||
const token = new URL(req.url).searchParams.get('token');
|
||||
if (!token) return new Response('Unauthorized', { status: 401 });
|
||||
@@ -422,6 +424,7 @@ const server = serve({
|
||||
'/api/tasks/pipeline/ws': (req, server) => upgradeWs(req, server, 'pipeline'),
|
||||
'/api/terminal/ws': (req, server) => upgradeWs(req, server, 'terminal'),
|
||||
'/api/chat/ws': (req, server) => upgradeWs(req, server, 'chat'),
|
||||
'/api/chat/notify/ws': (req, server) => upgradeWs(req, server, 'chat-notify'),
|
||||
// '/api/desktop/ws': (req, server) => upgradeWs(req, server, 'desktop'),
|
||||
// CalDAV/CardDAV. These live OUTSIDE /api because DAV clients are given a bare domain and probe
|
||||
// fixed, spec-defined paths — `/.well-known/caldav` unauthenticated, before they hold any
|
||||
|
||||
Reference in New Issue
Block a user