关于 convex-mutations
面向开发者的 Convex mutation 实现指南,涵盖函数定义、数据库写入、事务和任务调度模式。
主要功能
- 01Mutation 定义与注册
- 02参数验证模式
- 03数据库插入、更新、替换与删除
- 04事务与一致性
- 05后台任务调度
适用场景
- 01添加写入 Convex 数据的 mutation
- 02安排未来执行的操作或 mutation
- 03协调函数间的 mutation 调用
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ sstobo/ convex-skills --skill convex-mutations安装后在 Claude Code 中输入/convex-mutations确认已加载。
附带文件references/mutation-guidelines.md
详细介绍
Convex 变更技能
本技能为实现 Convex 变更函数提供专门指导,涵盖函数定义、注册、数据库操作和调度模式的最佳实践。
何时使用本技能
在以下情况下使用本技能:
- 定义新的变更函数以在 Convex 数据库中写入或修改数据
- 执行数据库操作(
insert、patch、replace、delete) - 从其他 Convex 函数中调用变更
- 使用
ctx.scheduler.runAfter调度未来的变更 - 处理事务性操作
- 协调变更与 action 以进行后台处理
技能资源
本技能在 references/mutation-guidelines.md 中提供了全面的参考文档,涵盖:
核心变更开发
- 使用新函数语法定义函数的语法
- 变更注册(
mutation和internalMutation) - 参数校验器及其用法
- 函数调用模式(
ctx.runQuery和ctx.runMutation) - 函数引用(
api和internal对象) - 基于文件的路由以确定变更路径
数据库操作
ctx.db.insert()- 创建新文档ctx.db.patch()- 将更新浅合并到现有文档ctx.db.replace()- 完全替换现有文档- 文档缺失时的错误处理
- 事务语义与一致性保证
高级变更功能
- 调度:使用
ctx.scheduler.runAfter()将后台任务加入队列- 调度变更和 action 以供将来执行
- 理解认证状态不会传播到已调度的任务
- 对需要权限的已调度任务使用内部函数
- 避免紧密循环并遵守 10 秒最小间隔
- 事务行为:理解变更事务
- 将调度器任务入队在变更中是事务性的
- 通过事务边界防止竞态条件
函数组合
- 在变更中调用查询以进行校验
- 从变更中调用变更
- 对同一文件中的变更调用使用返回类型注解
如何使用本技能
- 阅读参考文档
references/mutation-guidelines.md,了解完整的变更模式 - 遵循语法示例,使用正确的校验器定义变更函数
- 根据需求使用适当的数据库操作(
insert、patch、replace) - 使用
ctx.scheduler.runAfter调度后台工作,以处理长时间运行的操作 - 请记住认证状态不会传播到已调度的任务;对特权操作使用内部函数
- 利用事务确保多个操作之间的一致性
关键变更指南
- 始终为所有变更函数包含参数校验器
- 对部分更新使用
ctx.db.patch(),对完全替换使用ctx.db.replace() - 使用
ctx.scheduler.runAfter()调度 action(例如 AI 响应、通知) - 请记住已调度的任务的认证状态为
null;请改用内部函数 - 变更的执行时间最多为 1 秒,最多可写入 8192 个文档
- 如果变更没有显式返回值,则隐式返回
null - 在同一文件中调用变更时使用返回类型注解(TypeScript 循环引用的变通方案)
示例:带数据库操作和调度的变更
import { mutation, internalAction } from "./_generated/server";
import { v } from "convex/values";
import { internal } from "./_generated/api";
export const sendMessage = mutation({
args: {
channelId: v.id("channels"),
authorId: v.id("users"),
content: v.string(),
},
handler: async (ctx, args) => {
// Validate channel and user exist
const channel = await ctx.db.get(args.channelId);
if (!channel) {
throw new Error("Channel not found");
}
// Insert message into database
await ctx.db.insert("messages", {
channelId: args.channelId,
authorId: args.authorId,
content: args.content,
});
// Schedule AI response generation (transactional)
await ctx.scheduler.runAfter(0, internal.functions.generateResponse, {
channelId: args.channelId,
});
return null;
},
});
export const updateUserStatus = mutation({
args: {
userId: v.id("users"),
status: v.string(),
},
handler: async (ctx, args) => {
// Patch updates an existing document with shallow merge
await ctx.db.patch(args.userId, {
status: args.status,
lastUpdated: Date.now(),
});
return null;
},
});
如需更详细的信息和其他模式,请参阅完整的参考文档。
评论
支持 Markdown