You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cloud Firestore嵌套集合批量写入无报错但未生效求助

问题分析与解决方案

你的代码无报错但未写入Firestore,核心原因是Cloud Functions未等待异步操作完成就提前终止,同时缺少错误处理导致问题被隐藏。以下是具体修复点和完整代码:

核心问题点

  1. 异步任务未被等待
    functions.cloudEvent 处理函数没有返回Promise,也未等待https.get和后续Firestore批量写入操作完成。Cloud Functions会在同步代码执行完毕后立即终止进程,导致后续异步写入被中断。

  2. 无错误捕获机制
    代码未对HTTP请求、数据解析、Firestore操作添加错误处理,即使出现网络异常、权限问题或数据格式错误,也无法在控制台看到报错信息。

  3. 日期格式潜在风险
    需确认Wordle API的日期格式是否严格匹配UTC日期(当前代码逻辑是正确的,但需验证请求URL是否能返回有效数据)。

修复后的完整代码

const functions = require('@google-cloud/functions-framework');
const https = require('https');
const { promisify } = require('util');

const admin = require("firebase-admin");
admin.initializeApp();

// 将https.get转为Promise形式,适配async/await
const httpsGet = promisify(https.get);

functions.cloudEvent('getWordleSolution', async () => {  
  const incrementAndPad = (num) => {
    const str = String(num + 1);
    return str.padStart(2, "0");
  }

  const now = new Date();
  const year = now.getUTCFullYear();
  const month = incrementAndPad(now.getUTCMonth());
  const date = now.getUTCDate();

  const url = `https://www.nytimes.com/svc/wordle/v2/${year}-${month}-${date}.json`;

  try {
    // 等待HTTP请求完成
    const res = await httpsGet(url);
    let puzzleData = "";

    // 等待数据流接收完成
    await new Promise((resolve, reject) => {
      res.on("data", (chunk) => puzzleData += chunk);
      res.on('end', resolve);
      res.on('error', reject);
    });

    const puzzle = JSON.parse(puzzleData);
    await writeToFirestore(puzzle);
    console.log('批量写入完成');
  } catch (error) {
    console.error('执行出错:', error);
    throw error; // 抛出错误让Cloud Functions记录日志
  }
});

const writeToFirestore = async ({ id, solution, print_date }) => {
  const db = admin.firestore();
  const batch = db.batch();

  const leaderboardsRef = db.collection('leaderboards');
  const leaderboardDocsSnapshot = await leaderboardsRef.get();

  // 处理空集合场景
  if (leaderboardDocsSnapshot.empty) {
    console.log('未找到任何leaderboard文档');
    return;
  }

  leaderboardDocsSnapshot.forEach((snapshot) => {
    const contestsRef = snapshot.ref.collection('contests');
    // Firestore会自动创建不存在的contests集合
    batch.set(contestsRef.doc(id), { solution, print_date });
  });

  await batch.commit();
  console.log(`成功写入${leaderboardDocsSnapshot.size}个contest文档`);
};

关键修复说明

  • Promise封装异步操作:将https.get和数据流接收转为Promise,配合async/await确保Cloud Functions等待所有异步任务完成后再终止。
  • 完整错误处理:通过try/catch捕获全流程错误,确保异常能被日志记录,方便排查问题。
  • 空集合处理:当leaderboards集合为空时,提前返回并打印日志,避免无效操作。
  • 自动创建集合:无需手动创建contests集合,Firestore会在写入第一个文档时自动生成该集合,满足需求。

额外检查项

  1. 权限验证:确保Cloud Functions服务账号拥有datastore.user或更高权限,具备Firestore写入权限。
  2. API可用性:本地测试请求URL是否能返回有效JSON数据,确认Wordle API可正常访问。
  3. 日志排查:在Cloud Functions控制台查看执行日志,确认是否有隐藏的错误信息。

内容的提问来源于stack exchange,提问作者Zach McNulty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 16:45:09