Sessions and blocking
Lease a dedicated connection for blocking commands, WATCH and other stateful work.
A session is a connection leased from a pool for the length of one body. Commands that wait on the server or keep state on a connection, such as BLPOP and WATCH, run on a session so they cannot stall ordinary traffic. Sessions come from the RedisSessions service.
Example (Waiting for a Job With BLPOP)
import { , } from "effect";
import { } from "@effect-kit/redis";
const = .(function* () {
const = yield* ;
const popped = yield* .(["jobs"], { : .(1) });
return ;
});blpop returns None when the server times out and Some([key, value]) when an element arrives. Values are Uint8Array. Blocking calls use a separate pool of connections, two by default, so a waiting BLPOP does not hold up redis.get.
Blocking commands need a session
Redis has no blpop, brpop, bzpopmin or other blocking methods, and the compiler rejects
them. Running a blocking command through redis.execute fails with an UnsupportedCommandError.
Setting how long to wait
blockFor is an Effect Duration or the string "forever". A bare number does not compile. timeout is an optional, separate client-side deadline. Without it the client deadline is blockFor plus 1000 milliseconds, or none for "forever".
Example (Waiting Forever With a Client Deadline)
import { , } from "effect";
import { } from "@effect-kit/redis";
const = .(function* () {
const = yield* ;
const = yield* .(["queue"], {
: "forever",
: .(5),
});
return ;
});The blocking methods on RedisSessions are blpop, brpop, brpoplpush, blmove, blmpop, blmovem, bzpopmin, bzpopmax, bzmpop, xreadBlocking and xreadgroupBlocking. Each returns an Option.
Leasing a session
withSession runs a body on one leased connection and returns the connection when the body ends, including on failure or interruption. withBlockingSession leases from the blocking pool. Inside the body, session has the same command methods as redis, plus pipeline, transaction, watch and unwatch.
Example (Running Commands on One Connection)
import { } from "effect";
import { } from "@effect-kit/redis";
const = .(function* () {
const = yield* ;
return yield* .(() =>
.(function* () {
yield* .(["inventory:7"]);
const = yield* .("inventory:7");
yield* .();
return ;
}),
);
});Prefer sessions.watch over calling session.watch by hand, since it unwatches for you.
A session that runs a command which changes connection state, such as selectDatabase, is retired instead of returned to the pool.
Pool limits and SessionError
Leases are bounded. These options go under sessions in the layer settings:
Prop
Type
When the pool is exhausted the call fails with a SessionError. reason: "pool-full" means the waiter queue is full and reason: "lease-timeout" means no connection freed up in time. sessions.snapshot reports connections, idle and leased.
Upstash has no sessions. RedisUpstash does not provide RedisSessions, so none of this applies over HTTP.