trungitdn
trungitdn

Reputation: 11

Firebase Cloud Funtion call trigger mutiple time

I using firebase and create trigger listen any change from student document. If student document change, i push any change to rest api. But my function call mutiple time.

Bellow is my function :

exports.triggerTimeStudent= functions.firestore
    .document('users/{userId}/class/{classId}/students/{studentId}')
    .onUpdate( (change, context) => {
        const newValue = change.after.data();
        const previousValue = change.before.data();
        const {update_at: afterStatus} = newValue;
        const {update_at: beforeStatus} = previousValue;
        const {name: name} = newValue;
        if (afterStatus !== beforeStatus) {
                try {

                    var data = {
                        "student_name": name,
                    };
                    console.log(data);
                    console.log("Inside Rest API");
                    return rest.post("https://example.com/api/v1/student/add-by-name", {
                        ...studentServiceRestOption, ...{
                            body:  JSON.stringify(data)
                        }
                    });

                } catch (error) {
                    return res
                        .status(HttpStatus.INTERNAL_SERVER_ERROR)
                        .send(buildError({
                            code: errorCode.SYSTEM_ERROR,
                            message: error.message,
                        }))
                }

        }

I can't know why function call mutiple time. I want call only time. My function incorrect. Please help

Upvotes: 0

Views: 45

Answers (1)

samthecodingman
samthecodingman

Reputation: 26306

By design, Cloud Functions may be called multiple times. It is up to you to ensure that your functions can handle being retried.

However, your error likely stems from the value of the update_at key. If this key's value is an object, the === and !== operands aren't going to produce the correct result. You will need to check the object for an "isEqual" or "equals" method, or use a third-party solution such as _.isEqual.

Below, I have refactored your code for performance and ease-of-use. I could not identify the rest object you were using for the API call, so I have substituted it for node-fetch.

const fetch = require("node-fetch"); // see https://www.npmjs.com/package/node-fetch

// for object equality tests
// const isEqual = require("lodash.isequal");

const STUDENT_SERVICE_DEFAULT_OPTIONS = {
  method: "post",
  headers: {
    "Content-Type": "application/json"
  }
}

exports.triggerTimeStudent= functions.firestore
    .document("users/{userId}/class/{classId}/students/{studentId}")
    .onUpdate( (change, context) => {
        const beforeStatus = change.before.get("update_at"); // accessed directly for performance
        const afterStatus = change.after.get("update_at");

        // If beforeStatus and afterStatus are
        //  - string, boolean, int, etc.: use beforeStatus === afterStatus
        //  - firestore.Timestamp objects: use beforeStatus.isEqual(afterStatus)
        //  - custom objects: use isEqual(beforeStatus, afterStatus) from lodash/underscore packages

        if (beforeStatus === afterStatus) {
          console.log("Status unmodified. Ignored change.");
          return;
        }

        const data = {
          student_name: change.after.get("name")
        }

        console.log("Making API call...", { data });

        const fetchOptions = {
          ...STUDENT_SERVICE_DEFAULT_OPTIONS,
          body: JSON.stringify(data)
        }

        return fetch("https://example.com/api/v1/student/add-by-name", fetchOptions)
          .then(response => {
            if (!response.ok) { // see "Handling client and server errors" in "node-fetch" docs
              throw new Error("Unexpected API response: " + response.statusText);
            }

            console.log("Successfully added student!");
          })
          .catch(error => console.error("Failed to add student!", { error, fetchOptions }));
    });

Note: You can view the logged messages from Cloud Functions in the Firebase console.

Upvotes: 1

Related Questions