如何使用 pubsub 模拟器在本地调用 firebase Schedule 函数

Posted

技术标签:

【中文标题】如何使用 pubsub 模拟器在本地调用 firebase Schedule 函数【英文标题】:How to invoke firebase Schedule functions locally using pubsub emulator 【发布时间】:2020-10-26 18:09:42 【问题描述】:

我正在研究云功能,尤其是日程安排功能。我需要每 5 分钟定期触发一个功能,但仅在测试步骤中。我需要在 pubsub 模拟器上运行它而不部署它。

怎么做?

我尝试使用 firebase shell,但它只触发了一次

 exports.scheduledFunctionPlainEnglish =functions.pubsub.schedule('every 2 minutes')
 .onRun((context) => 
    functions.logger.log("this runs every 2 minutes")
    return null;
) 

【问题讨论】:

【参考方案1】:

正如您所说,您可以使用 firebase shell 来运行您的函数一次。 在 firebase shell 中,您可以使用 NodeJS 命令。

使用 setInterval

firebase functions:shell 中,使用 setInterval 每 2 分钟运行一次函数。

user@laptop:~$ firebase functions:shell

✔  functions: functions emulator started at http://localhost:5000
i  functions: Loaded functions: myScheduledFunction
firebase > setInterval(() => myScheduledFunction(), 120000)

> this runs every 2 minutes

单行脚本

自从 firebase-tools 的 8.4.3 版本,特别是 this PR,管道解决方案不再起作用。

在 Bash 中,您甚至可以通过管道将 setInterval 命令传送到 firebase shell

user@laptop:~$ echo "setInterval(() => myScheduledFunction(), 120000)" | firebase functions:shell

【讨论】:

从 firebase-tools 8.4.3 版开始,尤其是this PR,这个解决方案不再起作用了。 为了澄清,你的意思是单线管道到外壳不起作用? (那么可以从答案中编辑吗?)我正在使用 fireabse-tools 9.16.0 并在 shell 中以交互方式运行 setInterval( 对我有用。【参考方案2】:

计划函数加载到 Cloud Functions 模拟器运行时并绑定到 PubSub 模拟器主题。

但正如@samstern 所说(https://github.com/firebase/firebase-tools/issues/2034):

您必须使用 Pub/Sub 消息手动触发它们。

你可以这样做:

import * as functions from 'firebase-functions';
import * as admin from 'firebase-admin';
import  PubSub  from '@google-cloud/pubsub';

if (!admin.apps.length) 
  admin.initializeApp();


const pubsub = new PubSub(
  apiEndpoint: 'localhost:8085' // Change it to your PubSub emulator address and port
);

setInterval(() => 
  const SCHEDULED_FUNCTION_TOPIC = 'firebase-schedule-yourFunctionName';
  console.log(`Trigger sheduled function via PubSub topic: $SCHEDULED_FUNCTION_TOPIC`);
  const msg = await pubsub.topic(SCHEDULED_FUNCTION_TOPIC).publishJSON(
    foo: 'bar',
  ,  attr1: 'value1' );
, 5 * 60 * 1000); // every 5 minutes

关于这个概念的更多信息(感谢@kthaas):

    https://github.com/firebase/firebase-tools/pull/2011/files#diff-6b2a373d8dc24c4074ee623d433662831cadc7c178373fb957c06bc12c44ba7b https://github.com/firebase/firebase-tools/pull/2011/files#diff-73f0f0ab73ffbf988f109e0a4c8b3b8a793f30ef33929928a892d605f0f0cc1f

【讨论】:

为了完整起见,还有两件事要让这段代码 sn-p 工作。首先,PUBSUB_EMULATOR_HOST 环境变量必须设置为类似localhost:8432(取决于您的本地模拟器设置)。其次,必须将项目 id 提供给 PubSub 构造函数(例如new PubSub( projectId: '...' ) @Stephan 我在 PubSub 初始化中添加了 apiEndpoint。我没有指定projectId,而是使用env-cmd.env 文件,其中包含指向默认凭据GOOGLE_APPLICATION_CREDENTIALS=./default-credentials.json 的链接 这在我之前怎么没有票?这完美!我使用从您的答案中借来的代码创建了一个 js 文件(而不是 ts 文件,不必担心编译它),并手动触发任务,而不是像这样的间隔:node functions/src/myTriggerfile.js【参考方案3】:

目前不支持预定功能。 documentation 声明:

使用 shell,您可以模拟数据并执行函数调用,以模拟与 Emulator Suite 当前不支持的产品的交互:存储、PubSub、分析、远程配置、存储、身份验证和 Crashlytics .

计划函数是 pubsub 触发器的不受支持的扩展。

请随时file a feature request with Firebase support。

【讨论】:

这是 GitHub 上的open issue。

以上是关于如何使用 pubsub 模拟器在本地调用 firebase Schedule 函数的主要内容,如果未能解决你的问题,请参考以下文章

Firebase 模拟器:在函数中使用 PubSub

本地 Pubsub 模拟器不适用于 Dataflow

Firebase 函数不会看到 pubsub 模拟器在本地运行

尝试在本地运行 PubSub 模拟器时出错

如何将 spring gcp PubSubTemplate 连接到本地实例?

本地 GAE java 开发服务器的 Google Pub/Sub 测试策略