josephluck / urban-jungle

🌱 Simple reminders to help you care for your plants.
BSD 3-Clause "New" or "Revised" License
3 stars 0 forks source link

Store & handle push notification errors #9

Open josephluck opened 4 years ago

josephluck commented 4 years ago

Use Expo's push tickets & receipts to enqueue retries for each failed push ticket.

Use cases

Workflow:

Send some push notifications assuming everything's okay:

Retry and handle errors at intervals (30 mins, 1 hour?):

Notes

Alternative architecture

Event-driven using a queue persisted in Firebase with cloud functions. Pseudo API for this:

type PushyOptions = {
  /**
   * Name of the firebase table to use to persist event state
   */
  tableName: 'push-notifications-events',

  /**
   * Number of times to retry sending before stopping.
   */  
  retryAttempts: 3,

  /**
   * Callback fired when any push attempt contains failures.
   */
  onAttemptFail: (failures, req, res) => {},

  /**
   * Callback fired when any push attempt is successful.
   */
  onAttemptSuccess: (successes, req, res) => {},

  /**
   * Specific event handler callback for when an entire job has failed to be
   * sent.
   * NB: can be used to remove user's PN token
   */
  onJobFail: (failures, req, res) => {},

  /**
   * Specific event handler callback for when an entire job has successfully
   * been sent.
   */
  onJobSuccess: (successes, req, res) => {},

  /**
   * Low level callback fired when any event handling starts. 
   * Can be used to intercept the event to modify it before it's handled.
   * Must return the event.
   */
  onEventStarted: (event) => {},

  /**
   * Low level callback fired when any event has been handled. 
   * Can be used to log or fire other events.
   * Must return void
   */
  onEventFinished: (event) => {},
}

type PushyAPI = {
  /**
   * Creates a push notification job and sends the initial batch of
   * notifications.
   */
  push: (notifications: any[]) => Promise<void>;

  /**
   * Method to retry any unsuccessful push notifications. If a job is already at
   * the maximum retry count, it will dispatch a failed event
   */
  retry: () => Promise<void>;
}

/**
 * Factory function to make an instance of Pushy
 */
type Pushy = (options: PushyOptions) => PushyAPI