AI студия Владимира Ломтева
УСЛУГИПРОЕКТЫСТАТЬИБАЗА ЗНАНИЙМаркетплейсОбучениеПолезные сервисы

Оставьте заявку,
чтобы обсудить проект

Напишите ваш вопрос, не забудьте указать телефон. Мы перезвоним и все расскажем.

Контакты

Москва

Работаем по всей России
и миру (онлайн)

+7 (999) 760-24-41

Ежедневно с 9:00 до 21:00

lamooof@gmail.com

По вопросам сотрудничества

TelegramWhatsApp

Есть предложение?

Напишите нам в мессенджеры

© 2025 AI студия Владимира Ломтева

Политика конфиденциальностиСогласие на обработку ПДн|ИНН 623412173261
    Inngest Durable Functions — Скилл для ИИ-агентов | AI Рассвет

    Inngest Durable Functions

    Use when building functions that must survive process crashes, retry automatically on failure, run on a schedule, react to events, or maintain state across infrastructure failures — e.g., webhook handlers that drop events, flaky cron jobs, background jobs that fail mid execution, or workflows that need to resume where they left off. Covers Inngest function configuration, triggers (events, cron, invoke), step execution and memoization, idempotency, cancellation, error handling, retries, logging, and observability.

    Скиллы для операций#GitHub#inngest/inngest-skills#skills.sh
    Скачивания
    0
    В избранном
    0
    Комментарии
    0
    Просмотры
    1

    Установить скилл

    Добавьте инструмент одной командой или скачайте проверенный архив версии.

    npx skills add inngest/inngest-skills --skill inngest-durable-functions
    Скачать ZIP
    Версия
    1.0.0+ff42436bcedf
    Автор
    Владимир Ломтев
    Репозиторий
    inngest/inngest-skills
    GitHub: inngest/inngest-skills

    Как установить

    1. 1Скопируйте команду из блока установки.
    2. 2Запустите её в терминале из каталога проекта.

    Документация

    Inngest Durable Functions

    Master Inngest's durable execution model for building fault-tolerant, long-running workflows. This skill covers the complete lifecycle from triggers to error handling.

    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.

    Core Concepts You Need to Know

    Durable Execution Model

    • Each step should encapsulate side-effects and non-deterministic code
    • Memoization prevents re-execution of completed steps
    • State persistence survives infrastructure failures
    • Automatic retries with configurable retry count

    Step Execution Flow

    // ❌ BAD: Non-deterministic logic outside steps
    async ({ event, step }) => {
      const timestamp = Date.now(); // This runs multiple times!
    
      const result = await step.run("process-data", () => {
        return processData(event.data);
      });
    };
    
    // ✅ GOOD: All non-deterministic logic in steps
    async ({ event, step }) => {
      const result = await step.run("process-with-timestamp", () => {
        const timestamp = Date.now(); // Only runs once
        return processData(event.data, timestamp);
      });
    };
    

    Function Limits

    Every Inngest function has these hard limits:

    • Maximum 1,000 steps per function run
    • Maximum 4MB returned data for each step
    • Maximum 32MB combined function run state including, event data, step output, and function output
    • Each step = separate HTTP request (~50-100ms overhead)

    If you're hitting these limits, break your function into smaller functions connected via step.invoke() or step.sendEvent().

    When to Use Steps

    Always wrap in step.run():

    • API calls and network requests
    • Database reads and writes
    • File I/O operations
    • Any non-deterministic operation
    • Anything you want retried independently on failure

    Never wrap in step.run():

    • Pure calculations and data transformations
    • Simple validation logic
    • Deterministic operations with no side effects
    • Logging (use outside steps)

    Function Creation

    Basic Function Structure

    const processOrder = inngest.createFunction(
      {
        id: "process-order", // Unique, never change this
        triggers: [{ event: "order/created" }],
        retries: 4, // Default: 4 retries per step
        concurrency: 10 // Max concurrent executions
      },
      async ({ event, step }) => {
        // Your durable workflow
      }
    );
    

    Step IDs and Memoization

    // Step IDs can be reused - Inngest handles counters automatically
    const data = await step.run("fetch-data", () => fetchUserData());
    const more = await step.run("fetch-data", () => fetchOrderData()); // Different execution
    
    // Use descriptive IDs for clarity
    await step.run("validate-payment", () => validatePayment(event.data.paymentId));
    await step.run("charge-customer", () => chargeCustomer(event.data));
    await step.run("send-confirmation", () => sendEmail(event.data.email));
    

    Triggers and Events

    Event Triggers

    Triggers are defined in the triggers array in the first argument of createFunction:

    // Single event trigger
    inngest.createFunction(
      { id: "my-fn", triggers: [{ event: "user/signup" }] },
      async ({ event }) => { /* ... */ }
    );
    
    // Event with conditional filter
    inngest.createFunction(
      { id: "my-fn", triggers: [{ event: "user/action", if: 'event.data.action == "purchase" && event.data.amount > 100' }] },
      async ({ event }) => { /* ... */ }
    );
    
    // Multiple triggers (up to 10)
    inngest.createFunction(
      {
        id: "my-fn",
        triggers: [
          { event: "user/signup" },
          { event: "user/login", if: 'event.data.firstLogin == true' },
          { cron: "0 9 * * *" } // Daily at 9 AM
        ]
      },
      async ({ event }) => { /* ... */ }
    );
    

    Cron Triggers

    // Basic cron
    inngest.createFunction(
      { id: "my-fn", triggers: [{ cron: "0 */6 * * *" }] }, // Every 6 hours
      async ({ step }) => { /* ... */ }
    );
    
    // With timezone
    inngest.createFunction(
      { id: "my-fn", triggers: [{ cron: "TZ=Europe/Paris 0 12 * * 5" }] }, // Fridays at noon Paris time
      async ({ step }) => { /* ... */ }
    );
    
    // Combine with events
    inngest.createFunction(
      {
        id: "my-fn",
        triggers: [
          { event: "manual/report.requested" },
          { cron: "0 0 * * 0" } // Weekly on Sunday
        ]
      },
      async ({ event, step }) => { /* ... */ }
    );
    

    Function Invocation

    // Invoke another function as a step
    const result = await step.invoke("generate-report", {
      function: generateReportFunction,
      data: { userId: event.data.userId }
    });
    
    // Use returned data
    await step.run("process-report", () => {
      return processReport(result);
    });
    

    Idempotency Strategies

    Event-Level Idempotency (Producer Side)

    // Prevent duplicate events with custom ID
    await inngest.send({
      id: `checkout-completed-${cartId}`, // 24-hour deduplication
      name: "cart/checkout.completed",
      data: { cartId, email: "user@example.com" }
    });
    

    Function-Level Idempotency (Consumer Side)

    const sendEmail = inngest.createFunction(
      {
        id: "send-checkout-email",
        triggers: [{ event: "cart/checkout.completed" }],
        // Only run once per cartId per 24 hours
        idempotency: "event.data.cartId"
      },
      async ({ event, step }) => {
        // This function won't run twice for same cartId
      }
    );
    
    // Complex idempotency keys
    const processUserAction = inngest.createFunction(
      {
        id: "process-user-action",
        triggers: [{ event: "user/action.performed" }],
        // Unique per user + organization combination
        idempotency: 'event.data.userId + "-" + event.data.organizationId'
      },
      async ({ event, step }) => {
        /* ... */
      }
    );
    

    Cancellation Patterns

    Event-Based Cancellation

    In expressions, event = the original triggering event, async = the new event being matched. See Expression Syntax Reference for full details.

    const processOrder = inngest.createFunction(
      {
        id: "process-order",
        triggers: [{ event: "order/created" }],
        cancelOn: [
          {
            event: "order/cancelled",
            if: "event.data.orderId == async.data.orderId"
          }
        ]
      },
      async ({ event, step }) => {
        await step.sleepUntil("wait-for-payment", event.data.paymentDue);
        // Will be cancelled if order/cancelled event received
        await step.run("charge-payment", () => processPayment(event.data));
      }
    );
    

    Timeout Cancellation

    const processWithTimeout = inngest.createFunction(
      {
        id: "process-with-timeout",
        triggers: [{ event: "long/process.requested" }],
        timeouts: {
          start: "5m", // Cancel if not started within 5 minutes
          finish: "30m" // Cancel if not finished within 30 minutes
        }
      },
      async ({ event, step }) => {
        /* ... */
      }
    );
    

    Handling Cancellation Cleanup

    // Listen for cancellation events
    const cleanupCancelled = inngest.createFunction(
      { id: "cleanup-cancelled-process", triggers: [{ event: "inngest/function.cancelled" }] },
      async ({ event, step }) => {
        if (event.data.function_id === "process-order") {
          await step.run("cleanup-resources", () => {
            return cleanupOrderResources(event.data.run_id);
          });
        }
      }
    );
    

    Error Handling and Retries

    Default Retry Behavior

    • 5 total attempts (1 initial + 4 retries) per step
    • Exponential backoff with jitter
    • Independent retry counters per step

    Custom Retry Configuration

    const reliableFunction = inngest.createFunction(
      {
        id: "reliable-function",
        triggers: [{ event: "critical/task" }],
        retries: 10 // Up to 10 retries per step
      },
      async ({ event, step, attempt }) => {
        // `attempt` is the function-level attempt counter (0-indexed)
        // It tracks retries for the currently executing step, not the overall function
        if (attempt > 5) {
          // Different logic for later attempts of the current step
        }
      }
    );
    

    Non-Retriable Errors

    Prevent retries for code that won't succeed upon retry.

    import { NonRetriableError } from "inngest";
    
    const processUser = inngest.createFunction(
      { id: "process-user", triggers: [{ event: "user/process.requested" }] },
      async ({ event, step }) => {
        const user = await step.run("fetch-user", async () => {
          const user = await db.users.findOne(event.data.userId);
    
          if (!user) {
            // Don't retry - user doesn't exist
            throw new NonRetriableError("User not found, stopping execution");
          }
    
          return user;
        });
    
        // Continue processing...
      }
    );
    

    Custom Retry Timing

    import { RetryAfterError } from "inngest";
    
    const respectRateLimit = inngest.createFunction(
      { id: "api-call", triggers: [{ event: "api/call.requested" }] },
      async ({ event, step }) => {
        await step.run("call-api", async () => {
          const response = await externalAPI.call(event.data);
    
          if (response.status === 429) {
            // Retry after specific time from API
            const retryAfter = response.headers["retry-after"];
            throw new RetryAfterError("Rate limited", `${retryAfter}s`);
          }
    
          return response.data;
        });
      }
    );
    

    Logging Best Practices

    Proper Logging Setup

    import winston from "winston";
    
    // Configure logger
    const logger = winston.createLogger({
      level: "info",
      format: winston.format.json(),
      transports: [new winston.transports.Console()]
    });
    
    const inngest = new Inngest({
      id: "my-app",
      logger // Pass logger to client
    });
    
    // Or use the built-in ConsoleLogger for simple log level control
    import { ConsoleLogger, Inngest } from "inngest";
    
    const inngest = new Inngest({
      id: "my-app",
      logger: new ConsoleLogger({ level: "debug" }) // "debug" | "info" | "warn" | "error"
    });
    

    ⚠️ v4 Breaking Change: The logLevel option has been removed. Use the logger option with ConsoleLogger or a custom logger instead.

    Function Logging Patterns

    const processData = inngest.createFunction(
      { id: "process-data", triggers: [{ event: "data/process.requested" }] },
      async ({ event, step, logger }) => {
        // ✅ GOOD: Log inside steps to avoid duplicates
        const result = await step.run("fetch-data", async () => {
          logger.info("Fetching data for user", { userId: event.data.userId });
          return await fetchUserData(event.data.userId);
        });
    
        // ❌ AVOID: Logging outside steps can duplicate
        // logger.info("Processing complete"); // This could run multiple times!
    
        await step.run("log-completion", async () => {
          logger.info("Processing complete", { resultCount: result.length });
        });
      }
    );
    

    Performance Optimization

    Checkpointing

    Checkpointing is enabled by default in v4. It allows functions to persist state periodically during execution, reducing latency between steps.

    // Checkpointing is enabled by default in v4
    // Configure maxRuntime for serverless platforms (set to 60-80% of platform timeout)
    const realTimeFunction = inngest.createFunction(
      {
        id: "real-time-function",
        triggers: [{ event: "realtime/process" }],
        checkpointing: {
          maxRuntime: "50s", // For serverless with 60s timeout
        }
      },
      async ({ event, step }) => {
        // Steps execute immediately with periodic checkpointing
        const result1 = await step.run("step-1", () => process1(event.data));
        const result2 = await step.run("step-2", () => process2(result1));
        return { result2 };
      }
    );
    
    // Disable checkpointing if needed
    const legacyFunction = inngest.createFunction(
      {
        id: "legacy-function",
        triggers: [{ event: "legacy/process" }],
        checkpointing: false
      },
      async ({ event, step }) => { /* ... */ }
    );
    

    Advanced Patterns

    Conditional Step Execution

    const conditionalProcess = inngest.createFunction(
      { id: "conditional-process", triggers: [{ event: "process/conditional" }] },
      async ({ event, step }) => {
        const userData = await step.run("fetch-user", () => {
          return getUserData(event.data.userId);
        });
    
        // Conditional step execution
        if (userData.isPremium) {
          await step.run("premium-processing", () => {
            return processPremiumFeatures(userData);
          });
        }
    
        // Always runs
        await step.run("standard-processing", () => {
          return processStandardFeatures(userData);
        });
      }
    );
    

    Error Recovery Patterns

    const robustProcess = inngest.createFunction(
      { id: "robust-process", triggers: [{ event: "process/robust" }] },
      async ({ event, step }) => {
        let primaryResult;
    
        try {
          primaryResult = await step.run("primary-service", () => {
            return callPrimaryService(event.data);
          });
        } catch (error) {
          // Fallback to secondary service
          primaryResult = await step.run("fallback-service", () => {
            return callSecondaryService(event.data);
          });
        }
    
        return { result: primaryResult };
      }
    );
    

    Common Mistakes to Avoid

    1. ❌ Non-deterministic code outside steps
    2. ❌ Database calls outside steps
    3. ❌ Logging outside steps (causes duplicates)
    4. ❌ Changing step IDs after deployment
    5. ❌ Not handling NonRetriableError cases
    6. ❌ Ignoring idempotency for critical functions

    Next Steps

    • See inngest-steps for detailed step method reference
    • See references/step-execution.md for detailed step patterns
    • See references/error-handling.md for comprehensive error strategies
    • See references/observability.md for monitoring and tracing setup
    • See references/checkpointing.md for performance optimization details

    This skill covers Inngest's durable function patterns. For event sending and webhook handling, see the inngest-events skill.

    Требования и возможности

    Источник пакета
    https://github.com/inngest/inngest-skills/tree/ff42436bcedfb262d6a377571ce64a0d78d386a5/skills/inngest-durable-functions

    Файлы версии

    ПутьРазмерSHA256
    SKILL.md14695ed27ddd313a31a50...
    references/checkpointing.md14100d85098e709d9b30d...
    references/error-handling.md129005148eddee4742a17...
    references/observability.md149883d1b3be8d33f599c...
    references/step-execution.md102631175b68fad1a0e53...

    Частые вопросы

    Как установить Inngest Durable Functions?
    Используйте команду npx skills add inngest/inngest-skills --skill inngest-durable-functions или скачайте ZIP-архив.
    Можно ли скачать Inngest Durable Functions бесплатно?
    Да, опубликованную версию можно скачать из маркетплейса бесплатно.

    Похожие инструменты

    Смотреть все
    Ozon Seller и Performance APIСправочник Ozon Seller API и Performance API с локальными OpenAPI-спецификациями.Grill MeA relentless interview to sharpen a plan or design.Text To LottieCreate, edit, or fix Lottie/Bodymovin JSON animations for the local Skia Skottie player. Use for text-to-Lottie, SVG/logo/type animation, loaders/icons, state feedback, UI microinteractions, lower thirds, diagrams, data/stat/chart animations, product promos, scene/camera motion, visual effects, scene edits, slots/controls, and Skottie debugging.
    Комментарии

    Войдите, чтобы оставить комментарий.

    Комментариев пока нет.

    Установить скилл

    Добавьте инструмент одной командой или скачайте проверенный архив версии.

    npx skills add inngest/inngest-skills --skill inngest-durable-functions
    Скачать ZIP
    Версия
    1.0.0+ff42436bcedf
    Автор
    Владимир Ломтев
    Репозиторий
    inngest/inngest-skills
    GitHub: inngest/inngest-skills
    Excel Automation
    >