如何使用 firebase 模拟器 pubsub 在本地测试定时功能?

How to use firebase emulators pubsub to test timed functions locally?

我正在为一个项目使用 firebase,并且正在使用以下代码创建一个计划函数。我想每运行一分钟记录一条消息。

export const timedQuery = functions.pubsub.schedule('1 * * * *').onRun((context) => {
console.log("I am running")
return null;
})

我有在 http 函数下工作的代码的主要逻辑,想在部署到生产环境之前查看它是否在本地工作。通过 firebase 文档,我已经下载了所有的 firebase 模拟器并使用 "firebase emulators:start" 来获取它们 运行。从日志来看,我的 pubsub 模拟器似乎在 localhost:8085 成功启动并且 pubsub 功能已初始化,但是即使等待 2 - 3 分钟后也没有任何打印出来。是否可以在本地测试计划的功能?

此外,我创建这个时没有使用 google 云调度程序,因为我只使用 firebase。

Firebase 本地模拟器目前不模拟实际的预定功能。 documentation 表示:

The Firebase CLI includes a Cloud Functions emulator which can emulate the following function types:

  • HTTPS functions
  • Callable functions
  • Cloud Firestore functions

我建议使用 Firebase support 提交功能请求。

部署计划函数时,实际上是在幕后使用 Google Cloud Scheduler。详细信息为您管理。如 documentation 中所述:

If you want to schedule functions to run at specified times, use functions.pubsub.schedule().onRun() This convenience method creates a Google Cloud Pub/Sub topic and uses Google Cloud Scheduler to trigger events on that topic, ensuring that your function runs on the desired schedule.

我建议将您的函数代码重构为一种方法,您可以使用您选择的测试框架直接调用它来进行测试。您也可以暂时将其包装在 HTTP 函数中并以这种方式调用它。

实际上有一个 Firebase PubSub 模拟器。要启用它,您需要安装最新的 CLI(肯定是在 8.2.0 中)

  • 重新运行 Firebase Init
  • Select 模拟器(空格键)
  • Select PubSub(以及您希望的其他)
  • 配置所需的开发端口
  • 让 CLI 安装模拟器

在本地创建测试脚本以将 PubSub 消息提交到队列中:

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

const { PubSub } = require('@google-cloud/pubsub');
const pubsub = new PubSub();

exports.pubsubWriter = functions.https.onRequest(async (req, res) => {
    console.log("Pubsub Emulator:", process.env.PUBSUB_EMULATOR_HOST);

    const msg = await pubsub.topic('test-topic').publishJSON({
        foo: 'bar',
        date: new Date()
    }, { attr1: 'value' });

    res.json({
        published: msg
    })
});

重新运行 firebase init 由于某些原因对我不起作用。

我最终手动修改了 firebase.json 文件,

引用related docs

Change emulator ports by running firebase init emulators or by editing firebase.json manually.

// firebase.json
{
  "hosting": {
    // stuff...
  },
  "functions": {
    // stuff...
  },
  "emulators": {
    "functions": {
      "port": 5001
    },
    "hosting": {
      "port": 5000
    },
    "ui": {
      "enabled": true
    },
    "firestore": {
      "port": 8080
    },
    // * * * * * * * * *THIS * * * * * * * * * * * * * * * * * * * * * * * 
    "pubsub": {
      "port": "8085"
    }
    // * * * * * * * * *THIS * * * * * * * * * * * * * * * * * * * * * * * 
  },
  // more stuff...
}

解决方法

PubSub 模拟器还不支持定时函数。

但是你可以使用firebase functions:shellsetInterval来模拟调度器。

注意:请确保您在本地运行使用 firebase 模拟器,否则 shell 可能会调用 Production 中的函数 !!

firebase functions:shell

firebase > setInterval(() => yourScheduledFunc(), 60000)

不要退出,然后它将每 60 秒 运行 您的函数。

注意:shell 中的函数 运行 不会显示在模拟器的日志中。