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

资讯详情

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

Hasura Event Triggers 实战:用 AWS Lambda(Python)在数据变更时自动写入修订历史

Hasura Event Triggers 实战:用 AWS Lambda(Python)在数据变更时自动写入修订历史 Hasura Event Triggers 实战用 AWS LambdaPython在数据变更时自动写入修订历史【免费下载链接】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本文以仓库 community/boilerplates/event-triggers/aws-lambda/python/mutation 示例为骨架完整讲解在 Hasura GraphQL EngineHGE中配置事件触发器Event Triggers并以 Python 3.6 编写 AWS Lambda 作为 Webhook在notes表发生数据变更时自动向note_revision表写入一条修订记录的端到端方案。读完本文你将掌握事件触发器的建表准备、Lambda 部署与鉴权配置、事件 payload 解析以及通过 GraphQL Mutation 回写数据库的完整链路。一、场景与原理为什么需要一个mutation型 WebhookHasura GraphQL Engine 的事件触发器允许你在数据库表发生INSERT、UPDATE、DELETE以及手动触发MANUAL时通过 HTTPPOST将事件 payload 投递到你指定的 Webhook 端点详见仓库文档 docs/docs/event-triggers/payload.mdx。本示例的用途很典型为notes便签表维护一份修订历史。每当便签内容被修改或删除时Lambda 读取事件 payload 中的旧值再通过 GraphQL Mutation 把旧内容追加写入note_revision修订记录表。这是事件触发器的经典用法——在数据库事件发生时执行写回数据库的联动逻辑而不是像 echo 示例那样只回显 payload。事件 payload 的核心结构如下完整字段说明见 payload.mdx{ payload: { created_at: 2020-07-29T10:00:00.000Z, delivery_info: { current_retry: 0, max_retries: 0 }, event: { data: { new: { id: 1, note: 新内容 }, old: null }, op: INSERT, session_variables: { x-hasura-role: admin }, trace_context: { span_id: 123, trace_id: 456 } }, id: 123e4567-e89b-12d3-a456-426614174000, table: { name: notes, schema: public }, trigger: { name: log_note_revision } } }不同操作类型下event.data.old与event.data.new的取值规则PostgresINSERTold为nullnew为插入后的行UPDATEold为更新前的值new为更新后的值DELETEold为被删除的行new为nullMANUALold为nullnew为当前行。二、第一步创建数据表先在 Hasura Console 中创建两张表来自原文档的建表规格Table name: notes Columns: id: Integer auto-increment note: Text Table name: note_revision Columns: id: Integer auto-increment note: Text note_id: Integer (foreign key to notes.id) update_at: Timestamp, default now()要点说明notes是业务主表id为自增主键note保存便签正文note_revision是历史表通过note_id外键关联到notes.idupdate_at使用数据库默认值now()自动记录修订时间两张表都建议在 Console 的 Data 选项卡下通过Create Table界面创建外键约束可以在建表后通过 Modify 或 SQL 界面添加。三、第二步在 AWS 上创建 Lambda 函数在 AWS 控制台创建 Lambda 函数它将作为事件触发器的 Webhook进入 Lambda 服务点击Create a function选择运行时Python 3.6示例代码基于该运行时编写选择Start from scratch从零创建不套模板在函数配置中为函数添加API Gateway 触发器并新建一个 API这样 Hasura 才能通过 HTTP 调用到函数将 mutation.py 中的代码粘贴到函数编辑器Lambda 的 handler 设为mutation.lambda_handler即文件名.函数名在函数的Environment variables中配置两个环境变量ADMIN_SECRET你初始化 HGE 时配置的 admin secret 密钥HGE_ENDPOINTHGE 实例运行的 URL。注意不同语言的示例对环境变量的命名略有差异。Node.js 与 Ruby 版本使用ACCESS_KEY见 nodejs8/mutation/index.js 与 ruby/mutation/lambda_function.rb而 Python 版本统一使用ADMIN_SECRET。部署时请与所选语言的代码保持一致。部署完成后记录 API Gateway 为 Lambda 生成的API 端点 URL下一步配置触发器时要用它作为 Webhook 地址。四、深入解析 mutation.pyLambda 如何解析事件并回写数据库示例核心代码位于 community/boilerplates/event-triggers/aws-lambda/python/mutation/mutation.py其逻辑可拆解为四个阶段。4.1 初始化读取环境变量并拼接 GraphQL 端点import os import json from botocore.vendored import requests ADMIN_SECRET os.environ[ADMIN_SECRET] HGE_ENDPOINT os.environ[HGE_ENDPOINT] HGE_URL HGE_ENDPOINT /v1/graphql HEADERS { Content-Type: application/json, X-Hasura-Admin-Secret: ADMIN_SECRET, }通过os.environ读取ADMIN_SECRET与HGE_ENDPOINT二者缺一不可将端点与/v1/graphql拼接得到 GraphQL 入口 URLNode.js 版本同样拼接/v1/graphql请求头携带X-Hasura-Admin-Secret完成管理端鉴权这正是服务端源码中校验 admin secret 所用的标准请求头相关实现见 server/src-lib/Hasura/Authentication/User.hs 与 server/src-lib/Hasura/Authentication/Session.hs。4.2 定义回写用的 GraphQL Mutationquery mutation updateNoteRevision ($noteId: Int!, $data: String!) { insert_note_revision (objects: [ { note_id: $noteId, note: $data } ]) { affected_rows } } Mutation 名为updateNoteRevision接受$noteIdInt与$dataString两个变量通过insert_note_revision向修订表插入一条记录objects数组按变量填充note_id与note字段返回affected_rows用于确认写入影响的行数Go 版本还会额外返回returning { id }见 go/mutation/mutation.go。4.3 解析事件 payload 并提取旧值def lambda_handler(event, context): try: body json.loads(event[body]) except: return { statusCode: 400, body: json.dumps({message: Unable to parse request body}) } data body[event][data] qv {noteId: data[old][id], data: data[old][note]} jsonBody {query: query, variables: qv} resp requests.post(HGE_URL, datajson.dumps(jsonBody), headersHEADERS) my_json resp.json() print(my_json) return { statusCode: 200, body: json.dumps({message: success}) }读取 bodyAPI Gateway 在转发请求时会把原始 HTTP body 放入event[body]字段因此先json.loads(event[body])还原事件 payload解析失败则返回400定位数据body[event][data]即事件的新旧数据对象与第一节的 payload 结构一一对应提取旧值data[old][id]与data[old][note]组装成 Mutation 变量noteId与data。从源码结构可以推断该示例的语义是把变更前的旧内容存入修订表因此对UPDATE保存更新前版本和DELETE留存删除前记录天然适用而对INSERT操作old为null直接取值会抛出异常——如果你希望同时处理插入事件需要自行补充对data[new]的分支判断调用 HGE通过requests.post携带 admin secret 头向/v1/graphql发起 Mutation并把响应打印到日志可到 CloudWatch Logs 查看返回结果成功时返回200与{message: success}。根据 payload.mdx 的说明Webhook 返回2xx即视为投递成功非2xx会按重试配置重发若返回体中带有Retry-After头事件会按指定秒数再次投递。五、第三步在 Hasura 中添加事件触发器回到 Hasura Console完成触发器配置进入Events事件选项卡点击Add a trigger添加触发器为触发器指定名称选择操作类型为Insert、Update、Delete 全部勾选示例要求覆盖所有写操作选择目标表notes将上一步记录下的AWS Lambda API 端点 URL粘贴为Webhook URL保存触发器后HGE 会在notes表发生对应操作时把事件 payload 以 HTTPPOSTContent-Type: application/json投递到该端点。配置完成后在 Console 的 GraphiQL 或 Data 页面往notes表插入/更新/删除一条数据即可在 AWS CloudWatch 中看到 Lambda 的调用日志并在note_revision表中查询到自动生成的修订记录。六、多语言实现对照同一套逻辑的不同写法该 Boilerplate 目录community/boilerplates/event-triggers/aws-lambda/README.md提供了多种语言实现便于迁移到不同技术栈语言文件差异点Python 3.6python/mutation/mutation.py使用botocore.vendored.requests环境变量为ADMIN_SECRETNode.js 8nodejs8/mutation/index.js使用node-fetchhandler 为index.handler直接读取event.body.event.data.old并用errors判断调用失败Rubyruby/mutation/lambda_function.rb使用标准库net/http根据uri.scheme自动决定是否启用 SSLGogo/mutation/mutation.go用结构体严格建模HasuraEventpayload对缺失字段如note id not found返回明确的错误响应这些实现共享同一个 Mutation 语义插入note_revision是理解事件触发器在不同运行时下解析方式的绝佳对照材料。七、注意事项与生产化建议鉴权安全ADMIN_SECRET是 HGE 的管理员密钥切勿硬编码在代码中应通过 Lambda 环境变量或 AWS Secrets Manager 管理同理X-Hasura-Admin-Secret请求头只应在受信后端之间传递INSERT 与 old 数据示例代码只读取data[old]生产环境如需覆盖插入事件请补充对data[new]的处理与空值判断payload 规则见 payload.mdx幂等性Webhook 失败后会按重试配置重复投递payload 中的delivery_info.current_retry/max_retries标识重试次数业务逻辑应具备幂等性避免重复写入修订记录日志观测Lambda 中的print(my_json)会把 HGE 返回结果写入 CloudWatch Logs这是排查 Mutation 是否成功的最直接手段运行时版本示例基于 Python 3.6 / Node.js 8 等较旧运行时编写实际部署时建议在 AWS 当前支持的运行时下做兼容性验证并同步升级requests等依赖的引用方式例如用独立的requests包替代botocore.vendored.requests。【免费下载链接】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),仅供参考
返回列表