ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Automatisch Google Calendar 触发器全解析:New calendar 与 New event 的轮询机制与源码实现

2026/9/14 23:49:06 拓冰建站 浏览量
Automatisch Google Calendar 触发器全解析:New calendar 与 New event 的轮询机制与源码实现 Automatisch Google Calendar 触发器全解析New calendar 与 New event 的轮询机制与源码实现【免费下载链接】automatischThe open source Zapier alternative. Build workflow automation without spending time and money.项目地址: https://gitcode.com/GitHub_Trending/au/automatischGoogle Calendar 是 Automatisch开源 Zapier 替代品内置的日历自动化应用本指南以官方文档 triggers.md 为骨架系统讲解其提供的New calendar新建日历与New event新建事件两个触发器从 Google Cloud OAuth 连接配置到触发器的定义注册、分页拉取、去重与测试执行机制并深入到 packages/backend/src/apps/google-calendar 的真实源码带你掌握如何在流Flow中正确使用它们以及它们底层每 15 分钟轮询一次的工作原理。读完本文你将能够独立配置 Google Calendar 连接、理解触发器参数与去重行为并能在自己的 Automatisch 实例上构建当有新事件时发通知一类的自动化流。一、触发器总览官方文档定义的两种触发场景根据官方文档 triggers.md 的 frontmatter 元数据Google Calendar 应用向用户开放两种触发器触发器名称标识 Key官方描述New calendarnewCalendar当创建了一个新的日历时触发New eventnewEvent当创建了一个新的事件时触发在 Automatisch 文档站点中这两个条目由items列表定义通过 CustomListing.vue 组件渲染成可浏览的触发器清单页面。而在运行时真正驱动自动化的是 triggers/index.js 导出的两个触发器实现import newCalendar from ./new-calendar/index.js; import newEvent from ./new-event/index.js; export default [newCalendar, newEvent];该数组被 应用主入口 index.js 挂载到应用定义上export default defineApp({ name: Google Calendar, key: google-calendar, baseUrl: https://calendar.google.com, apiBaseUrl: https://www.googleapis.com/calendar, iconUrl: {BASE_URL}/apps/google-calendar/assets/favicon.svg, authDocUrl: {DOCS_URL}/apps/google-calendar/connection, primaryColor: #448AFF, supportsConnections: true, beforeRequest: [addAuthHeader], auth, triggers, dynamicData, });由此可见两个触发器都是轮询型polling触发器而非 Webhook 型。它们的共同特征是带有pollInterval属性这一点在下一节会详细说明。二、前置条件配置 Google Calendar 连接OAuth两个触发器都依赖用户授权的连接Connection。官方连接文档 connection.md 提供了完整的 Google Cloud 配置步骤这里是完整继承并整理的实操流程前往Google Cloud Console创建一个项目顶部项目下拉菜单 →New Project→ 填写项目名 →Create。进入API Library搜索并启用Google Calendar API。重复上述操作再启用People APIPeople API 用于获取当前用户信息与授权范围相关见下文。进入OAuth consent screen首次开发选择External外部类型以测试模式启动点击Create。填写App Name、User Support Email、Developer Contact Information点击Save and Continue。跳过 scopes 配置页点击Save and Continue。点击Add Users添加测试邮箱——当发布状态为 Testing 时只有测试用户能访问应用。点击Save and Continue完成同意屏幕配置。进入Credentials点击Create Credentials→ 选择OAuth client ID。应用类型选择Web application并填写Name。从 Automatisch 的 Google Calendar 连接表单中复制OAuth Redirect URL粘贴到 Google 的Authorized redirect URIs字段点击Create。将弹出的Your Client ID填入 Automatisch 的Client ID字段。将弹出的Your Client Secret填入 Automatisch 的Client Secret字段。点击 Automatisch 上的Submit连接即建立之后即可在流中使用。从源码 auth/index.js 可以看到连接表单正是要求OAuth Redirect URL、Client ID、Client Secret三个字段其中重定向 URL 由系统自动填充为{WEB_APP_URL}/app/google-calendar/connections/add并标记为只读readOnly: true与可点击复制clickToCopy: true便于直接粘贴到 Google Cloud 控制台。OAuth 授权范围Scope两个触发器请求的 Google 授权范围定义在 common/auth-scope.jsconst authScope [ https://www.googleapis.com/auth/calendar, https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile, ];其中calendar范围赋予读取及管理日历与事件的权限userinfo.email与userinfo.profile用于在验证凭据时获取当前用户身份信息见common/get-current-user.js。这也解释了为什么连接文档要求同时启用 People API。三、触发器定义规范为什么它们必须是轮询型查看 helpers/define-trigger.js 的校验逻辑可以确认任何触发器要么声明pollInterval轮询型要么声明type webhookWebhook 型否则会在注册时直接抛出异常const isWebhookOrPoll triggerDefinition.pollInterval || triggerDefinition.type webhook; const isSchedulerTrigger schedulerTriggers.includes(triggerDefinition.key); const isMcpTrigger triggerDefinition.key mcpTool; const haveValidTriggerType isWebhookOrPoll || isSchedulerTrigger || isMcpTrigger; if (!haveValidTriggerType) { throw new Error( Trigger must have a poll interval or be a webhook for ${triggerDefinition.key} ); }Google Calendar 的两个触发器均采用pollInterval: 15即每 15 分钟由调度器触发一次轮询。这是理解其行为延迟的关键新建事件后触发器最多会在 15 分钟内被捕获属于典型的近实时near-real-time方案而非 Google Calendar 推送式实时回调。四、New calendar 触发器源码解析官方描述Triggers when a new calendar is created当创建新日历时触发。完整实现位于 triggers/new-calendar/index.jsexport default defineTrigger({ name: New calendar, key: newCalendar, pollInterval: 15, description: Triggers when a new calendar is created., arguments: [], async run($) { const params { pageToken: undefined, maxResults: 250, }; do { const { data } await $.http.get(/v3/users/me/calendarList, { params, }); params.pageToken data.nextPageToken; if (data.items?.length) { for (const calendar of data.items.reverse()) { $.pushTriggerItem({ raw: calendar, meta: { internalId: calendar.etag, }, }); } } } while (params.pageToken); }, });值得注意的实现细节无需参数arguments为空数组因为当前用户的全部日历由接口自动返回不需要用户选择具体日历。分页拉取调用GET /v3/users/me/calendarList获取当前用户的日历列表每次最多 250 条maxResults: 250通过nextPageToken循环翻页直到取完所有页。时间倒序输出对当页数据执行data.items.reverse()使最新创建的日历排在最前再由引擎按顺序处理。去重依据 internalId使用日历资源的etag作为internalId。etag 是 Google API 资源的实体标签同一日历的 etag 稳定不变新建日历的 etag 则从未出现在历史记录中因此天然适合作为是否已处理过的判定键。五、New event 触发器源码解析官方描述Triggers when a new event is created当创建新事件时触发。完整实现位于 triggers/new-event/index.jsexport default defineTrigger({ name: New event, key: newEvent, pollInterval: 15, description: Triggers when a new event is created., arguments: [ { label: Calendar, key: calendarId, type: dropdown, required: true, description: , variables: false, source: { type: query, name: getDynamicData, arguments: [ { name: key, value: listCalendars, }, ], }, }, ], async run($) { const calendarId $.step.parameters.calendarId; const params { pageToken: undefined, orderBy: updated, }; do { const { data } await $.http.get(/v3/calendars/${calendarId}/events, { params, }); params.pageToken data.nextPageToken; if (data.items?.length) { for (const event of data.items.reverse()) { $.pushTriggerItem({ raw: event, meta: { internalId: event.etag, }, }); } } } while (params.pageToken); }, });它与 New calendar 的关键差异必须选择日历声明了一个必填required: true的Calendar下拉参数calendarId即触发范围被限定在用户指定的某个日历内。下拉数据来自动态数据源下拉框通过getDynamicData查询listCalendars动态数据源填充选项。该数据源实现在 dynamic-data/list-calendars/index.js它同样调用GET /v3/users/me/calendarList并分页收集所有日历最终把calendar.id作为选项值、calendar.summary作为展示名称for (const calendar of data.items) { drives.data.push({ value: calendar.id, name: calendar.summary, }); }按更新时间排序请求携带orderBy: updated让最近更新的事件排在前列配合reverse()后新创建或新修改的事件会被优先处理。注意这里事件创建在实现上体现为updated字段的排序——这是一个由源码得出的推断只要事件的etag是新的即便事件被修改也会被视为新的触发项详见下一节的去重原理。接口路径带日历 ID实际请求为GET /v3/calendars/{calendarId}/events其中calendarId来自步骤参数$.step.parameters.calendarId。六、轮询调度、去重与测试执行触发器运行时的幕后机制两个触发器都调用$.pushTriggerItem()提交触发项其运行时行为定义在 engine/global-variable.js 中理解这段逻辑是掌握触发器语义的核心pushTriggerItem: (triggerItem) { if ( isAlreadyProcessed(triggerItem.meta.internalId) !$.execution.testRun ) { // early exit as we do not want to process duplicate items in actual executions throw new AlreadyProcessedError(); } $.triggerOutput.data.push(triggerItem); if ($.execution.testRun !isWebhookApp !isFormsApp) { // early exit after receiving one item as it is enough for test execution throw new EarlyExitError(); } },由此可以提炼出三个关键行为基于 internalId 去重引擎会加载该流最近处理过的 internalId 列表flow.lastInternalIds(2000)即保留最近 2000 条当触发器提交的internalId已在列表中且当前不是测试运行testRun时直接抛出AlreadyProcessedError终止本轮避免同一个日历/事件被重复触发。这正是两个触发器都精心选用etag 作为 internalId的原因——etag 稳定且唯一。测试运行提前终止在测试模式下testRun为 true收到第一个触发项后立即抛出EarlyExitError结束执行——引擎只需一个样本即可验证触发器是否工作无需等待分页全部完成。去重窗口有限由于只保留最近 2000 条 internalId超过窗口后旧的记录会被淘汰。对于 Google Calendar 这种事件量较小的场景基本无感知但在高频率创建日历/事件且流长期运行时不处理失败的情况下理论上存在极低概率的重复触发设计流程时可考虑配合其他去重手段。轮询的调度节奏由pollInterval: 15决定——引擎按此间隔周期性调用run($)。这也意味着新建事件后立即可用并不成立实际延迟取决于上一次轮询的时间点最大约 15 分钟。七、实战建议与适用范围结合源码与官方文档使用这两个触发器时有几点实用建议选对触发器监听用户级变化任何日历被创建用New calendar监听某日历内变化用New event并明确选择目标日历。New event 的Calendar参数是必填的建流时记得先完成 Google Calendar 连接动态数据源才会返回可选项。理解延迟两者都是 15 分钟轮询不适合对时效性要求苛刻的场景若需要秒级响应应考虑其他实时通道如直接消费 Google 推送通知当前仓库未提供对应触发器。数据下行字段每个触发项都会把完整的日历/事件资源对象放在raw中后续步骤可通过变量面板直接引用如事件标题、开始时间、日历名称等字段无需额外 HTTP 请求。权限影响范围授权的calendar范围是读写级非只读calendar.readonly请只在可信环境中使用自己的 OAuth 凭据。八、总结Google Calendar 应用的触发器以简洁的官方文档为入口triggers.md背后由一套完整的源码体系支撑newCalendar监听GET /v3/users/me/calendarList的日历列表newEvent借助listCalendars动态数据源选择日历后监听GET /v3/calendars/{calendarId}/events的事件列表两者都以 15 分钟为轮询周期、以 etag 为去重标识并通过defineTrigger校验与引擎的pushTriggerItem机制保证注册合法、执行幂等。掌握这些细节后你就能在 Automatisch 中快速构建基于 Google Calendar 的自动化流例如新事件创建时发送 Slack 通知或新日历创建时写入 Google Sheets并按需评估其 15 分钟延迟对业务场景的适配性。【免费下载链接】automatischThe open source Zapier alternative. Build workflow automation without spending time and money.项目地址: https://gitcode.com/GitHub_Trending/au/automatisch创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考