Extract the mobile push recipient checks and the APNs fan-out

What does this MR do and why?

A refactor of code that already ships, with no behavior change and no database change.

Before: Notifications::MobilePush::SendTodoNotificationsService is the only place that knows which checks a push asks before a send (user active, per-user flag on, phones registered) and how to fan one payload out to every phone, drop a dead token and count the result.

After: two small objects under lib/gitlab/mobile_push/ own that, and the service uses them:

  • Gitlab::MobilePush::Recipient wraps a user: skip_reason returns the same :skipped_* symbols the service recorded before, or nil, and subscriptions loads the phones once.
  • Gitlab::MobilePush::Sender holds the ApnsClient for one job, pushes the payload yielded per phone, destroys a dead token and increments mobile_push_notifications_total with the same labels as before (SEND_RESULT_LABELS moved to Sender::RESULT_LABELS). The client is opened on the first send only, so a job that sends nothing opens no connection.

Why: the working hours summary, further up this stack, needs exactly these checks and this fan-out. Sharing them keeps the two senders from drifting apart.

The existing service spec passes unchanged, which is the point.

References

Split from !260440 (closed), as agreed with the reviewer there: seven merge requests of 200 to 300 lines each, cut where the code does not reference the other parts. Each one targets its parent branch and is retargeted to master when the parent merges.

Merge request Targets
A (this MR) Extract the mobile push recipient checks and the APNs fan-out master
B1 Add a value object for mobile push working hours A
B2 Store mobile push working hours on the user preference B1
C1 Hold mobile pushes for to-dos outside working hours B2
C2a Add the held summary that resumes one user's mobile pushes C1
C2b Send the mobile push summaries when working hours begin C2a
D Add the mobile push working hours to the user preferences API C2b

Merge order is the chain order: A, B1, B2, C1, C2a, C2b, then D. D is the switch: it targets C2b, so the API cannot reach master before the server can hold a push and send its summary. Any other order would open a window on GitLab.com where users who enabled the schedule have their pushes held but not summarized until C2b deploys.

Screenshots or screen recordings

No UI changes.

How to set up and validate locally

Nothing new to see. To confirm nothing changed:

  1. With a registered device (see doc/api/mobile_push_subscriptions.md) and the mobile_push_notifications_dispatch and mobile_push_notifications feature flags on for your user, assign yourself an issue from a second user.
  2. The push arrives as before, and log/sidekiq.log shows Todos::PushNotificationWorker with the same results and apns_results keys as on master.

MR acceptance checklist

Evaluated against the MR acceptance checklist.

🤖 Generated with Claude Code

Edited by Marcel van Remmerden

Merge request reports

Loading
Loading