How to schedule FCM notifications at a specific time using Firebase cloud functions

I need help figuring out how to schedule a Firebase Cloud Messaging notification to be sent at a specific time using cloud functions.

Currently, the notification is triggered whenever a new document is created in a Firestore database, with the scheduled time for the notification being based on a timestamp within that document.

I've explored setting up a cron job, but I'm struggling to find a way to ensure that the notification is only sent once, rather than daily or weekly. I also considered using a setTimeout function, but it's not ideal due to the limitations on invocation time.

Given my limited experience with TypeScript and Firebase Cloud Functions, I would greatly appreciate any suggestions or ideas on how best to approach this!

Answer №1

If you are in need of a solution to execute code at a specific time, such as setting up scheduled jobs, look no further than the scheduler library known as node-schedule. This library can be seamlessly integrated into your firebase cloud function to efficiently manage and automate tasks. While it does add a level of dependency, its functionality proves to be quite beneficial in streamlining processes. In order to maintain a stateless firebase function, the alternate option outlined below must be considered. Take a closer look at the practical example provided using this library and a cloud function.

1. Utilizing node-schedule

const functions = require('firebase-functions');
var schedule = require('node-schedule');

exports.scheduleSampleJob = functions.https.onRequest((req , res) => {
    /*
        For instance, if you want a specific function to run at 5:30am on December 
        21, 2012. Remember - when working with JavaScript - 0 represents January and 11 represents December.
    */
    var date = new Date(2012, 11, 21, 5, 30, 0);  

    var j = schedule.scheduleJob(date, function(){
        console.log('The Task has been executed');
    });
    return res.status(200).send(`Task has been successfully scheduled`);
});

Note: Ensure that this function is only called once to avoid multiple job creations.

2. Implementing Firebase Function Pub/Sub

While Firebase provides support for job scheduling through Pub/Sub, it is reserved for those on the Blaze plan, and transcends the limitations of the Free or Flame plans. The usage of Pub/Sub is detailed in the official Docs.

To schedule functions to run at specified times, utilize

functions.pubsub.schedule().onRun()
. This convenient method establishes a Google Cloud Pub/Sub topic, employing Google's Cloud Scheduler to initiate events on said topic, ensuring precise execution schedules.

exports.scheduledFunctionCrontab = functions.pubsub.schedule('5 11 * * *')
  .timeZone('America/New_York') // Users can select timezone - default is America/Los_Angeles
  .onRun((context) => {
  console.log('This will run daily at 11:05 AM Eastern!');
  return null;
});

3. Exploring OneSignal Push Notification

To simplify manual scheduling, consider utilizing OneSignal as an alternative option. Offering comprehensive push notification services for a variety of platforms including Web, IOS, Android, and more, OneSignal integrates seamlessly with firebase cloud messaging. Additionally, it supports REST-api functionalities, allowing for easy scheduling of push notifications through built-in delivery features. Instead of developing a custom solution, exploring the capabilities of OneSignal could prove to be a valuable choice. By creating a firebase cloud function that directly interfaces with the OneSignal REST api, push notifications can be scheduled efficiently.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The Strapi plugin seems to be encountering an issue as the API is not reachable, leading to a

In an attempt to create a custom API in Strapi backend, I developed a plugin called "test" for testing purposes. However, when trying to access the test response in Postman, it displays a 404 error stating that it is not accessible. Let me provide you wit ...

Is it possible to apply JavaScript object destructuring but make changes to certain values before assigning them to a new object?

After receiving movie data from an api, I am currently manually creating a new object with a subset of properties and modified values. Is there a more efficient way to achieve this using javascript/typescript object destructuring syntax? I specifically wa ...

Preserve the custom hook's return value in the component's state

I am currently facing a challenge in saving a value obtained from a custom hook, which fetches data from the server, into the state of a functional component using useState. This is necessary because I anticipate changes to this value, requiring a rerender ...

Exploring the intricacies of the let and const modifiers in ngFor loops

I encountered some unexpected behavior with the const keyword while using it in an Angular 2 *ngFor loop. Let's consider the following base code: interface Foo { name: string; list: string[]; } @Component({ ... }) class FooComponent() { ...

Troubleshooting issue with TypeScript: Union types not functioning correctly when mapping object values

When it comes to mapping object values with all primitive types, the process is quite straightforward: type ObjectOf<T> = { [k: string]: T }; type MapObj<Obj extends ObjectOf<any>> = { [K in keyof Obj]: Obj[K] extends string ? Obj[K] : ...

Using the useRef hook to target a particular input element for focus among a group of multiple inputs

I'm currently working with React and facing an issue where the child components lose focus on input fields every time they are re-rendered within the parent component. I update some state when the input is changed, but the focus is lost in the process ...

Typescript code encountering unexpected behavior with Array.includes()

Below is a snippet of TypeScript code from my NextJS application: const holeSet:any[] = []; ..... let xx = 1, yy = 2; holeSet.push({x:xx,y:yy}); xx = 3; yy = 4; holeSet.push({x:xx,y:yy}); holeSet.map((e) => { console.log("element ::"+JSON ...

A guide on creating a LoopBack 4 REST API to fetch data from a MySQL database

I am currently diving into the world of Loopback 4. I have successfully created a model, repository, and datasource in connection with MySQL. This has enabled me to retrieve results from http://127.0.0.1:3000/myapi/{id}. In my initial setup, obtaining dat ...

Ensure Jest returns the accurate file paths for images in a TypeScript and React environment

I'm currently developing a React application and I have come across an issue with importing images. My usual method of importing images is as follows: import image1Src from 'assets/img1.png"; For testing purposes, I need to be able to make ...

The .ts source file is mysteriously missing from the development tool's view after being deployed

When I work locally, I can see the .ts source files, but once I deploy them, they are not visible in any environment. Despite setting my sourcemap to true and configuring browserTargets for serve, it still doesn't work. Can someone help with this issu ...

Create a regulation that permits access solely to individuals currently logged into the system database

I am a beginner when it comes to working with Firebase and its rules. My goal is to implement a system where each user in the Firestore database has a boolean field called isOnline, as shown in the image I have attached. https://i.stack.imgur.com/7M3dc.pn ...

Unable to execute a join operation in TypeScript

I have an array of objects listed below var exampleArray = [{ "isAvailable": true, "receipent": [{ "id": "a6aedf0c34", "receipentName": "ABC" }, { "id": "a6aedbc34" ...

Is there a way to verify useFormik functionality while the form is being submitted?

Below is the implementation of the Form component which utilizes the useFormik hook. While the component fulfills all my requirements, I encounter challenges when it comes to testing, especially during form submission. Form.tsx import { TextField, But ...

Open new tab for Angular OAuth2 OIDC login process

Currently, I am incorporating the authorization code flow using angular-oauth2-oidc in my Angular application. It is a fairly straightforward process. However, I would like to have the ability for the login flow to open in a new tab when the login button ...

An error should not be thrown if the object is potentially 'undefined', as there is a filter in place from rxjs

During my service refactoring process, I encountered a frustrating issue. The API I am working with returns an object with various optional properties. To work with these properties, I need to check if they are undefined or not using an if statement, other ...

What is the best way to modify an object within a pure function in JavaScript?

Currently, I am exploring different strategies to ensure that a function remains pure while depending on object updates. Would creating a deep copy be the only solution? I understand that questions regarding object copying are quite common here. However, ...

Leveraging Expose in combination with class-transformer

I have a simple objective in mind: I need to convert the name of one property on my response DTO. refund-order.response.dto.ts export class RefundOrderResponseDto { @Expose({ name: 'order_reference' }) orderReference: string; } What I w ...

Tips for implementing a real-time search feature in Angular

I require assistance. I am attempting to perform a live search using the following code: when text is entered into an input, I want my targetListOptions array, which is used in a select dropdown, to update accordingly. The code runs without errors, but not ...

What is the best way to combine two arrays and generate a new array that includes only unique values, similar to a Union

Here are two arrays that I have: X = [ { "id": "123a", "month": 5, "markCount": 75 }, { "id": "123b", "month": 6, "markCount": 85 ...

What is the best way to convert an HTML table into an array of objects?

In my Angular Protractor end-to-end (e2e) tests, I need to perform assertions on an HTML fragment similar to the following: <table> <thead> <tr> <th>Name</th> <th>Age</th> ...