inngest-middleware

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Inngest Middleware

Inngest中间件

Master Inngest middleware to handle cross-cutting concerns like logging, error tracking, dependency injection, and data transformation. Middleware runs at key points in the function lifecycle, enabling powerful patterns for observability and shared functionality.
These skills are focused on TypeScript. For Python or Go, refer to the Inngest documentation for language-specific guidance. Core concepts apply across all languages.
掌握Inngest中间件,处理日志、错误追踪、依赖注入和数据转换等横切关注点。中间件在函数生命周期的关键节点运行,为可观测性和共享功能提供强大的实现模式。
本技能聚焦于TypeScript。 对于Python或Go语言,请参考Inngest documentation获取语言特定的指导。核心概念适用于所有语言。

What is Middleware?

什么是中间件?

Middleware allows code to run at various points in an Inngest client's lifecycle - during function execution, event sending, and more. Think of middleware as hooks into the Inngest execution pipeline.
When to use middleware:
  • Observability: Add logging, tracing, or metrics
  • Dependency injection: Share client instances across functions
  • Data transformation: Encrypt/decrypt, validate, or enrich data
  • Error handling: Custom error tracking and alerting
  • Authentication: Validate user context or permissions
中间件允许代码在Inngest客户端的生命周期各个阶段运行——包括函数执行、事件发送等场景。可以将中间件视为Inngest执行流程中的钩子。
何时使用中间件:
  • 可观测性: 添加日志、追踪或指标
  • 依赖注入: 在多个函数间共享客户端实例
  • 数据转换: 加密/解密、验证或丰富数据
  • 错误处理: 自定义错误追踪和告警
  • 身份验证: 验证用户上下文或权限

Middleware Lifecycle

中间件生命周期

Middleware can be registered at client-level (affects all functions) or function-level (affects specific functions).
中间件可以注册在客户端级别(影响所有函数)或函数级别(影响特定函数)。

Execution Order

执行顺序

typescript
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 */
  }
);
Order matters: Client middleware runs first, then function middleware, in the order specified.
typescript
const inngest = new Inngest({
  id: "my-app",
  middleware: [
    loggingMiddleware, // 第1个运行
    errorMiddleware // 第2个运行
  ]
});

inngest.createFunction(
  {
    id: "example",
    middleware: [
      authMiddleware, // 第3个运行
      metricsMiddleware // 第4个运行
    ]
  },
  { event: "test" },
  async () => {
    /* 函数代码 */
  }
);
顺序很重要: 客户端中间件先运行,然后是函数级中间件,按照指定的顺序执行。

Creating Custom Middleware

创建自定义中间件

Basic Middleware Structure

基础中间件结构

typescript
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
      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)
            });

            // Return unmodified payloads
            return { payloads };
          }
        };
      }
    };
  }
});
typescript
import { InngestMiddleware } from "inngest";

const loggingMiddleware = new InngestMiddleware({
  name: "Logging Middleware",
  init() {
    // 初始化阶段 - 客户端初始化时运行
    const logger = setupLogger();

    return {
      // 函数执行生命周期
      onFunctionRun({ ctx, fn }) {
        return {
          beforeExecution() {
            logger.info("函数启动", {
              functionId: fn.id,
              eventName: ctx.event.name,
              runId: ctx.runId
            });
          },

          afterExecution() {
            logger.info("函数完成", {
              functionId: fn.id,
              runId: ctx.runId
            });
          },

          transformOutput({ result }) {
            // 记录函数输出
            logger.debug("函数输出", {
              functionId: fn.id,
              output: result.data
            });

            // 返回未修改的结果
            return { result };
          }
        };
      },

      // 事件发送生命周期
      onSendEvent() {
        return {
          transformInput({ payloads }) {
            logger.info("发送事件", {
              count: payloads.length,
              events: payloads.map((p) => p.name)
            });

            // 返回未修改的负载
            return { payloads };
          }
        };
      }
    };
  }
});

Python Implementation

Python实现

Python middleware follows a similar pattern. See Dependency Injection Reference for complete Python examples.
undefined
Python中间件遵循类似的模式。完整的Python示例请参阅Dependency Injection Reference

Dependency Injection

依赖注入

Share expensive or stateful clients across all functions. See Dependency Injection Reference for detailed patterns.
在所有函数间共享资源密集型或有状态的客户端。有关详细模式,请参阅Dependency Injection Reference

Quick Example - Built-in DI

快速示例 - 内置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 }
    });
  }
);
typescript
import { dependencyInjectionMiddleware } from "inngest";

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

// 函数会自动获取注入的依赖
inngest.createFunction(
  { id: "ai-summary" },
  { event: "document/uploaded" },
  async ({ event, openai, db }) => {
    // 依赖在函数上下文中可用
    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 }
    });
  }
);

Built-in Middleware

内置中间件

Inngest provides pre-built middleware for common use cases. See Built-in Middleware Reference for complete implementation details.
Inngest为常见使用场景提供了预构建的中间件。完整的实现细节请参阅Built-in Middleware Reference

Encryption Middleware

加密中间件

typescript
import { encryptionMiddleware } from "inngest";

const inngest = new Inngest({
  id: "my-app",
  middleware: [
    encryptionMiddleware({
      key: process.env.ENCRYPTION_KEY
      // Automatically encrypt/decrypt sensitive data
    })
  ]
});
typescript
import { encryptionMiddleware } from "inngest";

const inngest = new Inngest({
  id: "my-app",
  middleware: [
    encryptionMiddleware({
      key: process.env.ENCRYPTION_KEY
      // 自动加密/解密敏感数据
    })
  ]
});

Sentry Error Tracking

Sentry错误追踪

typescript
import { sentryMiddleware } from "inngest";

const inngest = new Inngest({
  id: "my-app",
  middleware: [
    sentryMiddleware({
      dsn: process.env.SENTRY_DSN
      // Auto-capture errors and performance data
    })
  ]
});
typescript
import { sentryMiddleware } from "inngest";

const inngest = new Inngest({
  id: "my-app",
  middleware: [
    sentryMiddleware({
      dsn: process.env.SENTRY_DSN
      // 自动捕获错误和性能数据
    })
  ]
});

Common Middleware Patterns

常见中间件模式

Metrics and Performance Tracking

指标与性能追踪

typescript
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 };
          }
        };
      }
    };
  }
});
typescript
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 };
          }
        };
      }
    };
  }
});

Advanced Patterns

高级模式

Authentication: Validate tokens and inject user context Conditional logic: Apply middleware based on event type or function Circuit breakers: Prevent cascading failures from external services
身份验证: 验证令牌并注入用户上下文 条件逻辑: 根据事件类型或函数应用中间件 断路器: 防止外部服务故障引发级联失败

Configuration-Based Middleware

基于配置的中间件

Create reusable middleware with configuration options for different environments and use cases. See reference documentation for complete examples.
创建可复用的中间件,为不同环境和使用场景提供配置选项。完整示例请参阅参考文档。

Best Practices

最佳实践

Design Principles

设计原则

  1. Keep middleware focused: One concern per middleware
  2. Handle errors gracefully: Don't let middleware crash functions
  3. Consider performance: Middleware runs on every execution
  4. Use proper typing: Let TypeScript infer middleware types
  5. Test thoroughly: Middleware affects all functions that use it
  1. 保持中间件聚焦: 每个中间件只处理一个关注点
  2. 优雅处理错误: 不要让中间件导致函数崩溃
  3. 考虑性能: 中间件会在每次执行时运行
  4. 使用正确的类型: 让TypeScript自动推断中间件类型
  5. 充分测试: 中间件会影响所有使用它的函数

Common Use Cases to Implement

推荐实现的常见场景

  • Retry logic for transient failures
  • Circuit breakers for external service calls
  • Request/response logging for debugging
  • User context enrichment from external sources
  • Feature flags for gradual rollouts
  • Custom authentication and authorization checks
  • 重试逻辑 处理临时故障
  • 断路器 用于外部服务调用
  • 请求/响应日志 用于调试
  • 用户上下文 enrichment 从外部源获取
  • 功能标志 用于逐步发布
  • 自定义身份验证 和授权检查

Error Handling in Middleware

中间件中的错误处理

typescript
const robustMiddleware = new InngestMiddleware({
  name: "Robust Middleware",
  init() {
    return {
      onFunctionRun({ ctx, fn }) {
        return {
          transformOutput({ result }) {
            try {
              // Your middleware logic here
              return performTransformation(result);
            } catch (middlewareError) {
              // Log error but don't break the function
              console.error("Middleware error:", middlewareError);

              // Return original result on middleware failure
              return { result };
            }
          }
        };
      }
    };
  }
});
typescript
const robustMiddleware = new InngestMiddleware({
  name: "Robust Middleware",
  init() {
    return {
      onFunctionRun({ ctx, fn }) {
        return {
          transformOutput({ result }) {
            try {
              // 你的中间件逻辑在这里
              return performTransformation(result);
            } catch (middlewareError) {
              // 记录错误但不中断函数
              console.error("中间件错误:", middlewareError);

              // 中间件失败时返回原始结果
              return { result };
            }
          }
        };
      }
    };
  }
});

Testing Middleware

测试中间件

Use Inngest's testing utilities (
createMockContext
,
createMockFunction
) to unit test middleware behavior.
For complete implementation examples and advanced patterns, see:
  • Dependency Injection Reference
  • Built-in Middleware Reference
使用Inngest的测试工具(
createMockContext
createMockFunction
)对中间件行为进行单元测试。
完整的实现示例和高级模式,请参阅:
  • Dependency Injection Reference
  • Built-in Middleware Reference