Beignet API reference
    Preparing search index...

    Module @beignet/provider-event-bus-redis

    @beignet/provider-event-bus-redis

    Caution

    Beignet is experimental alpha software. The 0.0.x package line is for early evaluation, and APIs may change between releases while the framework settles.

    Redis Pub/Sub EventBusPort provider for Beignet applications.

    Use it when a multi-process app needs domain events published by one process to reach listeners registered in another process. Delivery is best-effort: subscribers must be online, Redis does not persist messages for later replay, and the provider does not acknowledge, retry, or dead-letter failed handlers. Use Beignet outbox and jobs for durable side effects that need retry, idempotency, or recovery after downtime.

    createRedisEventBusProvider(...) returns the stable RedisEventBusProvider type. RedisEventBusConfig describes its validated config; the Zod schema remains internal.

    bun add @beignet/provider-event-bus-redis @beignet/core ioredis
    

    You can also wire it into an existing app with the CLI:

    beignet provider add event-bus-redis
    
    import { createNextServer, createNextServerLoader } from "@beignet/next";
    import { createRedisEventBusProvider } from "@beignet/provider-event-bus-redis";
    import { initialPorts } from "@/infra/port-wiring";
    import { appContext } from "@/server/context";
    import { routes } from "@/server/routes";

    // Set environment variables:
    // REDIS_EVENT_BUS_URL=redis://localhost:6379
    // REDIS_EVENT_BUS_DB=0 (optional)

    export const getServer = createNextServerLoader(() =>
    createNextServer({
    ports: initialPorts,
    providers: [createRedisEventBusProvider()],
    context: appContext,
    routes,
    }),
    );

    The provider contributes ctx.ports.eventBus, the standard Beignet event bus port, and ctx.ports.redisEventBus as a Redis-specific escape hatch.

    The provider reads environment variables with the REDIS_EVENT_BUS_ prefix:

    Variable Required Description Example
    REDIS_EVENT_BUS_URL Yes Redis connection URL. redis://localhost:6379
    REDIS_EVENT_BUS_DB No Redis database number. Defaults to 0. 0
    REDIS_EVENT_BUS_CHANNEL_PREFIX No Prefix for Pub/Sub channels. Defaults to beignet:event-bus:. my-app:events:
    REDIS_EVENT_BUS_CONNECT_TIMEOUT_MS No Initial connection timeout in milliseconds. Defaults to 5000. 2000
    REDIS_EVENT_BUS_MAX_RETRIES_PER_REQUEST No Per-command retry limit before a command rejects. Defaults to 2. 1
    REDIS_EVENT_BUS_CONNECT_MAX_ATTEMPTS No Connection attempts before startup fails. Defaults to 3. 5

    Use createRedisEventBusProvider(options) when the app should own connection settings. Defined options override matching REDIS_EVENT_BUS_* environment variables:

    import { createRedisEventBusProvider } from "@beignet/provider-event-bus-redis";

    const provider = createRedisEventBusProvider({
    channelPrefix: "my-app:events:",
    connectTimeoutMs: 2000,
    maxRetriesPerRequest: 1,
    db: 1,
    retryStrategy: (times) => Math.min(times * 100, 1000),
    });

    Calling createRedisEventBusProvider() with no options uses the env-backed defaults above.

    During startup the provider creates separate publisher and subscriber clients, connects both eagerly, and fails boot with a redacted connection error when Redis is unreachable. The default initial connection retry strategy stops after REDIS_EVENT_BUS_CONNECT_MAX_ATTEMPTS; after a successful connection, ioredis reconnects with capped exponential backoff and resubscribes to the channels owned by that subscriber client. Events published while the subscriber is disconnected are still lost because Redis Pub/Sub has no replay. If an initial SUBSCRIBE command fails after ioredis exhausts its command retries, the adapter retries that desired subscription with capped backoff for as long as at least one local handler remains registered.

    The environment-backed provider targets a standalone Redis URL or a managed Redis service that exposes one Redis-compatible endpoint. It opens two TCP connections per app process: one publisher and one subscriber. Include both in the process connection budget.

    Every long-lived process that should receive events must install the provider and register its listeners. Ephemeral request runtimes can publish events, but they are not reliable subscriber hosts because Redis only delivers while the connection is online. Run subscriptions in a long-lived web or worker process.

    Sentinel and Redis Cluster require constructor options that cannot be expressed by REDIS_EVENT_BUS_URL. Apps using those topologies should create their own ioredis clients and pass them to createRedisEventBus(...). Beignet's live suite does not currently prove Sentinel or Cluster failover semantics, so test subscription recovery against the exact managed topology before relying on it. HTTP-only Redis APIs are not compatible because Pub/Sub requires a persistent Redis connection.

    Use createRedisEventBus(...) when your app owns Redis clients:

    import Redis from "ioredis";
    import { createRedisEventBus } from "@beignet/provider-event-bus-redis";

    const eventBus = createRedisEventBus({
    publisher: new Redis(process.env.REDIS_EVENT_BUS_URL),
    subscriber: new Redis(process.env.REDIS_EVENT_BUS_URL),
    channelPrefix: "my-app:events:",
    });

    Register listeners during startup before handling traffic. The EventBusPort subscription API is synchronous, while Redis subscription acknowledgement is asynchronous, so messages published immediately after a new subscription may be missed during startup races.

    • publish(...) publishes one Redis Pub/Sub message on <channelPrefix><event.name>.
    • Only subscribers that are online and currently subscribed receive the event.
    • ioredis resubscribes after a transient reconnect, but messages published during the disconnected interval are not recovered.
    • Payloads are JSON encoded and delivered to handlers without persisting the message.
    • When a tracing port is available, the envelope includes Beignet's versioned trace carrier and subscribers receive it as publish metadata. Registered listeners continue the producer trace. Legacy messages without a carrier and messages with malformed trace metadata still deliver their payload.
    • Handler errors are reported through onHandlerError when provided and are also recorded as provider instrumentation events; they do not reject the original publisher.
    • Invalid messages and subscription errors are reported through onSubscriberError when provided and recorded as eventBus.message.failed or eventBus.subscription.failed provider instrumentation events. Failed subscriptions retry with capped backoff while their local handlers remain registered; removing the last handler cancels a pending retry.
    • Failed publish(...) calls reject with the Redis error and record an eventBus.publish.failed instrumentation event. The provider does not retry the publish after the configured ioredis command retries are exhausted.
    • When the eventBus instrumentation watcher is enabled, publisher and subscriber connection errors from env-backed clients are recorded as eventBus.connection.failed. When instrumentation is absent or disabled, Beignet leaves ioredis's error fallback intact so connection failures remain visible.
    • The provider does not retry handlers, store attempts, replay missed events, or dead-letter failures.

    When side effects must survive process restarts or dependency outages, record the domain event through the Unit of Work outbox and drain it through jobs or outbox-backed listeners.

    ctx.ports.redisEventBus exposes:

    const health = await ctx.ports.redisEventBus.checkHealth();

    ctx.ports.redisEventBus.publisher;
    ctx.ports.redisEventBus.subscriber;
    ctx.ports.redisEventBus.channelPrefix;

    checkHealth() sends cheap PING commands to both Redis clients and returns metadata suitable for app-owned readiness endpoints. It proves both connections can reach Redis; it does not prove that every expected listener has registered its channel subscription.

    The provider records successful publish events under the eventBus watcher. Received messages, failed publishes, connection failures, subscription failures, and handler failures are recorded as custom provider events. Payloads are not recorded.

    Use @beignet/provider-event-bus-memory for deterministic unit tests and single-process local tests. Use this Redis provider in integration tests when the behavior under test specifically depends on cross-process delivery or Redis connection behavior.

    This package includes opt-in live Redis integration tests for cross-instance delivery, reconnect and automatic resubscription, expected loss while offline, active-subscription cleanup during shutdown, readiness, instrumentation, and failure callbacks. The default bun run test command runs the hermetic unit suite only so the live tests cannot share process state with the mocked ioredis tests. Set REDIS_EVENT_BUS_TEST_URL or the shared REDIS_TEST_URL before running the dedicated live test command:

    REDIS_EVENT_BUS_TEST_URL=redis://localhost:6379 bun run test:live
    
    CreateRedisEventBusOptions
    CreateRedisEventBusProviderOptions
    RedisEventBusConfig
    RedisEventBusEscapeHatch
    RedisEventBusHealth
    RedisEventBusProviderPorts
    RedisEventBusPublisherClient
    RedisEventBusSubscriberClient
    RedisEventBusProvider
    createRedisEventBus
    createRedisEventBusProvider