Firebase 云功能无法正确记录
Firebase cloud function doesn't log correctly
我正在 运行 在 firebase 函数上设置一个 pubsub 计划函数,运行 每两分钟一次。
我尝试记录快照循环收集的事件,但有些地方不正常。
exports.check_event_ended_notification = functions.pubsub.schedule('every 2 minutes').onRun((context) => {
let default_lineup = "default";
let events = [];
return admin.database().ref("Events").once('value')
.then(snapshot => {
console.log(("EVENTS number : " + snapshot.numChildren()));
snapshot.forEach(event_snapshot => {
let event_key = event_snapshot.key;
let event = event_snapshot.val();
events.push(event_key);
console.log("EVENT_UID : " + event_key);
console.log(("EVENTS : " + events));
// iterate through all events and check if they're marked as ended
// if not, check if ended
let event_status = event[['ended_status']];
if (event_status === '0') {
// get event date
let event_day = event[['date']]['0'];
let event_month = event[['date']]['1'];
let event_year = event[['date']]['2'];
let event_full_date = event_year + "-" + event_month + "-" + event_day;
// get today date
let today = new Date();
let today_day = today.getDate();
let today_month = (today.getMonth() + 1);
let today_year = today.getFullYear();
let today_full_date = today_year + "-" + today_month + "-" + today_day;
//create date objects to compare
let event_date = new Date(event_full_date);
let today_date = new Date(today_full_date);
// if event date is in the past
// check to see if its marked as ended.
if (event_date.getTime() < today_date.getTime()) {
console.log("EVENT : past event : " + event_key);
if (event[['ended_status']] === "0") {
console.log("EVENT : ended 0 : " + event_key);
//mark as ended
// admin.database().ref("Events/"+event_key+"/ended_status").set("1");
//create notifications for participation artists
for (let artist_key in event[['lineup']]) {
console.log("ARTIST before: " + artist_key);
if (artist_key !== default_lineup) {
console.log("ARTIST after: " + artist_key);
let approved_invitation = event[['lineup']][artist_key]['approved_invitation'];
let handshake_status = event[['lineup']][artist_key]['handshake_status'];
let quit = event[['lineup']][artist_key]['quit'];
let removed = event[['lineup']][artist_key]['removed'];
let event_publish_status = event[['publish_status']];
let owner_uid = event[['owner_uid']];
if (approved_invitation === '1' && handshake_status === '1' && quit === '0' && removed === '0' && event_publish_status === '1') {
return admin.database().ref("Notifications/" + artist_key + "/" + owner_uid + "/" + event['uid']).push({
notification_type: "ended",
seen_status: "0",
timestamp: new Date().getTime()
})
}
}
}
}
}
}
return null;
})
})
}
虽然开头的 numChildren() 日志显示快照下有 4 children(这是正确的),但 foreach() 方法似乎只 运行 两次,收集第一个两个 children 并将它们添加到“事件”列表中。
并且日志在此之后停止:
2020-07-29T14:22:00.593Z ? check_event_ended_notification: EVENTS number : 4
2020-07-29T14:22:00.593Z ? check_event_ended_notification: EVENT_UID : 3853c2db-f31a-4f46-8c1b-740ca4e3407b
2020-07-29T14:22:00.593Z ? check_event_ended_notification: EVENTS : 3853c2db-f31a-4f46-8c1b-740ca4e3407b
2020-07-29T14:22:00.594Z ? check_event_ended_notification: EVENT_UID : 4253c2db-f31a-4f46-8c1b-740ca4e3407s
2020-07-29T14:22:00.594Z ? check_event_ended_notification: EVENTS : 3853c2db-f31a-4f46-8c1b-740ca4e3407b,4253c2db-f31a-4f46-8c1b-740ca4e3407s
您没有正确管理 Cloud Functions 的生命周期。如 doc 中所述,您需要通过 returning JavaScript promise[= 解决执行异步处理的函数(也称为“后台函数”) 35=]".
此外,在 Cloud Function 中,不建议使用设置监听器的 on()
方法,而是 once()
方法,它“只监听指定事件的一个事件”事件类型,然后停止监听。”。
所以下面应该可以解决问题:
exports.check_event_ended_notification = functions.pubsub.schedule('every 2 minutes').onRun((context) => {
let default_lineup = "default";
let events = [];
return admin.database().ref("Events").once('value') // Note the return here
.then(snapshot => {
snapshot.forEach(event_snapshot => {
let event_key = event_snapshot.key;
let event = event_snapshot.val();
events.push(event_key)
console.log("EVENT_UID : " + event_key);
console.log(("EVENTS : " + events));
});
// Do something with events... We don't have enough details
return null; // Or return a promise
});
});
根据您的评论更新
如果你想在forEach()
中写入数据库(这是一个异步过程),你应该使用Promise.all()
,以便return一个promise的时候对异步 push()
方法的所有并行调用都已完成。
这是代码的框架,您应该根据所有细节进行调整:
exports.check_event_ended_notification = functions.pubsub.schedule('every 2 minutes').onRun((context) => {
let default_lineup = "default";
let events = [];
return admin.database().ref("Events/").once('value')
.then(snapshot => {
const promises = [];
snapShot.forEach(event_snapshot => {
let event_key = event_snapshot.key;
let event = event_snapshot.val();
events.push(event_key)
console.log("EVENT_UID : " + event_key);
console.log(("EVENTS : " + events));
promises.push(
admin.database().ref("Notifications/" + artist_key + "/" + owner_uid + "/" + event['uid']).push({
notification_type: "ended",
seen_status: "0",
timestamp: new Date().getTime()
})
);
});
return Promise.all(promises); // This returns a promise!!
});
});
我正在 运行 在 firebase 函数上设置一个 pubsub 计划函数,运行 每两分钟一次。 我尝试记录快照循环收集的事件,但有些地方不正常。
exports.check_event_ended_notification = functions.pubsub.schedule('every 2 minutes').onRun((context) => {
let default_lineup = "default";
let events = [];
return admin.database().ref("Events").once('value')
.then(snapshot => {
console.log(("EVENTS number : " + snapshot.numChildren()));
snapshot.forEach(event_snapshot => {
let event_key = event_snapshot.key;
let event = event_snapshot.val();
events.push(event_key);
console.log("EVENT_UID : " + event_key);
console.log(("EVENTS : " + events));
// iterate through all events and check if they're marked as ended
// if not, check if ended
let event_status = event[['ended_status']];
if (event_status === '0') {
// get event date
let event_day = event[['date']]['0'];
let event_month = event[['date']]['1'];
let event_year = event[['date']]['2'];
let event_full_date = event_year + "-" + event_month + "-" + event_day;
// get today date
let today = new Date();
let today_day = today.getDate();
let today_month = (today.getMonth() + 1);
let today_year = today.getFullYear();
let today_full_date = today_year + "-" + today_month + "-" + today_day;
//create date objects to compare
let event_date = new Date(event_full_date);
let today_date = new Date(today_full_date);
// if event date is in the past
// check to see if its marked as ended.
if (event_date.getTime() < today_date.getTime()) {
console.log("EVENT : past event : " + event_key);
if (event[['ended_status']] === "0") {
console.log("EVENT : ended 0 : " + event_key);
//mark as ended
// admin.database().ref("Events/"+event_key+"/ended_status").set("1");
//create notifications for participation artists
for (let artist_key in event[['lineup']]) {
console.log("ARTIST before: " + artist_key);
if (artist_key !== default_lineup) {
console.log("ARTIST after: " + artist_key);
let approved_invitation = event[['lineup']][artist_key]['approved_invitation'];
let handshake_status = event[['lineup']][artist_key]['handshake_status'];
let quit = event[['lineup']][artist_key]['quit'];
let removed = event[['lineup']][artist_key]['removed'];
let event_publish_status = event[['publish_status']];
let owner_uid = event[['owner_uid']];
if (approved_invitation === '1' && handshake_status === '1' && quit === '0' && removed === '0' && event_publish_status === '1') {
return admin.database().ref("Notifications/" + artist_key + "/" + owner_uid + "/" + event['uid']).push({
notification_type: "ended",
seen_status: "0",
timestamp: new Date().getTime()
})
}
}
}
}
}
}
return null;
})
})
}
虽然开头的 numChildren() 日志显示快照下有 4 children(这是正确的),但 foreach() 方法似乎只 运行 两次,收集第一个两个 children 并将它们添加到“事件”列表中。
并且日志在此之后停止:
2020-07-29T14:22:00.593Z ? check_event_ended_notification: EVENTS number : 4
2020-07-29T14:22:00.593Z ? check_event_ended_notification: EVENT_UID : 3853c2db-f31a-4f46-8c1b-740ca4e3407b
2020-07-29T14:22:00.593Z ? check_event_ended_notification: EVENTS : 3853c2db-f31a-4f46-8c1b-740ca4e3407b
2020-07-29T14:22:00.594Z ? check_event_ended_notification: EVENT_UID : 4253c2db-f31a-4f46-8c1b-740ca4e3407s
2020-07-29T14:22:00.594Z ? check_event_ended_notification: EVENTS : 3853c2db-f31a-4f46-8c1b-740ca4e3407b,4253c2db-f31a-4f46-8c1b-740ca4e3407s
您没有正确管理 Cloud Functions 的生命周期。如 doc 中所述,您需要通过 returning JavaScript promise[= 解决执行异步处理的函数(也称为“后台函数”) 35=]".
此外,在 Cloud Function 中,不建议使用设置监听器的 on()
方法,而是 once()
方法,它“只监听指定事件的一个事件”事件类型,然后停止监听。”。
所以下面应该可以解决问题:
exports.check_event_ended_notification = functions.pubsub.schedule('every 2 minutes').onRun((context) => {
let default_lineup = "default";
let events = [];
return admin.database().ref("Events").once('value') // Note the return here
.then(snapshot => {
snapshot.forEach(event_snapshot => {
let event_key = event_snapshot.key;
let event = event_snapshot.val();
events.push(event_key)
console.log("EVENT_UID : " + event_key);
console.log(("EVENTS : " + events));
});
// Do something with events... We don't have enough details
return null; // Or return a promise
});
});
根据您的评论更新
如果你想在forEach()
中写入数据库(这是一个异步过程),你应该使用Promise.all()
,以便return一个promise的时候对异步 push()
方法的所有并行调用都已完成。
这是代码的框架,您应该根据所有细节进行调整:
exports.check_event_ended_notification = functions.pubsub.schedule('every 2 minutes').onRun((context) => {
let default_lineup = "default";
let events = [];
return admin.database().ref("Events/").once('value')
.then(snapshot => {
const promises = [];
snapShot.forEach(event_snapshot => {
let event_key = event_snapshot.key;
let event = event_snapshot.val();
events.push(event_key)
console.log("EVENT_UID : " + event_key);
console.log(("EVENTS : " + events));
promises.push(
admin.database().ref("Notifications/" + artist_key + "/" + owner_uid + "/" + event['uid']).push({
notification_type: "ended",
seen_status: "0",
timestamp: new Date().getTime()
})
);
});
return Promise.all(promises); // This returns a promise!!
});
});