简体   繁体   中英

Data not saved into Firestore through scheduler function with Firebase Cloud Functions

I'm trying to create APIs with Firebase Cloud Functions so as to build a system to make what's collected through the APIs and other third-party APIs routinely saved into Firestore. Here is my source code index.js at this moment, and I'd like to control all the processes in this one file.

/functions/index.js

const firebaseAdmin = require("firebase-admin");
const firebaseFunctions = require("firebase-functions");
firebaseAdmin.initializeApp();
const fireStore = firebaseAdmin.firestore();

const express = require("express");
const axios = require("axios");
const cors = require("cors");

const serviceToken = "SERVICE-TOKEN";
const serviceBaseUrl = "https://api.service.com/";

const app = express();
app.use(cors());

const getAllExamples = async () => {
    var url = `${serviceBaseUrl}/examples?token=${serviceToken}`;
    var config = {
        method: "get",
        url: url,
        headers: {}
    };
    axios(config).then((res) => {
        console.log("Data saved!");
        return res.data;
    }).catch((err) => {
        console.log("Data not saved: ", err);
        return err;
    });
}

const setExample = async (documentId, dataObject) => {
    fireStore.collection("examples").doc(documentId).set(dataObject).then(() => {
        console.log("Document written!");
    }).catch((err) => {
        console.log("Document not written: ", err);
    });
}

app.get("/getAllExamples", (req, res) => {
    getAllExamples().then((response) => res.send(response));
});

app.put("/setExample", (req, res) => {
    setExample(req.params.documentId).then((response) => res.send(response));
});

const api = firebaseFunctions.https.onRequest(app);
module.exports = { api };

module.exports.updateExamplesRoutinely = firebaseFunctions.pubsub.schedule("0 0 * * *").timeZone("America/Los_Angeles").onRun((context) => {
    var examples = getAllExamples();
    for(var i = 0; i < examples.length; i++) {
        var example = examples[i];
        var exampleId = example["id"];
        if(exampleId && example) setExample(exampleId, example);
    }
});

As a result, updateExamplesRoutinely is properly triggered every 00:00 in PST, but NO data is stored in Firebase and NO console logs about Firebase data updates and found in Cloud Functions Logs.

Output data collected through https://api.service.com/ is something like this below:

[
  {
    id: "BB345",
    name: "Tim Gordon",
    age: 24,
    email: "tgordon@yahoo.com"
  },
  {
    id: "CC098",
    name: "John Doe",
    age: 28,
    email: "john.doe@gmail.com"
  },
  {
    id: "DD777",
    name: "Adam Smith",
    age: 39,
    email: "adamsmith@outlook.com"
  },
  ...
]

Simply, these 3 problems are what I would like to get resolved.

  1. How should I call APIs defined in index.js through Cloud Functions' scheduler?
  2. How should I save data into Firestore inside Cloud Functions' scheduler?
  3. What's the best "async" way to call the third-party APIs, wait and collect the results, and pass them to other events or functions?

How should I call APIs defined in index.js through Cloud Functions' scheduler?

I guess you want to say "How should I call the methods defined in index.js". There is no reason to call the APIs exposed by the Cloud Funtion from this same Cloud Function.

So to call the methods, do as follows:

const getAllExamples = async () => {
    var url = `${serviceBaseUrl}/examples?token=${serviceToken}`;
    var config = {
        method: "get",
        url: url,
        headers: {}
    };
    return axios(config).then((res) => {   // !!! note the return here
        console.log("Data saved!");
        return res.data;
    }).catch((err) => {
        console.log("Data not saved: ", err);
        return err;
    });
}

const setExample = async (documentId, dataObject) => {
    // !!! note the return on next line
    return fireStore.collection("examples").doc(documentId).set(dataObject).then(() => {
        console.log("Document written!");
    }).catch((err) => {
        console.log("Document not written: ", err);
    });
}

module.exports.updateExamplesRoutinely = firebaseFunctions.pubsub.schedule("0 0 * * *").timeZone("America/Los_Angeles").onRun(async (context) => {
    const examples = await getAllExamples();

    const promises = [];
    for(var i = 0; i < examples.length; i++) {
        var example = examples[i];
        var exampleId = example["id"];
        if(exampleId && example) promises.push(setExample(exampleId, example));
    }
    return Promise.all(promises);
    // See how we return the promise returned by Promise.all
    // !!! This is IMPORTANT, see https://firebase.google.com/docs/functions/terminate-functions 

});

How should I save data into Firestore inside Cloud Functions' scheduler?

The above code will save the data in Firestore. You actually want to execute a variable number of call to the setExample() method, you need to use Promise.all() as shown above. This way, setExample() will write to Firestore for each example .

What's the best "async" way to call the third-party APIs, wait and collect the results, and pass them to other events or functions?

See how we adapt the updateExamplesRoutinely Cloud Function: we use the async and await keywords.

module.exports.updateExamplesRoutinely = firebaseFunctions.pubsub.schedule("0 0 * * *").timeZone("America/Los_Angeles").onRun(async (context) => {
    const examples = await getAllExamples();
    // ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM