skip to Main Content

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.

2

Answers


  1. Here’s one idea. You can keep a sorted list of all upcoming notifications for all users (perhaps those to fire in the next hour). Depending on the scale of your system, you may be able to keep this sorted list of the next hour’s notifications in memory.

    Then, once a minute, you just look at the start of the list to see which notifications are ready to fire. You only have to search the sorted list until you find the first notification that is not ready.

    Then, depending upon how much time your sorted list in memory covers, you update the sorted list from the database to pull in new upcoming events. If your list contains the next hour’s worth of events, then you only need to update the list once an hour to get the next hour’s worth of events. In this way, you don’t have to be querying the database very often.

    Then, you need to also create some utility functions that capture every place you might add, remove or modify a future event so you can check if that event needs to be added or removed from the next hour’s in-memory list. So, instead of directly modifying the database, you always go through these utility functions so you can separately maintain your sorted next hour list anytime the database is updated. Of course, the check on a database mod will have nothing extra to do if the event it is modifying is further away from now than the next hour.

    Login or Signup to reply.
  2. If you have a system where you can 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();
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search