尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

使用 AWS Lambda 作为 Hasura GraphQL Engine 事件触发器 Webhook 的 Node.js 实战指南

使用 AWS Lambda 作为 Hasura GraphQL Engine 事件触发器 Webhook 的 Node.js 实战指南 使用 AWS Lambda 作为 Hasura GraphQL Engine 事件触发器 Webhook 的 Node.js 实战指南【免费下载链接】graphql-engineBlazing fast, instant realtime GraphQL APIs on all your data with fine grained access control, also trigger webhooks on database events.项目地址: https://gitcode.com/gh_mirrors/gr/graphql-engine导读本文基于 Hasura GraphQL Engine 官方仓库中的 aws-lambda/nodejs8/echo 示例完整讲解如何把 AWS Lambda 函数接入 Hasura Event Trigger在数据库发生INSERT/UPDATE/DELETE操作时自动接收事件负载并执行异步业务逻辑。读完本文你将掌握事件触发负载payload的结构、Lambda 的创建与配置步骤、index.handler的编写方式以及如何在 Hasura Console 中把 Lambda 的 API 端点注册为 Webhook并了解在此基础上扩展出写回数据库等高级用法的实现思路。什么是 Event Trigger为什么选择 AWS LambdaHasura Event Trigger 是 Hasura GraphQL Engine 提供的一种异步业务逻辑机制当连接的数据库中某张表发生数据变更时Hasura 会以 HTTPPOST请求将事件负载发送到你配置的 Webhook 端点参见 docs/docs/event-triggers/overview.mdx。Event Trigger 可配置为在表的INSERT、UPDATE、DELETE事件上触发也可以在 Console 中通过按钮手动触发。把 Webhook 部署在 AWS Lambda 上的好处在于无需维护常驻服务器按调用次数计费天然适合数据库事件 → 异步处理这种低频、突发的调用模式。仓库 community/boilerplates/event-triggers/README.md 给出的整体架构如下从源码目录看aws-lambda 下按语言组织了多个官方示例Node.jsnodejs8目录下包含两个用例目录用途echo回显触发器负载本文主体mutation在收到 insert 事件后用 GraphQL mutation 向数据库写回关联数据第一步在数据库中准备notes表Event Trigger 必须挂在某张表上。官方示例使用一张简单的notes表你可以在 Hasura Console 的 Data 页签中创建也可以在 SQL 中执行建表语句。字段定义如下notes: id: int note: text字段含义id整数类型作为主键示例中默认为自增mutation 示例中明确为Integer auto-incrementnote文本类型存放便签内容。该表将成为后面验证事件负载的载体插入、更新、删除notes表的数据时对应的 Lambda 就会被触发。第二步理解 Event Trigger 的 Webhook 负载结构在动手写 Lambda 之前先理解 Hasura 发送给 Webhook 的数据格式这是正确解析index.js中event.body的关键。官方文档 docs/docs/event-triggers/payload.mdx 定义了完整的负载结构{ payload: { created_at: TIMESTAMP, delivery_info: { current_retry: RETRY_NUMBER, max_retries: MAX_RETRIES }, event: { data: { new: OBJECT_OF_COLUMNS_AND_VALUES, old: OBJECT_OF_COLUMNS_AND_VALUES|NULL }, op: INSERT|UPDATE|DELETE|MANUAL, session_variables: { x-hasura-role: ROLE_NAME }, trace_context: { span_id: SPAN_ID, trace_id: TRACE_ID } }, id: UUID_FOR_INVOCATION, table: { name: TABLE_NAME, schema: SCHEMA_NAME }, trigger: { name: TRIGGER_NAME } } }核心字段说明完整字段表见 payload.mdx字段类型说明created_atString触发器被调用的时间戳delivery_info.current_retry/max_retriesInteger当前重试次数 / 最大重试次数event.opString操作名取值仅为INSERT、UPDATE、DELETE、MANUALevent.data.newObject事件相关的新数据键值对为列名-值event.data.oldObject 或null事件相关的旧数据不适用时为nullevent.session_variablesObject触发事件的用户的 session 变量Postgres 下可用idString本次调用的 UUIDtable.name/table.schemaString表名 / schema 名trigger.nameString触发器名不同操作下new/old的取值规则PostgresINSERTold为nullnew为插入的行UPDATEold为更新前的值new为更新后的值DELETEold为被删除的行new为nullMANUALold为nullnew为当前行。此外官方文档还说明UPDATE事件只在新数据与旧数据不同时才投递表计算字段不会包含在负载中。Webhook 返回2xx状态码被视为调用成功其他状态码会按重试配置触发重试若响应携带Retry-After头且状态码为非2xx则事件会在指定秒数后再次投递可用于限流/防抖。第三步在 AWS 上创建 Lambda 函数按 echo/README.md 的步骤在 AWS 控制台完成配置在 AWS Lambda 控制台创建一个函数运行时选择Node.js 8.10选择start from scratch从头开始创作添加API Gateway作为触发器在 API Gateway 中新建一个 API这样 Lambda 就获得了一个可供 Hasura 调用的 HTTP 端点把下文 index.js 的代码粘贴进函数编辑器处理函数即为index.handler。环境说明示例基于 Node.js 8.10 编写当时 Lambda 的主流运行时。当前 AWS 已提供更新的 Node.js 运行时代码中的 async/await 语法在更高版本中同样可用运行时版本升级不影响示例逻辑本身。第四步深入解析index.handler源码这是本次示例的核心文件echo/index.js。它演示了如何解析 Hasura 事件负载并按操作类型回显消息exports.handler async (event) { let response {} try { let { table: { name }, event: { op, data } } event.body; response.statusCode 200; if (name notes op INSERT) { response.body New note ${data.new.id} inserted, with data: ${data.new.note}; } else if (name notes op UPDATE) { response.body Note ${data.new.id} updated, with data: ${data.new.note}; } else if (name notes op DELETE) { response.body Note ${data.old.id} deleted, with data: ${data.old.note}; } return response } catch (e) { response.statusCode 400; response.body cannot parse hasura event; return response } };逐段解读其设计1. 从event.body解构负载let { table: { name }, event: { op, data } } event.body;注意这里解构的是event.bodyLambda 通过 API Gateway 收到的 HTTP 请求体而不是event本身。对照上面的负载结构table.name对应payload.table.nameevent.op对应payload.event.opdata对应payload.event.data。需要强调的是仓库中这份示例对event.body直接解构说明作者在创建 API Gateway 触发器时未开启 Lambda 代理集成若开启代理集成event.body会是 JSON 字符串需要先JSON.parse才能解构你在实际部署时需根据自己的 API Gateway 配置做相应调整。2. 按操作类型分支处理INSERTdata.new携带新行读取data.new.id和data.new.noteUPDATEdata.new携带更新后的行DELETE此时data.new为null必须读取data.old.id与data.old.note——这是示例中体现不同操作读取不同数据段的关键细节。3. 异常兜底整个解构与分支放在try/catch中一旦负载格式不符例如 Webhook 被非 Hasura 的请求调用返回400与cannot parse hasura event。这符合官方对 Webhook 响应约定2xx表示成功其他状态码会触发重试或告警。第五步在 Hasura Console 中添加 Event Trigger完成 Lambda 部署并记下 API Gateway 的端点 URL 后回到 Hasura Console 配置触发器进入Events页签点击添加触发器选择notes表并勾选全部操作insert、update、delete把 AWS Lambda 的API 端点 URL粘贴为Webhook地址保存后触发器的状态变为活跃active。至此链路打通任何对notes表的插入、更新、删除操作都会触发 Hasura 向你的 Lambda 端点发送POST请求Lambda 解析负载并按操作类型返回响应消息。可以在 Console 的 Events 页签中看到每次事件的投递记录、响应状态码与重试信息用于验证整条链路是否工作正常。进阶在 Lambda 中通过 GraphQL Mutation 写回数据库echo示例只做回显同目录下的 mutation/index.js 展示了更有业务价值的模式在收到事件后调用 Hasura 的 GraphQL 端点向数据库写入关联数据。其部署步骤比 echo 多两步详见 mutation/README.md在mutation目录执行npm install安装依赖使用node-fetch发起 HTTP 请求执行zip -r hge-mutation.zip .打成 zip 包在 Lambda 中上传该 zip而非粘贴代码在 Lambda 环境变量中配置两项ACCESS_KEY你初始化 Hasura GraphQL Engine 时配置的 admin secretHGE_ENDPOINTHGE 实例运行的 URL。代码的核心逻辑是当notes表发生 insert 事件时用旧行数据构造一个 GraphQL mutation把note_revision表的记录写回数据库const query mutation updateNoteRevision ($noteId: Int!, $data: String!) { insert_note_revision (objects: [ { note_id: $noteId, note: $data } ]) { affected_rows } } ; exports.handler async (event) { try { const qv { noteId: event.body.event.data.old.id, data: event.body.event.data.old.note }; const result await fetch(hgeEndpoint /v1/graphql, { method: POST, body: JSON.stringify({ query: query, variables: qv }), headers: { Content-Type: application/json, x-hasura-admin-secret: accessKey }, }); // ... } };这段代码演示了三个要点用环境变量保存敏感信息ACCESS_KEY与HGE_ENDPOINT通过process.env读取避免硬编码以 admin secret 调用 GraphQL API请求头中的x-hasura-admin-secret用于绕过权限校验执行写操作mutation 携带变量variables中的noteId、data与 GraphQL 查询的$noteId、$data一一对应而数据来源正是事件负载中event.data.old的旧行。对应的note_revision表需要在 Hasura Console 中预先创建Table name: note_revision Columns: id: Integer auto-increment note: Text note_id: Integer (foreign key to notes.id) update_at: Timestamp, default now()扩展阅读与仓库参考事件触发器官方文档事件触发负载结构见 docs/docs/event-triggers/payload.mdx总览见 docs/docs/event-triggers/overview.mdxAWS Lambda 目录总览与多语言支持情况见 community/boilerplates/event-triggers/aws-lambda/README.md同一用例还提供 Go、Python、Ruby 等语言实现如 python/echo/echo.py其他 Serverless 平台示例仓库还包含 Azure Functions、Google Cloud Functions、Netlify Functions、Zeit Now 等平台的同款 boilerplate可对照参考。本文的完整示例代码与部署文档均位于仓库 community/boilerplates/event-triggers/aws-lambda/nodejs8/ 目录下可直接查看、复制并据此部署。【免费下载链接】graphql-engineBlazing fast, instant realtime GraphQL APIs on all your data with fine grained access control, also trigger webhooks on database events.项目地址: https://gitcode.com/gh_mirrors/gr/graphql-engine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表