inngest-js

repository·main·Indexed 21 days ago

https://github.com/inngest/inngest-js

JavaScript/TypeScript client for Inngest, featuring Durable Endpoints to transform HTTP handlers into fault-tolerant, resumable workflows using step.run(). Includes the @inngest/ai adapter for type-safe AI provider integration (OpenAI, Anthropic, Gemini) via step.ai.infer, and framework templates for Bun, Next.js, Astro, ElysiaJS, Express, and Fastify.

Tokens
38.6K
Snippets
129
Records
199
Agent score
75%

What's inside inngest-js

  1. What is @inngest/otel?

    main

    The @inngest/otel package provides turnkey OpenTelemetry instrumentation helpers for Inngest. It is designed to automatically install supported instrumentations before your application code starts, making it a low-effort way to set up Node.js OpenTelemetry.

    While this package is recommended for a quick setup, you can still configure OpenTelemetry manually if you require direct control over providers, exporters, sampling, resources, or specific instrumentation lists.

  2. Explore Realtime implementation examples

    main

    The core inngest SDK includes a built-in realtime implementation. You can find various implementation patterns in the following example directories:

    • Next.js Hooks: Using realtime features with React hooks in a Next.js environment (next-realtime-hooks).
    • Background Jobs with Realtime: Synchronizing background job progress or status with a Next.js frontend (nextjs-bg-jobs-realtime).
    • Multi-channel Realtime: Managing realtime communication across multiple distinct channels (realtime-across-multiple-channels).
    • Human-in-the-loop: Implementing workflows that require real-time user interaction or approval (realtime-human-in-the-loop).
    • Single-run Subscriptions: Subscribing to updates for a specific, individual function run (single-run-subscription).
  3. Supported AI Providers in @inngest/ai

    main

    The @inngest/ai package provides type-safe adapters for the following providers:

    • OpenAI: GPT models and embeddings
    • Anthropic: Claude models
    • Google Gemini: Gemini models (including thinking features)
    • Grok: Grok models (OpenAI-compatible)
    • Azure OpenAI: Azure-hosted OpenAI models
  4. Explore Inngest features in the Next.js starter

    main

    The Next.js starter project provides an interactive tour of several core Inngest capabilities:

    • Triggering Functions: Learn how to trigger an Inngest function and observe its output.
    • Multi-Step Functions and Streaming: See how functions can be divided into fault-tolerant steps and how to stream updates directly to a UI.
    • Fault Tolerance with Retries: Observe how Inngest handles failures and manages retries using a function designed to fail intentionally.
    • Flow Control (Throttling): Learn how to use throttling to control function execution, which is useful for handling rate limits on 3rd party APIs.

    All demo function logic is located in src/lib/demo-functions.ts.

  5. Encrypt event data using middleware

    main

    Beyond encrypting step state, you can also encrypt all incoming event data using a full encryption middleware approach. This ensures that the payload of the event triggering the function is also protected.

    Important Operational Warnings:

    • Feature Limitations: Encrypting event data disables Inngest features that rely on inspecting event payloads, such as using expressions with step.waitForEvent() or browsing event data in the Inngest dashboard.
    • System Integration: Event data is often shared between different systems. Consider whether encrypting the event data at the source is appropriate for your architecture.
  6. Instrumentations provided by @inngest/otel

    main

    When used as a preload, @inngest/otel automatically registers the following instrumentations:

    • Common Node.js library instrumentation (via @opentelemetry/auto-instrumentations-node)
    • OpenAI instrumentation (via @traceloop/instrumentation-openai)
    • Anthropic instrumentation (via @traceloop/instrumentation-anthropic)
    • Google Generative AI instrumentation (via @traceloop/instrumentation-google-generativeai)

    Note: @google/genai v2 is not currently supported by the Traceloop Google Generative AI instrumentation.

  7. How logging works in the Worker Thread strategy

    main

    Because the SDK's Logger instance is not serializable across the worker thread boundary and is bound to the main thread's Inngest client, the worker thread uses a message-passing pattern for logging:

    1. Creation: runner.ts creates a lightweight, logger-compatible object using createMessageLogger().
    2. Parsing: Log calls are processed by parsePinoArgs() to convert them into a { message, data? } format. This supports both pino-style (object, string) and simple (string) signatures.
    3. Transmission: The parsed log is sent to the main thread as a LOG message (defined as WorkerToMainMessage in protocol.ts).
    4. Execution: The main thread receives the message via handleWorkerLog() in index.ts and executes the actual logging call using the real logger.
  8. Use `defer` for fire-and-forget independent work

    main

    Use defer when you need to trigger a specific, typed function independently without waiting for its result. Unlike step.invoke, which blocks the caller until the result is returned, defer is synchronous and fire-and-forget.

    Comparison of execution tools

    ToolReturns to caller?Independent execution?Use Case
    step.invoke(fn, { data })Yes (awaits result)No (caller blocks)When you need the result of the function to continue.
    step.sendEvent(...)NoYes (any matching fn)When you want to trigger any function matching an event.
    defer(id, { function, data })NoYes (single typed target)When you need a typed contract with a specific target but don't need the result (e.g., an LLM scorer).
  9. How Durable Endpoints work

    main

    Durable Endpoints solve the problem of HTTP request timeouts when executing long-running workflows.

    The Lifecycle:

    1. A request is made to an endpoint wrapped with inngest.endpoint().
    2. If the request takes longer than the sync timeout, the endpoint redirects the client to a proxy endpoint.
    3. The proxy endpoint (created via inngest.endpointProxy()) fetches the result from Inngest.
    4. If E2E encryption is enabled, the proxy handles decryption before returning the final result to the user.
  10. Compare Durable Endpoints vs Traditional Inngest

    main

    When deciding how to implement workflows, use the following comparison to choose between traditional Inngest functions and the new Durable Endpoints:

    FeatureTraditional InngestDurable Endpoints
    DefinitionDefine separate functionsInline in HTTP handlers
    TriggerTrigger via eventsDirect HTTP calls
    API Methodinngest.createFunction()inngest.endpoint()
    Step Access{ event, step } from contextImport step directly
    EndpointSeparate /api/inngest endpointNo separate endpoint needed
  11. How Durable Endpoint Streaming works

    main

    Durable Endpoint (DE) Streaming allows you to stream arbitrary data (such as LLM outputs) to a client via Server-Sent Events (SSE).

    Execution Modes

    • Sync Mode: If the request includes the Accept: text/event-stream header, the DE returns an SSE response immediately. The function continues executing steps in the background.
    • Async Mode: After an asynchronous operation (like step.sleep), the DE switches to streaming data to the Inngest Server (IS). The IS then relays this data to the client via a redirect URL.

    Reconnection Logic

    When switching to async mode, the client receives an inngest.redirect_info event containing a URL. Once the initial direct stream ends, the client reconnects to that specific URL to receive the remaining events.

  12. How the Worker Thread strategy works

    main

    The Worker Thread strategy is designed to prevent CPU-intensive userland function execution from blocking critical connection health checks.

    It achieves this by offloading the following tasks to a separate Node.js worker thread (runner.ts):

    • WebSocket connection management
    • Heartbeater execution
    • Lease extender execution

    Userland function execution (your actual business logic) continues to run on the main thread. This separation ensures that even if your code is performing heavy computations, the connection to Inngest remains stable.