fix(server): send push notifications at high priority so Android delivers them on time

This commit is contained in:
Andrii Panasiuk
2026-11-01 23:59:57 +00:00
committed by paseo-bot[bot]
parent dbbcb103ba
commit 57586e6b52
2 changed files with 47 additions and 0 deletions
@@ -0,0 +1,42 @@
import type pino from "pino";
import { afterEach, describe, expect, test, vi } from "vitest";
import { PushService } from "./push-service.js";
function createLogger(): pino.Logger {
const logger = {
child: () => logger,
debug: () => undefined,
info: () => undefined,
warn: () => undefined,
error: () => undefined,
};
return logger as unknown as pino.Logger;
}
describe("PushService", () => {
afterEach(() => {
vi.unstubAllGlobals();
});
test("sends high priority so Android delivers while the device dozes", async () => {
const requests: unknown[] = [];
vi.stubGlobal(
"fetch",
vi.fn(async (_url: string, init: RequestInit) => {
requests.push(JSON.parse(String(init.body)));
return new Response(JSON.stringify({ data: [{ status: "ok", id: "ticket" }] }));
}),
);
const service = new PushService(createLogger(), () => undefined);
await service.sendPush(["ExponentPushToken[android-device]"], {
title: "Agent finished",
body: "Done",
});
expect(requests).toEqual([
[expect.objectContaining({ to: "ExponentPushToken[android-device]", priority: "high" })],
]);
});
});
@@ -12,6 +12,7 @@ interface ExpoPushMessage {
body: string;
data?: Record<string, unknown>;
sound?: "default";
priority?: "default" | "normal" | "high";
}
interface ExpoPushTicket {
@@ -42,12 +43,16 @@ export class PushService {
return;
}
// Expo defaults to "normal" priority on Android, which FCM holds back while
// the device dozes, so notifications arrive minutes late. iOS already
// defaults to "high".
const messages: ExpoPushMessage[] = tokens.map((token) => ({
to: token,
title: payload.title,
body: payload.body,
data: payload.data,
sound: "default",
priority: "high",
}));
// Batch tokens (max 100 per request per Expo limits)