Firebase Cloud 函数偶尔不会执行



我有一个firestore项目,它管理用户预订,并包括下面的云功能,该功能设置为每天午夜运行。该功能识别定期预订的标志,并为下一周的同一时间/天创建新的预订(消防商店文档(。

此函数可能每周运行5或6天,但有时不会随机运行。之所以调用它,是因为我看到"已开始每日定期预订…"日志,但没有创建新文档。

如果我更改pubsub时间表上的时间,让它在当天晚些时候再次运行。。。

日志中没有错误。。。

很难理解为什么这个功能在某些情况下似乎被扼杀了。。。。


// Scheduled function to create repeat bookings each day.
exports.createRecurringBooking = functions.pubsub
.schedule('01 00 * * *')
.timeZone('Europe/London') // Runs in London Timezone
.onRun((context) => {
const firestore = admin.firestore;
const db = admin.firestore();
console.log('⏰ Daily Recurring Bookings Started....');

// Define current day and next day with 00:00 start Time
const today = new Date(new Date().setHours(0, 0, 0, 0));
const todayUnix = dayjs(today).valueOf();
const tomorrowUnix = dayjs(today).add(1, 'day').valueOf();
const todayTimestamp = firestore.Timestamp.fromMillis(todayUnix);
const tomorrowTimestamp = firestore.Timestamp.fromMillis(tomorrowUnix);

// Get bookings from firestore for current day with no end date
db.collection('bookings')
.where('startTime', '>=', todayTimestamp)
.where('startTime', '<', tomorrowTimestamp)
.where('isRecurring', '==', true)
.where('recurringCount', '==', -1)
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
const startTime = dayjs(doc.data().startTime.toDate());
const newStartTime = dayjs(startTime).add(7, 'day');
const newStartTimeTimestamp = firestore.Timestamp.fromMillis(
dayjs(newStartTime).valueOf()
);
newRecurringBooking = {
bookingDetails: doc.data().bookingDetails,
channel: doc.data().channel,
createdAt: firestore.Timestamp.now(),
isRecurring: true,
start: doc.data().start ? doc.data().start : newStartTimeTimestamp,
location: doc.data().location,
recurringCount: doc.data().recurringCount,
recurringDescription: doc.data().recurringDescription
? doc.data().recurringDescription
: '',
recurringWeek: doc.data().recurringWeek + 1,
startTime: newStartTimeTimestamp,
status: 'confirmed',
studio: doc.data().studio,
user: doc.data().user,
};
db.collection('bookings')
.doc()
.set(newRecurringBooking)
.then(() => {
console.log(' ⭐ Recurring Booking created! ');
})
.catch((error) => {
console.error('Error Creating Booking: ', error);
});
});
})
.catch((error) => {
console.log(
`❌ ERROR when creating open ended recurring bookings! Error: ${error}`
);
});

// Get bookings from firestore for current day with end date
db.collection('bookings')
.where('startTime', '>=', todayTimestamp)
.where('startTime', '<', tomorrowTimestamp)
.where('isRecurring', '==', true)
.get()
.then((querySnapshot) => {
querySnapshot.forEach((doc) => {
const startTime = dayjs(doc.data().startTime.toDate());
const newStartTime = dayjs(startTime).add(7, 'day');
const newStartTimeTimestamp = firestore.Timestamp.fromMillis(
dayjs(newStartTime).valueOf()
);
// Only create new booking if sequence hasn't ended.
if (
doc.data().recurringWeek < doc.data().recurringCount &&
doc.data().recurringCount > 0
) {

newRecurringBooking = {
bookingDetails: doc.data().bookingDetails,
channel: doc.data().channel,
createdAt: firestore.Timestamp.now(),
isRecurring: true,
location: doc.data().location,
recurringCount: doc.data().recurringCount,
recurringDescription: doc.data().recurringDescription
? doc.data().recurringDescription
: '',
recurringWeek: doc.data().recurringWeek + 1,
startTime: newStartTimeTimestamp,
status: 'confirmed',
studio: doc.data().studio,
user: doc.data().user,
};
db.collection('bookings')
.doc()
.set(newRecurringBooking)
.then(() => {
console.log(' ⭐  Booking created! ');
})
.catch((error) => {
console.error('Error Creating Booking: ', error);
});
}
});
})
.catch((error) => {
console.log(
`❌ ERROR when creating recurring bookings with end date! Error: ${error}`
);
});

return null;
});

您根本没有考虑您在云函数中调用的Firebase方法的异步特性。我不知道这是否是你问题的确切原因,但它总有一天会产生问题,以一种很难调试的方式,因为正如你在问题中解释的那样,它会以一种不稳定的方式出现。

正如你将在关于";JavaScript承诺";从官方的Firebase系列视频中,您必须在后台触发的Cloud Function中返回Promise或值,以向平台指示Cloud Function已完成。由于您没有返回Promise,因此您会遇到这种不一致的行为。有时云函数在写入Firestore之前就被平台杀死了,有时云函数平台没有立即终止函数,异步操作就可以完成。

你需要使用async/await或Promise.all((来调整你的代码。如果你想在初始化下一个Promise之前等待每个Promise的解析,你可以通过在异步函数中等待每个Promises来完成。如果你不想在开始下一个承诺之前等待每个承诺完成,你可以使用promise.all((在所有承诺都得到解决后运行一些东西。

最新更新