计划的 Firebase 功能 - 不写入 Firestore

Posted

技术标签:

【中文标题】计划的 Firebase 功能 - 不写入 Firestore【英文标题】:Scheduled Firebase Function - No writing to Firestore 【发布时间】:2021-10-01 08:17:00 【问题描述】:

我的计划 Cloud Function 正在按计划运行,但未成功写入我的 Firestore 实例。当我在本地将其作为 HTTP 请求触发时,该代码成功写入 FirestoreDB。但是一旦部署并添加了 PubSub 调度逻辑,它似乎不会写入 Firestore。

GCP 中的函数日志显示“ok”的完成状态。

想知道我做的事情是否在 JS 中有效,但 GCP 或 Pubsub 不喜欢,即使它在技术上是有效的 JS?

感谢任何帮助或指导。

const admin = require("firebase-admin");
const request = require("request");
const functions = require("firebase-functions");

const serviceAccount = require("......");

admin.initializeApp(
  credential: admin.credential.cert(serviceAccount),
);
const db = admin.firestore();

exports.scheduledPRRfunction = functions.pubsub
    .schedule("every 2 minutes")
    .timeZone("America/New_York")
    .onRun(((context) => 
      const Options = 
        "method": "GET",
        "url": "...",
        "headers": 
          "Cookie": ".....",
        ,
      ;

      db.collection("myCollectionName").get().then((querySnapshot) => 
        querySnapshot.forEach((doc) => 
          const documentIds = doc.id;
          // Delete Documents
          db.collection("myCollectionName")
              .doc(documentIds).delete().then(() => 
              ).catch((error) => 
                console.log("Error removing document: ", error);
              );
        );
      );

      // Write Documents
      request(Options, function(error, response) 
        if (error) throw new Error(error);
        const apiResponse = JSON.parse(response.body);
        const parsedResponse = apiResponse["news_results"];
        for (let i = 0; i < parsedResponse.length; i++) 
          // console.log(i);
          db.collection("myCollectionName").add(parsedResponse[i]);
        
      );
  ));

【问题讨论】:

【参考方案1】:

request 原生支持回调接口,但不返回 Promise,这是您必须在 Pub/Sub Cloud Function(以及后台 Cloud Functions)中执行的操作。

这在官方 Firebase 视频系列中有解释:https://firebase.google.com/docs/functions/video-series/。特别是观看名为“学习 javascript Promises”的三个视频(第 2 部分和第 3 部分特别关注背景触发的云函数,但之前确实值得观看第 1 部分)。

可以使用 request-promise 库代替,但自 2020 年 2 月 11 日起,request 已完全弃用,因此我建议使用 axios

以下代码应该可以解决问题(未经测试):

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

admin.initializeApp();
const db = admin.firestore();

exports.scheduledPRRfunction = functions.pubsub
    .schedule("every 2 minutes")
    .timeZone("America/New_York")
    .onRun(async (context) => 

        try 

            const querySnapshot = await db.collection("myCollectionName").get();
            const promises = querySnapshot.docs.map(doc => db.collection("myCollectionName").doc(doc.id).delete());

            await Promise.all(promises);

            const options = 
                "method": "get",
                "url": "...",
                "headers": 
                    "Cookie": ".....",
                ,
            ;

            const axiosResponse = await axios(options);
            const apiResponse = JSON.parse(axiosResponse.data);
            const parsedResponse = apiResponse["news_results"];

            const docCreationPromises = parsedResponse.map(response => db.collection("myCollectionName").add(parsedResponse))

            await Promise.all(docCreationPromises);

            return null;

         catch (error) 
            console.log(error);
            return null;
        

    );

注意:

我们使用async/await,以便更轻松地编写异步代码 由于您要并行触发多个异步操作,因此您必须使用Promise.all()

另外,请注意,由于 Cloud Functions 的 Firebase SDK 版本 1.0.0,firebase-admin 应在 Cloud Functions 运行时内不带任何参数的情况下进行初始化,如下所示:

const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();

【讨论】:

感谢@renaud_tarnec 的详细回复 - 我已经使用 Axios 更新了我的代码并成功部署了预定的功能。不幸的是,它仍然无法写入我的数据库。 你能调试吗?您是否从调用 API/URL 中得到正确的结果? axiosResponse 的值是多少?在db.collection("myCollectionName").add(parsedResponse) 也有一个错字:它是db.collection("myCollectionName").add(response) 抱歉耽搁了@renaud-tarec。我现在无法在本地运行此功能。 i functions[us-central1-scheduledPRRfunction]: function ignored because the pubsub emulator does not exist or is not running. 我已经确认 PubSub 模拟器在 8085 端口上运行。我会努力解决这个问题并尽快报告。

以上是关于计划的 Firebase 功能 - 不写入 Firestore的主要内容,如果未能解决你的问题,请参考以下文章

扩展 Firebase Firestore 计划事件

密码注册后 Firebase 云功能出现未经身份验证的错误

Firebase - 跨多个位置的原子写入不起作用

firebase 云计划功能无法正常工作

为啥我的用于 Firebase 的 Cron 计划云功能在太平洋时间而不是 UTC 时间运行?

Firebase Spark 计划云消息传递限制 [重复]