Mobile notifications for iOS (#210)

* mobile: wire notification registration and listener

* implement backend components for push notifications

* refactor: agentic comment cleanup

* docs: use proper module name for particle processor

* set required env variables for push notifications

* bump version

* fix: always upsert push token on mobile start

* Revert "fix: always upsert push token on mobile start"

This reverts commit 90ff18a788.

* send push notifications regardless of online status
This commit was merged in pull request #210.
This commit is contained in:
Arjun Patel
2026-05-18 12:44:31 -07:00
committed by GitHub
parent a564ea819b
commit d262f734f0
61 changed files with 1682 additions and 531 deletions
+7 -15
View File
@@ -1,13 +1,7 @@
// memberreconciler is a one-shot job (also safe to run on a cron) that makes
// the Firestore membership mirror (humans/{humanId}.networks) match the
// authoritative Postgres network_members table.
//
// Run on a cron to heal any drift from a dropped mirror
// write in network.Service.
//
// The reconciler reads the current Firestore state and only writes humans
// whose mirrored networks differ from Postgres. Writes cost ~3x reads, and in
// steady state drift is rare, so read-first keeps the cron nearly free.
// memberreconciler reconciles the Firestore membership mirror
// (humans/{humanId}.networks) against the authoritative Postgres
// network_members table. Safe to run on a cron — only humans whose mirrored
// set differs from Postgres are written, so a steady-state run is nearly free.
package main
import (
@@ -98,8 +92,7 @@ func reconcile(
return written, scanned, nil
}
// snapshotMirror streams the humans collection once and returns a map of
// humanId -> current networks array. One iterator, N billed reads.
// One iterator, N billed reads — returns humanId → mirrored networks.
func snapshotMirror(ctx context.Context, fs *firestore.Client) (map[string][]string, error) {
out := map[string][]string{}
iter := fs.Collection("humans").Documents(ctx)
@@ -124,9 +117,8 @@ func snapshotMirror(ctx context.Context, fs *firestore.Client) (map[string][]str
return out, nil
}
// sameSet reports whether a and b contain the same elements, ignoring order
// and duplicates. Firestore array ops don't preserve order, so set equality is
// the right comparison for the networks array.
// Set equality (order- and duplicate-insensitive); Firestore array ops don't
// preserve order.
func sameSet(a, b []string) bool {
if len(a) == 0 && len(b) == 0 {
return true