谷歌日历 API。同时修补事件时修改丢失
Posted
技术标签:
【中文标题】谷歌日历 API。同时修补事件时修改丢失【英文标题】:Google calendar API. Modifications loss when simultaneously patching event 【发布时间】:2021-06-29 10:04:39 【问题描述】:我有处理 webhook 的 firebase 函数。
此功能更新日历事件,单个事件可以同时更新。
我使用 Etag 和 If-Match
标头来防止修改丢失,如 doc 中所述。
但我仍然丢失了除最后一个之外的所有更改。
此代码对同一事件进行多次同时更新。
结果摘要中必须是“10”,但实际上是“2”。
这有什么问题?
代码
const calendarId = 'calendarid';
const scopes = [
"https://www.googleapis.com/auth/calendar",
"https://www.googleapis.com/auth/calendar.events",
];
const auth = new google.auth.GoogleAuth( scopes );
const calendar = google.calendar( version: "v3", auth );
...
const reproduce = async () =>
const id: eventId = await calendar.events.insert(
auth,
calendarId,
resource:
summary: '1',
// some another resource data
,
);
const update = async () =>
const event = await calendar.events.get(
auth,
calendarId,
eventId,
);
console.log("***BEFORE***");
console.log("summary: " + event.summary);
console.log("etag: " + event.etag);
const previousSummary = event.summary;
const newSummary = parseInt(previousSummary) + 1;
const res = await calendar.events.patch(
auth,
calendarId,
eventId,
resource: summary: newSummary.toString(),
,
headers:
"If-Match": event.data.etag
);
console.log("***AFTER***");
console.log("summary: " + res.data.summary);
console.log("etag: " + res.data.etag);
let i = 0;
// simultaneously updates event
while (i++ < 10)
update();
输出
> ***BEFORE***
> summary: 1
> etag: "3235006977030000"
> ***BEFORE***
> summary: 1
> etag: "3235006977030000"
> ***BEFORE***
> summary: 1
> etag: "3235006977030000"
> ***BEFORE***
> summary: 1
> etag: "3235006977030000"
> ***BEFORE***
> summary: 1
> etag: "3235006977030000"
> ***BEFORE***
> summary: 1
> etag: "3235006977030000"
> ***BEFORE***
> summary: 1
> etag: "3235006977030000"
> ***BEFORE***
> summary: 1
> etag: "3235006977030000"
> ***BEFORE***
> summary: 1
> etag: "3235006977030000"
> ***AFTER***
> summary: 2
> etag: "3235006998028000"
> Event updated successfully
> ***AFTER***
> summary: 2
> etag: "3235007000852000"
> Event updated successfully
> ***AFTER***
> summary: 2
> etag: "3235007002822000"
> Event updated successfully
> ***AFTER***
> summary: 2
> etag: "3235007003202000"
> Event updated successfully
> ***AFTER***
> summary: 2
> etag: "3235007004826000"
> Event updated successfully
> ***AFTER***
> summary: 2
> etag: "3235007009742000"
> Event updated successfully
> ***AFTER***
> summary: 2
> etag: "3235007011058000"
> Event updated successfully
> ***AFTER***
> summary: 2
> etag: "3235007014902000"
> Event updated successfully
> ***AFTER***
> summary: 2
> etag: "3235007018050000"
> Event updated successfully
【问题讨论】:
【参考方案1】:我能够在 Apps 脚本中使用 javascript 重现您的问题。
您能够更新您的事件一次(使您的摘要为“2”)的原因是因为您在 update()
中的 async/await
命令。
示例代码:
const update = async () =>
const event = await Calendar.Events.get(
calendarId,
eventId,
);
Logger.log("***BEFORE***");
Logger.log("summary: "+event.summary);
Logger.log("etag: "+event.etag);
const previousSummary = event.summary;
const newSummary = parseInt(previousSummary) + 1;
const res = await Calendar.Events.patch(
summary: newSummary.toString(),
calendarId,
event.id,
"If-Match": event.etag
);
Logger.log("***AFTER***");
Logger.log("summary: "+res.summary);
Logger.log("etag: "+res.etag);
//Logger.log(res);
let i = 0;
// simultaneously updates event
while (i++ < 10)
update();
输出:
12:04:47 AM Notice Execution started
12:04:51 AM Info ***BEFORE***
12:04:51 AM Info summary: 1
12:04:51 AM Info etag: "3234758978180000"
12:04:51 AM Info ***BEFORE***
12:04:51 AM Info summary: 1
12:04:51 AM Info etag: "3234758978180000"
12:04:52 AM Info ***BEFORE***
12:04:52 AM Info summary: 1
12:04:52 AM Info etag: "3234758978180000"
12:04:52 AM Info ***BEFORE***
12:04:52 AM Info summary: 1
12:04:52 AM Info etag: "3234758978180000"
12:04:52 AM Info ***BEFORE***
12:04:52 AM Info summary: 1
12:04:52 AM Info etag: "3234758978180000"
12:04:53 AM Info ***BEFORE***
12:04:53 AM Info summary: 1
12:04:53 AM Info etag: "3234758978180000"
12:04:53 AM Info ***BEFORE***
12:04:53 AM Info summary: 1
12:04:53 AM Info etag: "3234758978180000"
12:04:53 AM Info ***BEFORE***
12:04:53 AM Info summary: 1
12:04:53 AM Info etag: "3234758978180000"
12:04:54 AM Info ***BEFORE***
12:04:54 AM Info summary: 1
12:04:54 AM Info etag: "3234758978180000"
12:04:54 AM Info ***BEFORE***
12:04:54 AM Info summary: 1
12:04:54 AM Info etag: "3234758978180000"
12:04:54 AM Info ***AFTER***
12:04:54 AM Info summary: 2
12:04:54 AM Info etag: "3234758983260000"
12:04:54 AM Info ***AFTER***
12:04:54 AM Info summary: 2
12:04:54 AM Info etag: "3234758983260000"
12:04:54 AM Info ***AFTER***
12:04:54 AM Info summary: 2
12:04:54 AM Info etag: "3234758983260000"
12:04:54 AM Info ***AFTER***
12:04:54 AM Info summary: 2
12:04:54 AM Info etag: "3234758983260000"
12:04:54 AM Info ***AFTER***
12:04:54 AM Info summary: 2
12:04:54 AM Info etag: "3234758983260000"
12:04:54 AM Info ***AFTER***
12:04:54 AM Info summary: 2
12:04:54 AM Info etag: "3234758983260000"
12:04:54 AM Info ***AFTER***
12:04:54 AM Info summary: 2
12:04:54 AM Info etag: "3234758983260000"
12:04:54 AM Info ***AFTER***
12:04:54 AM Info summary: 2
12:04:54 AM Info etag: "3234758983260000"
12:04:54 AM Info ***AFTER***
12:04:54 AM Info summary: 2
12:04:54 AM Info etag: "3234758983260000"
12:04:54 AM Info ***AFTER***
12:04:54 AM Info summary: 2
12:04:54 AM Info etag: "3234758983260000"
12:04:54 AM Notice Execution completed
注意Calendar.Events.get()
方法在Calendar.Events.patch()
执行之前执行了10 次。因此,您可以一次修补您的事件。
我不是 Javascript Promises 方面的专家,但您可能希望删除 update()
、get()
和 patch()
中的 async/await
。
【讨论】:
感谢您的回答,但我仍然无法理解为什么多个同时更新会相互覆盖。 文档说如果事件自上次检索后发生变化,我将收到 412(前提条件失败)响应代码,但没有发生。 它没有相互覆盖,发生的事情是您的 await 命令先执行了您的 events.get() 10 次,但没有继续执行您的 events.patch()。当 events.patch() 也被执行 10 次时,补丁请求中使用的 etag 是基于执行 10 次后的最后一个 events.get() 响应。它是基于示例复制代码得到证明的,并在日志中看到。 您是否尝试过删除异步并等待以查看是否达到了预期的输出? 我已经更新了我的示例代码,添加了像你这样的日志打印。此外,我还添加了代码的输出,我看到发生覆盖是因为日历 API 响应更新了 ETag。以上是关于谷歌日历 API。同时修补事件时修改丢失的主要内容,如果未能解决你的问题,请参考以下文章
如何传播通过 gdata python api 创建的谷歌日历事件的提醒?
如何使用 android 使用日历 API 在谷歌日历上添加事件?