import type { AddOnPlansResponseEdgesItemNode, AddOnsResponseEdgesItemNode } from "@distilled.cloud/fly-io/addons"; import * as addons from "@distilled.cloud/fly-io/addons"; import * as Effect from "effect/Effect"; import * as Provider from "../Provider.ts"; import { Resource } from "../Resource.ts"; import type { Providers } from "./Providers.ts"; export declare const DEFAULT_REDIS_REGION = "iad"; export declare const REDIS_ADDON_TYPE = "upstash_redis"; export declare const REDIS_PROVIDER = "upstash_redis"; export declare const REDIS_URL_ENV = "REDIS_URL"; declare const RedisUrlMissing_base: new = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & { readonly _tag: "Fly.RedisUrlMissing"; } & Readonly; export declare class RedisUrlMissing extends RedisUrlMissing_base<{ name: string; }> { } declare const RedisCommandError_base: new = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & { readonly _tag: "Fly.RedisCommandError"; } & Readonly; export declare class RedisCommandError extends RedisCommandError_base<{ command: string; cause: unknown; }> { } export interface RedisProps { /** * Upstash Redis database name. Globally unique in the org. If omitted, * a unique name is generated from the stack, stage and logical ID. * Changing it replaces the database. */ name?: string; /** * Primary region (`iad`, `ord`, `sjc`, …). Fly cannot move a primary. * Changing it replaces the database. * * @default "iad" */ primaryRegion?: string; /** * Organization slug. Defaults to the current token's org. Changing it * replaces the database. */ orgSlug?: string; /** * Add-on plan id, name, or display name from `addOnPlans`. Default is * the cheapest listed plan (free or pay-as-you-go). Fixed plans are * billed. Default tests use the cheapest listed plan. */ plan?: string; /** * Read-replica regions. Updated in place. Must not include the * primary region. */ readRegions?: string[]; /** * Evict keys when memory is full (cache workload). Updated in place. */ eviction?: boolean; /** * Automatically upgrade a fixed plan when hitting resource limits. * Ignored on pay-as-you-go. */ autoUpgrade?: boolean; /** * ProdPack add-on ($200/mo). Paid. Not enabled in default tests. */ prodPack?: boolean; } export type Redis = Resource<"Fly.Redis", RedisProps, { /** Fly GraphQL add-on id. */ redisId: string; /** Physical Upstash Redis name. */ name: string; /** Primary region code. */ primaryRegion: string; /** Observed read-replica regions. */ readRegions: string[]; /** Observed status (`ready`, `provisioning`, …). */ status: string | undefined; /** Selected plan id, if the API returned one. */ planId: string | undefined; /** Observed plan name (`Pay-as-you-go`, `Fixed 250MB`, …). */ planName: string | undefined; /** Private 6PN address, if the API returned one. */ privateIp: string | undefined; /** Organization slug. */ orgSlug: string | undefined; /** Whether eviction is enabled. */ eviction: boolean | undefined; }, never, Providers>; /** * Managed Upstash Redis in a Fly org. Bind {@link ReadRedis}, * {@link WriteRedis}, or {@link ReadWriteRedis} on a {@link Service}. * Alchemy writes `REDIS_URL` as an App secret and the runtime client * uses it internally. Redis is not reachable from CI — drive it over * HTTP. * * @see https://fly.io/docs/upstash/redis/ * * ### Create Redis * Alchemy generates a unique name unless you pass one. Default region is * `iad`. Default plan is the cheapest `addOnPlans` row (free or * pay-as-you-go). * * **Example:** Generated name * ```typescript * const cache = yield* Fly.Redis("Cache"); * ``` * * :::note * Prefer omitting `name` in tests and CI so names stay unique and * reclaimable. * ::: * * ### A stable name * Pass `name` when you want a stable Upstash database name. * * **Example:** Explicit name * ```typescript * const cache = yield* Fly.Redis("Cache", { * name: "my-cache", * primaryRegion: "iad", * }); * ``` * * :::caution[Changing `name` replaces Redis] * Fly cannot rename an add-on. Alchemy deletes the old database first, * then creates the new one. * ::: * * :::caution[Changing `primaryRegion` replaces Redis] * The primary region is immutable. The old database is deleted first * because the name cannot exist twice. * ::: * * ### Bind from a Service * Yield {@link ReadWriteRedis} (or {@link ReadRedis} / {@link WriteRedis}) * in Service init. Provide the matching `*Http` layer. * * **Example:** Read and write * ```typescript * import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse"; * * const Cache = Fly.Redis("Cache"); * * export default class Api extends Fly.Service()( * "Api", * { app: Site, main: import.meta.url, port: 3000 }, * Effect.gen(function* () { * const cache = yield* Fly.ReadWriteRedis(Cache); * return { * fetch: Effect.gen(function* () { * yield* cache.set("marker", "hello"); * const value = yield* cache.get("marker"); * return HttpServerResponse.json({ value }); * }), * }; * }).pipe(Effect.provide(Fly.ReadWriteRedisHttp)), * ) {} * ``` * * ### Eviction * Enable eviction for cache workloads. Updated in place. * * **Example:** Eviction * ```typescript * const cache = yield* Fly.Redis("Cache", { * eviction: true, * }); * ``` * * ### Read replicas * `readRegions` are extra replica regions. Updated in place. * * **Example:** Replica region * ```typescript * const cache = yield* Fly.Redis("Cache", { * primaryRegion: "iad", * readRegions: ["sjc"], * }); * ``` * * ### Plan * Omit `plan` for the cheapest listed plan. Pass a plan id or display * name to pin one. Fixed plans are billed. * * **Example:** Pin pay-as-you-go * ```typescript * const cache = yield* Fly.Redis("Cache", { * plan: "Pay-as-you-go", * }); * ``` * * :::caution[Fixed plans are billed] * Fixed plans are billed monthly. Prefer omitting `plan` unless you * need a specific size. * ::: * * @resource */ export declare const Redis: import("../Resource.ts").ResourceClass; declare const RedisNotCreated_base: new = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & { readonly _tag: "Fly.RedisNotCreated"; } & Readonly; export declare class RedisNotCreated extends RedisNotCreated_base<{ name: string; errorMessage?: string; }> { } declare const RedisPlanNotFound_base: new = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & { readonly _tag: "Fly.RedisPlanNotFound"; } & Readonly; export declare class RedisPlanNotFound extends RedisPlanNotFound_base<{ plan: string; }> { } declare const RedisOrgMissing_base: new = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & { readonly _tag: "Fly.RedisOrgMissing"; } & Readonly; export declare class RedisOrgMissing extends RedisOrgMissing_base<{ orgSlug: string; }> { } type RedisPlan = AddOnPlansResponseEdgesItemNode; export declare const isFixedRedisPlan: (plan: Pick) => boolean; export declare const listRedisAddOns: () => Effect.Effect; export declare const listRedisPlans: () => Effect.Effect; export declare const findRedisAddOn: (input: { id?: string; name?: string; }) => Effect.Effect; /** * Write `REDIS_URL` onto an App from attached Redis add-on names. * Called from {@link Service} reconcile so the secret exists before * Machines boot. */ export declare const attachRedisSecrets: (appName: string, attached: readonly { name: string; id?: string; }[]) => Effect.Effect; export declare const RedisProvider: () => import("effect/Layer").Layer, never, import("../Stack.ts").Stack | import("../Stage.ts").Stage | addons.FlyIoOpContext>; export {}; //# sourceMappingURL=Redis.d.ts.map