mcpField
I
inngest-middleware

inngest-middleware

github.com/joelhooks开发6536 次安装2 天前更新
代码仓库

关于 inngest-middleware

面向 Inngest TypeScript 开发者的中间件指南,介绍生命周期钩子及跨函数共享逻辑的实现方式,涵盖依赖注入、错误跟踪和数据转换。

主要功能

  1. 01客户端级与函数级中间件
  2. 02依赖注入
  3. 03加密与 Sentry 错误跟踪
  4. 04指标与性能追踪
  5. 05中间件行为测试

适用场景

  1. 01为函数添加日志和指标
  2. 02跨函数共享客户端实例
  3. 03加密步骤数据并跟踪异常

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/joelhooks/joelclaw --skill inngest-middleware

安装后在 Claude Code 中输入/inngest-middleware确认已加载。

详细介绍

Inngest 中间件

掌握 Inngest 中间件,以处理日志记录、错误跟踪、依赖注入和数据转换等横切关注点。中间件会在函数生命周期的关键节点运行,从而实现强大的可观测性和共享功能模式。

这些技能侧重于 TypeScript。 对于 Python 或 Go,请参阅 Inngest 文档中的语言特定指南。核心概念适用于所有语言。

什么是中间件?

中间件允许代码在 Inngest 客户端生命周期的不同阶段运行,包括函数执行期间、发送事件时等。可以将中间件视为 Inngest 执行流水线中的钩子。

中间件的适用场景:

  • 可观测性: 添加日志记录、跟踪或指标
  • 依赖注入: 在多个函数之间共享客户端实例
  • 数据转换: 加密/解密、验证或丰富数据
  • 错误处理: 自定义错误跟踪和告警
  • 身份验证: 验证用户上下文或权限

中间件生命周期

中间件可以在客户端级别(影响所有函数)或函数级别(影响特定函数)注册。

执行顺序
const inngest = new Inngest({
  id: "my-app",
  middleware: [
    loggingMiddleware, // Runs 1st
    errorMiddleware // Runs 2nd
  ]
});

inngest.createFunction(
  {
    id: "example",
    middleware: [
      authMiddleware, // Runs 3rd
      metricsMiddleware // Runs 4th
    ]
  },
  { event: "test" },
  async () => {
    /* function code */
  }
);

顺序很重要: 客户端中间件先运行,然后按指定顺序运行函数中间件。

创建自定义中间件

基本中间件结构
import { InngestMiddleware } from "inngest";

const loggingMiddleware = new InngestMiddleware({
  name: "Logging Middleware",
  init() {
    // Setup phase - runs when client initializes
    const logger = setupLogger();

    return {
      // Function execution lifecycle
      // Note: `fn` is loosely typed in middleware generics; fn.id works at runtime
      onFunctionRun({ ctx, fn }) {
        return {
          beforeExecution() {
            logger.info("Function starting", {
              functionId: fn.id,
              eventName: ctx.event.name,
              runId: ctx.runId
            });
          },

          afterExecution() {
            logger.info("Function completed", {
              functionId: fn.id,
              runId: ctx.runId
            });
          },

          transformOutput({ result }) {
            // Log function output
            logger.debug("Function output", {
              functionId: fn.id,
              output: result.data
            });

            // Return unmodified result
            return { result };
          }
        };
      },

      // Event sending lifecycle
      onSendEvent() {
        return {
          transformInput({ payloads }) {
            logger.info("Sending events", {
              count: payloads.length,
              events: payloads.map((p) => p.name)
            });

            // Spread to convert readonly array to mutable array
            return { payloads: [...payloads] };
          }
        };
      }
    };
  }
});
Python 实现

Python 中间件遵循类似的模式。完整的 Python 示例请参阅依赖注入参考。


## Dependency Injection

Share expensive or stateful clients across all functions. **See [Dependency Injection Reference](./references/dependency-injection.md) for detailed patterns.**

### Quick Example - Built-in DI

```typescript
import { dependencyInjectionMiddleware } from "inngest";

const inngest = new Inngest({
  id: 'my-app',
  middleware: [
    dependencyInjectionMiddleware({
      openai: new OpenAI(),
      db: new PrismaClient(),
    }),
  ],
});

// Functions automatically get injected dependencies
inngest.createFunction(
  { id: "ai-summary" },
  { event: "document/uploaded" },
  async ({ event, openai, db }) => {
    // Dependencies available in function context
    const summary = await openai.chat.completions.create({
      messages: [{ role: "user", content: event.data.content }],
      model: "gpt-4",
    });

    await db.document.update({
      where: { id: event.data.documentId },
      data: { summary: summary.choices[0].message.content }
    });
  }
);

中间件包

除了 dependencyInjectionMiddleware(内置,如上所示)之外,Inngest 还通过独立包提供官方中间件。完整详情请参阅中间件参考。

加密中间件
npm install @inngest/middleware-encryption
import { encryptionMiddleware } from "@inngest/middleware-encryption";

const inngest = new Inngest({
  id: "my-app",
  middleware: [
    encryptionMiddleware({
      key: process.env.ENCRYPTION_KEY,
    })
  ]
});

自动加密所有步骤数据、函数输出和事件 data.encrypted 字段。通过 fallbackDecryptionKeys 支持密钥轮换。

Sentry 错误跟踪
npm install @inngest/middleware-sentry
import * as Sentry from "@sentry/node";
import { sentryMiddleware } from "@inngest/middleware-sentry";

Sentry.init({ /* your Sentry config */ });

const inngest = new Inngest({
  id: "my-app",
  middleware: [sentryMiddleware()]
});

捕获异常,为每次函数运行添加跟踪,并将函数 ID 和事件名称作为上下文。需要 @sentry/*@>=8.0.0。

常见中间件模式

指标和性能跟踪
const metricsMiddleware = new InngestMiddleware({
  name: "Metrics Tracking",
  init() {
    return {
      onFunctionRun({ ctx, fn }) {
        let startTime: number;

        return {
          beforeExecution() {
            startTime = Date.now();
            metrics.increment("inngest.step.started", {
              function: fn.id,
              event: ctx.event.name
            });
          },

          afterExecution() {
            const duration = Date.now() - startTime;
            metrics.histogram("inngest.step.duration", duration, {
              function: fn.id,
              event: ctx.event.name
            });
          },

          transformOutput({ result }) {
            const status = result.error ? "error" : "success";
            metrics.increment("inngest.step.completed", {
              function: fn.id,
              status: status
            });

            return { result };
          }
        };
      }
    };
  }
});
高级模式

身份验证: 验证令牌并注入用户上下文
条件逻辑: 根据事件类型或函数应用中间件
熔断器: 防止外部服务发生级联故障

基于配置的中间件

创建带有配置选项的可复用中间件,以适应不同的环境和使用场景。完整示例请参阅参考文档。

最佳实践

设计原则
  1. 保持中间件专注: 每个中间件只处理一个关注点
  2. 选择失败策略: 可选遥测功能可以优雅降级。身份验证、授权、验证和加密失败时必须拒绝访问。
  3. 考虑性能: 中间件会在每次执行时运行
  4. 使用正确的类型: 让 TypeScript 推断中间件类型
  5. 充分测试: 中间件会影响所有使用它的函数
常见实现用例
  • 重试逻辑,用于处理暂时性故障
  • 熔断器,用于外部服务调用
  • 请求/响应日志记录,用于调试
  • 从外部来源丰富用户上下文
  • 功能标志,用于逐步发布
  • 自定义身份验证和授权检查
中间件中的错误处理
const optionalTelemetryMiddleware = new InngestMiddleware({
  name: "Optional Telemetry Middleware",
  init() {
    return {
      onFunctionRun({ ctx, fn }) {
        return {
          transformOutput({ result }) {
            try {
              // Your middleware logic here
              return performTransformation(result);
            } catch (middlewareError) {
              // This example is optional telemetry only; required guards must throw.
              console.error("Middleware error:", middlewareError);

              // Optional telemetry only. Security/validation middleware must propagate failure.
              return { result };
            }
          }
        };
      }
    };
  }
});
测试中间件

使用 Inngest 的测试工具(createMockContext、createMockFunction)对中间件行为进行单元测试。

完整实现示例和高级模式请参阅:

评论

支持 Markdown