Add the held summary that resumes one user's mobile pushes

What does this MR do and why?

Adds Gitlab::MobilePush::HeldSummary, the object that takes one user off the working hours wake-up list and resumes their pushes. It is the "each held summary resumes itself and returns an outcome" shape from the review of the original merge request.

resume re-asks every check the per-todo path made hours ago, then acts, and answers with one symbol:

Outcome When
:skipped_user_inactive, :skipped_no_subscription the recipient checks fail by now
:skipped_schedule_disabled the switch was turned off overnight
:skipped_nothing_pending no to-do is pending any more, so a badge of 0 would point at nothing
:rescheduled the window has closed again (a narrower window or a dropped weekday), or every push failed; the user goes back on the list for the next window start
:dropped_no_window the window is closed and no next opening can be computed
:delivered at least one phone received the generic "You have new to-dos" summary with the pending badge
:evicted, :skipped_not_configured a dead token or missing APNs credentials; not retried

Gitlab::MobilePush::Sender#deliver gains a delivered_as: label, so a summary can be told apart from a per-todo push on mobile_push_notifications_total.

Nothing calls it yet; the cron worker and its service follow in the next MR.

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 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 (this MR) 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

  1. Hold a user as described in the MR below this one (C1): closed window, one to-do assigned, user on the wake-up list.

  2. Still outside the window, in a Rails console:

    user = User.find_by!(username: 'root')
    Gitlab::MobilePush::HeldSummary.new(user, sender: Gitlab::MobilePush::Sender.new).resume # => :rescheduled
  3. Widen the window to cover the current time and run it again: one push arrives, "You have new to-dos", with the pending badge, and the call returns :delivered.

MR acceptance checklist

Evaluated against the MR acceptance checklist.

🤖 Generated with Claude Code

Edited by Marcel van Remmerden

Merge request reports

Loading
Loading