Is there a way for me to connect to my Firebase Realtime Database using my Firebase Cloud Function?

My current challenge involves retrieving the list of users in my database when a specific field is updated. I aim to modify the scores of players based on the structure outlined below:

The Realtime Database Schema:

{
    "users": {
         "user1": {
             "name": "abc",
             "game": {
                   "gameId": "id1"
                   "score": 123
             }
         },
         "user2": {
             "name": "def",
             "game": {
                   "gameId": "id1"
                   "score": 456
             }
         },
         "user3": {
             "name": "ghi",
             "game": {
                   "gameId": "id1"
                   "score": 789
             }
         }

    },

    "leaderboard": {
        "game": {
               "gameId": "id1", 
               "players": [
                   "playerName": ...
                   "score": ...
               ]
    }
}

Whenever a user updates their score, I trigger OnValueUpdate() successfully and access the necessary data before and after the update. However, I struggle to retrieve the full list of users for comparison and leaderboard updates. Despite trying various approaches, all queries return null.

Here are some attempts:


const admin = require('firebase-admin');
admin.initalizeApp();

export const func = OnValueUpdate(
    {
       ref: '/users/{userId}/games/{gameId}/score';
    },
    (event) => {
       const db = admin.database();


       db.ref('/users/{userId}')
         .get()
         .then( (result) => {
             console.log(result.val());  // prints null
         });
    }
)

I also experimented with:

const functions = require('firebase-functions');

export const func ) OnValueUpdate(
    {
       ref: '/users/{userId}/games/{gameId}/score';
    },
    (event) => {
       const db = functions.database 

       // and then access the ref with db.ref...
    }
)

Yet, the results remain null. Any suggestions on what else I could try?


While utilizing Firebase emulators locally, everything functions as expected.

Answer №1

Your inquiry includes the following comment:

[When] I work locally with the Firebase emulators, everything works perfectly

The smooth operation while working locally with the Firebase emulators is likely due to the fact that these emulators do not replicate the strict Cloud Functions lifecycle. In a typical scenario, when a function is executed, it runs the code, waits for completion, and then promptly hibernates or even shuts down. Hibernation severely throttles the function, leading to potential blocking of some API requests. Failure to inform the Cloud Functions host properly that your function is awaiting an asynchronous task's completion may result in premature hibernation/termination before the task finishes.

In your recent attempts, you initiate a task ("get data at /users/{userId}, then log the output") but fail to return the Promise to the Cloud Function host. Additionally, failing to substitute {userId} with the actual userId value results in querying a non-existent document location. These issues likely cause the function to hibernate/terminate before the task commences, fetching data from a wrong (non-existent) location, hence encountering the observed issues.

const admin = require('firebase-admin');
const { logger } = require("firebase-functions");
const { onValueUpdated } = require("firebase-functions/v2/database");

admin.initializeApp();

export const func = onValueUpdated(
    {
       ref: '/users/{userId}/games/{gameId}/score';
    },
    (event) => {
       const db = admin.database();
       const { userId, gameId } = event.params; // fetches userId and gameId from the given path

       return db.ref(`/users/${userId}`) 
         .get()
         .then((result) => {
             logger.log(result.val()); 
         });
    }
)

The above function, though operational, does not align with the database structure provided in your query. For it to work, the database needs to be structured as follows:

{
  "users": {
     "user1": {
       "name": "abc",
       "games": {
         "id1": {
           "gameId": "id1"
           "score": 123
         }
       }
     },
     ...
 },
  "leaderboard": { ... }
}

Avoid utilizing arrays in the Firebase Realtime Database. Though dated, this blog post explains the rationale well. Storing entries into array-like objects using unique IDs simplifies handling logic significantly. For instance, adding/updating/removing a player's score involves operations similar to the following (where gamePlayersRef is

ref(db, `/leaderboard/${gameId}/players`)
):

  • Player joins a game -
    set(child(gamePlayersRef, userId), { playerName: "newPlayer", score: 0 })
  • Player leaves a game -
    remove(child(gamePlayersRef, userId))
  • Player achieves a new score -
    update(child(gamePlayersRef, `${userId}/score`), 100)
{
  "leaderboard": {
    "id1": {
      "gameId": "id1", 
...

Importantly, updating a user's display name across all games simultaneously becomes easy by leveraging unique IDs. This task would prove much more complex if arrays were used.

const userId = "...";
const playerData = (await get(ref(db, `/users/${userId}`))).val();

const newPlayerName = "...";
const arrPlayerGameIds = Object.keys(playerData.games);

const batchUpdateData = {};
batchUpdateData[`/users/${userId}/name`] = newPlayerName;
arrPlayerGameIds.forEach(gameId => {
  const playerNameInGamePath = `/leaderboard/${gameId}/players/${userId}/playerName`;
  batchUpdateData[playerNameInGamePath] = newPlayerName;
});

return update(ref(db), batchUpdateData);

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

Here's a step-by-step guide on how to parse JSON information in JavaScript when it's formatted as key-value

I need to parse the JSON data in JavaScript. The data consists of key-value pairs. Data looks like this: {09/02/2014 15:36:25=[33.82, 33.42, 40.83], 08/11/2014 16:25:15=[36.6, 33.42, 40.45], 07/30/2014 08:43:57=[0.0, 0.0, 0.0], 08/12/2014 22:00:52=[77.99 ...

Mouse event listener includes timeout function that updates a global variable

I'm currently working on a function that gets activated by a mouse click, but there's a 10-second cooldown period using setTimeout() before it can be triggered again. However, after the timeout, my variable doesn't get set to the correct boo ...

implement a discount and waive tax computation specifically for Canadian customers

I have encountered a problem while developing a POS application for a client in Canada. My issue lies in the tax calculation process, where I am unsure how to handle discounts and tax exemptions properly. Here is the scenario: I have 2 items - item 1 price ...

Can you explain the purpose of prevState within the setState method of a functional component?

When returning the updated previous state within a setState method retrieved from the useState hook, it appears that the state remains unchanged. To demonstrate this behavior, consider running the following code snippet: function App(){ const [state, ...

Is it possible to target an element using the data-testid attribute with #?

Is there a shortcut for selecting elements with the data-testid attribute in playwright-typescript? await page.locator("[data-testid='YourTestId']").click() I attempted to use await page.locator("[data-testid='YourData-testid ...

Generate a pre-signed URL for an AWS S3 bucket object using Typescript in NextJS, allowing for easy file downloads on the client-side using @aws-sdk/S3Client

In the utilization of v3 of the S3Client, it appears that all existing examples are based on the old aws-sdk package. The goal is for the client (browser) to access a file from S3 without revealing the key from the backend. From my research, it seems tha ...

The delay function in RxJS allows for waiting to return a value until a specific condition is met within a stream and

Currently, I am facing an issue with a method in my application that triggers a server request. This method has access to a stream from the redux-store and needs to execute a callback only when the result of the request is found in the mentioned stream. Th ...

I attempted to publish my React application using gh-pages and encountered the following error: "The argument for 'file' must be a string. However, it was received as undefined."

I encountered an issue while attempting to deploy my React application with gh-pages. The error message I'm facing states: "The 'file' argument must be of type string. Received type undefined." Initially, I suspected that the problem was wi ...

Refresh a doughnut chart in real-time using NG2Charts

Currently, I am in the process of developing a macronutrient calculator as part of a project. The idea is to have a form where users can input values, and a corresponding doughnut chart will display with initial values set at 0. However, upon clicking the ...

How to Retrieve an Array from a Promise Using Angular 4 and Typescript

I am encountering difficulties when trying to store data from a returned promise. To verify that the desired value has been returned, I log it in this manner: private fetchData() { this._movieFranchiseService.getHighestGrossingFilmFranchises() ...

Angular 2 - Utilizing a Shared Service for Subscriptions

After referencing this guide: Parent and children communicate via a service I have decided to utilize a shared service instead of EventEmitter. The reason being that EventEmitter only facilitates communication between parent and child components, which do ...

Determine the number of distinct elements in fields using MongoDB aggregation

After executing my query, I received documents in the following format: { _id: '48nmqsyxmswpkkded2ac_331fabf34fcd3935', actions: { sales: { pixel: [Object] } }, date: Sun Jul 27 2014 00:00:00 GMT-0400 (EDT), client: '48nmqsyxmswpkkded ...

In React and Node Js, the setState function will return a value of NULL

My Node Js API utilizes a find function to retrieve data from the database, which works flawlessly and returns the results. However, when I pass this data into setState using React and Axios, it ends up returning null. Below is my API's find() functi ...

An issue with the Pipe searchByType is resulting in an error stating that the property 'type' is not found on the type 'unknown'

I keep encountering a range of errors like roperty does not exist on type 'unknown' after running the command ionic build --prod --release src/app/pages/top-media/top-media.page.ts:18:16 18 templateUrl: './top-media.page.html', ...

Attempting to revert the imported module back to its initial/default mock configuration

When working on my test file, I utilize a folder named mocks which contains various exported functions. Most of the time, I rely on the mocks folder to perform all necessary tasks. However, there is one scenario where I need to adjust the return value to a ...

HighCharts.js - Customizing Label Colors Dynamically

Can the label color change along with gauge color changes? You can view my js fiddle here to see the current setup and the desired requirement: http://jsfiddle.net/e76o9otk/735/ dataLabels: { format: '<div style="margin-top: -15.5px; ...

What is the best way to have the sidebar of a webpage slide out over the main body content that is being displayed?

Issue Summary I am experiencing an issue with the positioning of my sidebar, which is initially located 66% offscreen using -translate-x-2/3. The sidebar is meant to be pulled into view onmouseover, however, the main body content remains stuck in place. I ...

Exploring Enum properties within an angular js select drop down

I am working with an enum in Java that looks like this: public enum myEnum{ enum1("enumDisplayVal1"), enum2("enumDisplayVal2") myEnum(String displayValue) { this.displayValue = displayValue;} private String displayValue; public String getDisp ...

Create a way to allow users to download html2canvas with a customized filename

I have a div where I want to use html2canvas to save a PNG file of its content. The issue is that the name of the saved file is static in my code and does not change unless I manually edit it. Is there a way to dynamically set the filename based on user i ...

What is preventing me from accessing these attributes using "${array[a].name}"?

What is preventing me from reading the properties using ${ array[a].name } with For Of loop? I created an example with an array of objects to help diagnose the problem. const movies = [{ title: "Shrek", year: 2001 }, { title: "Shrek 2", ...