Firebase pubsub 功能在模拟器中有效,但在生产中不能立即 returns
Firebase pubsub function works in emulator but not returns immediatly in production
我预定的功能
// TODO;
export const reportUsage =
fun.pubsub.schedule("0 0 1 * *").onRun(async (context) => {
functions.logger.debug("Initialising db");
const db = admin.firestore();
const users = await db.collection("users").get();
users.docs.forEach( async (doc) => {
functions.logger.debug("Got list of users. Looping..");
const userData = doc.data();
const SOME_DATA:number = userData["SOME_DATA"];
functions.logger.debug("got SOME_DATA of this user");
const SOME_DATAIntPart:number =
parseInt(SOME_DATA.toFixed(20).split(".")[0]);
const SOME_DATAFloatPart:number =
parseFloat("0." + SOME_DATA.toFixed(20).split(".")[1]);
const subItemId =
userData["stripeInfo"]["subscription"]["items"]["data"][0]["id"];
functions.logger.debug("got sub id of this user");
await stripe.subscriptionItems.createUsageRecord(subItemId, {
quantity: SOME_DATAIntPart,
timestamp: admin.firestore.Timestamp.now().seconds,
}, {
timeout: 60,
maxNetworkRetries: 5,
});
functions.logger.debug("got reported to stripe");
await doc.ref.update({
"SOME_DATA": SOME_DATAFloatPart,
});
functions.logger.debug("updated SOME_DATA");
return null;
});
});
当我从 Cloud Scheduler 手动 运行 函数时,它 returns 就在 Stripe 调用之前
await stripe.subscriptionItems.createUsageRecord(subItemId, {
quantity: SOME_DATAIntPart,
timestamp: admin.firestore.Timestamp.now().seconds,
}, {
timeout: 60,
maxNetworkRetries: 5,
});
我记录的日志显示了这个
如您所见,它在执行 Stripe 调用之前立即 returns。
上次日志中的错误是这样的:
但是,运行使用函数 shell 调用函数、firestore 和 pubsub 模拟器,我可以调用 reportUsage 函数,这就是打印出来的内容
谁能告诉我为什么 pubsub 功能在生产环境中不起作用?
您不应在 forEach()
循环中使用 async/await
,请参阅 "JavaScript: async/await with forEach()" and 。
您可以按如下方式使用Promise.all()
:
export const reportUsage = fun.pubsub
.schedule('0 0 1 * *')
.onRun(async (context) => {
functions.logger.debug('Initialising db');
const db = admin.firestore();
const users = await db.collection('users').get();
users.docs.forEach((doc) => {
functions.logger.debug('Got list of users. Looping..');
const userData = doc.data();
const SOME_DATA: number = userData['SOME_DATA'];
functions.logger.debug('got SOME_DATA of this user');
const SOME_DATAIntPart: number = parseInt(
SOME_DATA.toFixed(20).split('.')[0]
);
const SOME_DATAFloatPart: number = parseFloat(
'0.' + SOME_DATA.toFixed(20).split('.')[1]
);
const subItemId =
userData['stripeInfo']['subscription']['items']['data'][0]['id'];
functions.logger.debug('got sub id of this user');
const promises = [];
// We push a Promise to the promsies Array. Note that the then() method returns a promise.
promises.push(
stripe.subscriptionItems
.createUsageRecord(
subItemId,
{
quantity: SOME_DATAIntPart,
timestamp: admin.firestore.Timestamp.now().seconds,
},
{
timeout: 60,
maxNetworkRetries: 5,
}
)
.then(() => {
return doc.ref.update({
SOME_DATA: SOME_DATAFloatPart,
});
})
);
functions.logger.debug('updated SOME_DATA');
});
await Promise.all(promises);
return null;
});
我预定的功能
// TODO;
export const reportUsage =
fun.pubsub.schedule("0 0 1 * *").onRun(async (context) => {
functions.logger.debug("Initialising db");
const db = admin.firestore();
const users = await db.collection("users").get();
users.docs.forEach( async (doc) => {
functions.logger.debug("Got list of users. Looping..");
const userData = doc.data();
const SOME_DATA:number = userData["SOME_DATA"];
functions.logger.debug("got SOME_DATA of this user");
const SOME_DATAIntPart:number =
parseInt(SOME_DATA.toFixed(20).split(".")[0]);
const SOME_DATAFloatPart:number =
parseFloat("0." + SOME_DATA.toFixed(20).split(".")[1]);
const subItemId =
userData["stripeInfo"]["subscription"]["items"]["data"][0]["id"];
functions.logger.debug("got sub id of this user");
await stripe.subscriptionItems.createUsageRecord(subItemId, {
quantity: SOME_DATAIntPart,
timestamp: admin.firestore.Timestamp.now().seconds,
}, {
timeout: 60,
maxNetworkRetries: 5,
});
functions.logger.debug("got reported to stripe");
await doc.ref.update({
"SOME_DATA": SOME_DATAFloatPart,
});
functions.logger.debug("updated SOME_DATA");
return null;
});
});
当我从 Cloud Scheduler 手动 运行 函数时,它 returns 就在 Stripe 调用之前
await stripe.subscriptionItems.createUsageRecord(subItemId, {
quantity: SOME_DATAIntPart,
timestamp: admin.firestore.Timestamp.now().seconds,
}, {
timeout: 60,
maxNetworkRetries: 5,
});
我记录的日志显示了这个
如您所见,它在执行 Stripe 调用之前立即 returns。
上次日志中的错误是这样的:
但是,运行使用函数 shell 调用函数、firestore 和 pubsub 模拟器,我可以调用 reportUsage 函数,这就是打印出来的内容
谁能告诉我为什么 pubsub 功能在生产环境中不起作用?
您不应在 forEach()
循环中使用 async/await
,请参阅 "JavaScript: async/await with forEach()" and
您可以按如下方式使用Promise.all()
:
export const reportUsage = fun.pubsub
.schedule('0 0 1 * *')
.onRun(async (context) => {
functions.logger.debug('Initialising db');
const db = admin.firestore();
const users = await db.collection('users').get();
users.docs.forEach((doc) => {
functions.logger.debug('Got list of users. Looping..');
const userData = doc.data();
const SOME_DATA: number = userData['SOME_DATA'];
functions.logger.debug('got SOME_DATA of this user');
const SOME_DATAIntPart: number = parseInt(
SOME_DATA.toFixed(20).split('.')[0]
);
const SOME_DATAFloatPart: number = parseFloat(
'0.' + SOME_DATA.toFixed(20).split('.')[1]
);
const subItemId =
userData['stripeInfo']['subscription']['items']['data'][0]['id'];
functions.logger.debug('got sub id of this user');
const promises = [];
// We push a Promise to the promsies Array. Note that the then() method returns a promise.
promises.push(
stripe.subscriptionItems
.createUsageRecord(
subItemId,
{
quantity: SOME_DATAIntPart,
timestamp: admin.firestore.Timestamp.now().seconds,
},
{
timeout: 60,
maxNetworkRetries: 5,
}
)
.then(() => {
return doc.ref.update({
SOME_DATA: SOME_DATAFloatPart,
});
})
);
functions.logger.debug('updated SOME_DATA');
});
await Promise.all(promises);
return null;
});