Episode-ready push notification (server-driven, no client polling/BGTask) #5

Open
opened 2026-07-01 17:05:46 +00:00 by admin · 0 comments
Owner

Summary

Notify the user when a podcast is ready via a server-sent APNs push, and let
generation complete without the app staying alive. Because generation already
runs server-side, this replaces the client-side poll/BGTask approach entirely:
the backend knows when a job finishes and simply tells the device.

This supersedes the original BGTask design — polling podcastStatus and running
a background task on the client goes away.

Why server-driven

The compute already happens on the magicive.api backend. Today the app only does
the bookkeeping around it — poll status, download the mp3, write PodcastIndex,
and (in the old plan) a BGTask to keep that alive. Move the "when is it done"
signal to APNs and almost all of that disappears.

  • Backend fires a user-facing APNs alert when a job completes:
    "Your podcast on
## Summary Notify the user when a podcast is ready via a **server-sent APNs push**, and let generation complete without the app staying alive. Because generation already runs server-side, this replaces the client-side poll/BGTask approach entirely: the backend knows when a job finishes and simply *tells* the device. This supersedes the original BGTask design — polling `podcastStatus` and running a background task on the client goes away. ## Why server-driven The compute already happens on the magicive.api backend. Today the app only does the bookkeeping around it — poll status, download the mp3, write `PodcastIndex`, and (in the old plan) a BGTask to keep that alive. Move the "when is it done" signal to APNs and almost all of that disappears. ## Recommended approach — Variant A: download-on-play - Backend fires a **user-facing APNs alert** when a job completes: "Your podcast on <title> is ready", deep-linking via the existing `marks://podcast?url=…` handler (`handleDeepLink` in `MarksApp`). - The episode "exists" server-side; the client **downloads the audio only when the user opens/plays it**. No BGTask, no background download, fully server-driven. - The library lists server-known episodes that may not be downloaded yet (download on play, then cache locally as today). ## Optional follow-up — Variant B: pre-download for offline - Add a **silent push** (`content-available: 1`) + a background `URLSession` download so the mp3 is on-device before the app is opened. - Note: iOS throttles silent pushes, so delivery is best-effort, not instant. - Slim client handler; still no polling loop. Defer unless offline-before-open is required. ## Backend tasks - [ ] APNs credentials: auth key (`.p8`), topic = app bundle id. - [ ] `device_token ↔ user` registry (the generate endpoint already runs under a Bearer identity via `MarksAuth`, so the user mapping exists). - [ ] On job completion, send an APNs alert with title + `marks://podcast?url=…` payload. (Variant B: also send a silent `content-available` push.) - [ ] Per-user episode catalog endpoint (see tradeoff below) so the client can list server-known episodes. ## Client tasks - [ ] Register for remote notifications; request permission at first generation. - [ ] Send the APNs **device token** to the backend, tied to the auth identity. - [ ] Handle notification tap → open the player via the existing deep link. - [ ] List server-known (not-yet-downloaded) episodes; download audio on play. - [ ] (Variant B only) Background-push handler + background `URLSession` download. ## Tradeoff to accept Server-driven means the **backend takes on per-user episode state** (catalog + device registry), whereas today the client owns everything locally in `PodcastIndex` keyed by URL hash. That's a real backend scope increase — but it also enables **multi-device sync** for free. ## Irreducible client pieces (Apple requirements) - The APNs **device-token handshake** cannot move to the server. - Notifications require user permission; fall back to the in-app "Generating…" banner when denied. ## Relationship to shipped work - Builds on background generation (#2) and share-extension auto-generate (#3): the share extension enqueues server-side, the backend generates and pushes. - Badge/clear coordinates with the unread-count item in #6.
admin changed title from Episode-ready notification + true background generation (BGTask) to Episode-ready push notification (server-driven, no client polling/BGTask) 2026-07-01 17:43:55 +00:00
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: admin/linkding-ios#5