Search code examples
node.jsfirebasereact-nativearchitecture

I need to create a notification service but can't decide the architecture


I am creating a service in which i am asking user about a particular time of the day for example a user selects 7:15 PM , then user will be notified at this particular time everyday. Each user can select any time of the day and the time is stored in a NoSQL DB along with other user details, Now the problem is i need to scan database each minute to find out every user's specified time which is not ideal and very expensive. I cannot think of any other architecture,i cannot use local notifications of the phones, notifications has to be remote i.e. sent from a backend server.

Thanks for any help you could offer.


Solution

  • If you have a system where you can keep data in memory, you can implement a priority queue quite cheaply - such as what I've shown for Firebase Realtime Database in this example: https://stackblitz.com/edit/ttl

    The key points for such a structure are:

    • You keep all tasks in an ordered list, and then set a timer only for the first task in the list.
    • If the timer expires, you execute the task and delete it.
    • If an item comes in your add it in the right spot in the list.
    • Either of the last two points can/will lead to a new first item in the list, so you set the timer for this new first item.

    The main code is:

    function checkFirstAndTrigger() {
      clearTimeout(timer); // clear any potentially pending timer, since we may have been interrupted
      if (first && first.exists()) {
        const deltaMs = first.child(ttlProp).val() - Date.now();
        // if the item has to be triggered now (or before now), do so
        if (deltaMs <= 0) {
          first.ref.remove(); // this will retrigger the child_added listener below
        }
        else {
          console.log(`Waiting for ${deltaMs}ms`)
          // we were triggered prematurely, wait until it's our time (or until we're interrupted)
          timer = setTimeout(checkFirstAndTrigger, deltaMs);
        }
      }
    }
    
    // Set a trigger for the first item/task in the list. This gets triggered 
    // when a new first item is added, or when the current first item gets deleted.
    queue.orderByChild(ttlProp).limitToFirst(1).on('child_added', (snapshot) => {
      // a new item became the first in the queue, either because a new one was added or because the previous first got deleted
      first = snapshot;
      checkFirstAndTrigger();
    });