# 1) Data model & basics * A **queue** is a List at key `queue:`. * Common patterns: * **Producer**: `LPUSH queue item` (or `RPUSH`) * **Consumer (non-blocking)**: `RPOP queue` (or `LPOP`) * **Consumer (blocking)**: `BRPOP queue timeout` (or `BLPOP`) * If a key doesn’t exist, it’s treated as an **empty list**; push **creates** the list; when the **last element is popped, the key is deleted**. ([Redis][1]) --- # 2) Commands to implement (queues via Lists) ## LPUSH / RPUSH Prepend/append one or more elements. Create the list if it doesn’t exist. **Return**: Integer = new length of the list. **Syntax** ``` LPUSH key element [element ...] RPUSH key element [element ...] ``` **RESP (example)** ``` *3\r\n$5\r\nLPUSH\r\n$5\r\nqueue\r\n$5\r\njob-1\r\n :1\r\n ``` Refs: semantics & multi-arg ordering. ([Redis][1]) ### LPUSHX / RPUSHX (optional but useful) Like LPUSH/RPUSH, **but only if the list exists**. **Return**: Integer = new length (0 if key didn’t exist). ``` LPUSHX key element [element ...] RPUSHX key element [element ...] ``` Refs: command index. ([Redis][2]) --- ## LPOP / RPOP Remove & return one (default) or **up to COUNT** elements since Redis 6.2. If the list is empty or missing, **Null** is returned (Null Bulk or Null Array if COUNT>1). **Return**: * No COUNT: Bulk String or Null Bulk. * With COUNT: Array of Bulk Strings (possibly empty) or Null Array if key missing. **Syntax** ``` LPOP key [count] RPOP key [count] ``` **RESP (no COUNT)** ``` *2\r\n$4\r\nRPOP\r\n$5\r\nqueue\r\n $5\r\njob-1\r\n # or $-1\r\n if empty ``` **RESP (COUNT=2)** ``` *3\r\n$4\r\nLPOP\r\n$5\r\nqueue\r\n$1\r\n2\r\n *2\r\n$5\r\njob-2\r\n$5\r\njob-3\r\n # or *-1\r\n if key missing ``` Refs: LPOP w/ COUNT; general pop semantics. ([Redis][3]) --- ## BLPOP / BRPOP (blocking consumers) Block until an element is available in any of the given lists or until `timeout` (seconds, **double**, `0` = forever). **Return** on success: **Array \[key, element]**. **Return** on timeout: **Null Array**. **Syntax** ``` BLPOP key [key ...] timeout BRPOP key [key ...] timeout ``` **RESP** ``` *3\r\n$5\r\nBRPOP\r\n$5\r\nqueue\r\n$1\r\n0\r\n # block forever # Success reply *2\r\n$5\r\nqueue\r\n$5\r\njob-4\r\n # Timeout reply *-1\r\n ``` **Implementation notes** * If any listed key is non-empty at call time, reply **immediately** from the first non-empty key **by the command’s key order**. * Otherwise, put the client into a **blocked state** (register per-key waiters). On any `LPUSH/RPUSH` to those keys, **wake the earliest waiter** and serve it atomically. * If timeout expires, return **Null Array** and clear the blocked state. Refs: timeout semantics and return shape. ([Redis][4]) --- ## LMOVE / BLMOVE (atomic move; replaces RPOPLPUSH/BRPOPLPUSH) Atomically **pop from one side** of `source` and **push to one side** of `destination`. * Use for **reliable queues** (move to a *processing* list). * `BLMOVE` blocks like `BLPOP` when `source` is empty. **Syntax** ``` LMOVE source destination LEFT|RIGHT LEFT|RIGHT BLMOVE source destination LEFT|RIGHT LEFT|RIGHT timeout ``` **Return**: Bulk String element moved, or Null if `source` empty (LMOVE); `BLMOVE` blocks/Null on timeout. **RESP (LMOVE RIGHT->LEFT)** ``` *5\r\n$5\r\nLMOVE\r\n$6\r\nsource\r\n$3\r\ndst\r\n$5\r\nRIGHT\r\n$4\r\nLEFT\r\n $5\r\njob-5\r\n ``` **Notes** * Prefer `LMOVE/BLMOVE` over deprecated `RPOPLPUSH/BRPOPLPUSH`. * Pattern: consumer `LMOVE queue processing RIGHT LEFT` → work → `LREM processing 1 ` to ACK; a reaper can requeue stale items. Refs: LMOVE/BLMOVE behavior and reliable-queue pattern; deprecation of RPOPLPUSH. ([Redis][5]) *(Compat: you can still implement `RPOPLPUSH source dest` and `BRPOPLPUSH source dest timeout`, but mark them deprecated and map to LMOVE/BLMOVE.)* ([Redis][6]) --- ## LLEN (length) Useful for metrics/backpressure. ``` LLEN key ``` **RESP** ``` *2\r\n$4\r\nLLEN\r\n$5\r\nqueue\r\n :3\r\n ``` Refs: list overview mentioning LLEN. ([Redis][7]) --- ## LREM (ack for “reliable” processing) Remove occurrences of `element` from the list (head→tail scan). Use `count=1` to ACK a single processed item from `processing`. ``` LREM key count element ``` **RESP** ``` *4\r\n$4\r\nLREM\r\n$9\r\nprocessing\r\n$1\r\n1\r\n$5\r\njob-5\r\n :1\r\n ``` Refs: reliable pattern mentions LREM to ACK. ([Redis][5]) --- ## LTRIM (bounded queues / retention) Keep only `[start, stop]` range; everything else is dropped. Use to cap queue length after pushes. ``` LTRIM key start stop ``` **RESP** ``` *4\r\n$5\r\nLTRIM\r\n$5\r\nqueue\r\n$2\r\n0\r\n$3\r\n999\r\n +OK\r\n ``` Refs: list overview includes LTRIM for retention. ([Redis][7]) --- ## LRANGE / LINDEX (debugging / peeking) * `LRANGE key start stop` → Array of elements (non-destructive). * `LINDEX key index` → one element or Null. These aren’t required for queue semantics, but handy. ([Redis][7]) --- # 3) Errors & types * Wrong type: `-WRONGTYPE Operation against a key holding the wrong kind of value\r\n` * Non-existing key: * Push: creates the list (returns new length). * Pop (non-blocking): returns **Null**. * Blocking pop: **Null Array** on timeout. ([Redis][1]) --- # 4) Blocking engine (implementation sketch) 1. **Call time**: scan keys in user order. If a non-empty list is found, pop & reply immediately. 2. **Otherwise**: register the client as **blocked** on those keys with `deadline = now + timeout` (or infinite). 3. **On push to any key**: if waiters exist, **wake one** (FIFO) and serve its pop **atomically** with the push result. 4. **On timer**: for each blocked client whose deadline passed, reply `Null Array` and clear state. 5. **Connection close**: remove from any wait queues. Refs for timeout/block semantics. ([Redis][4]) --- # 5) Reliable queue pattern (recommended) * **Consume**: `LMOVE queue processing RIGHT LEFT` (or `BLMOVE ... 0`). * **Process** the job. * **ACK**: `LREM processing 1 ` when done. * **Reaper**: auxiliary task that detects stale jobs (e.g., track job IDs + timestamps in a ZSET) and requeues them. (Lists don’t include timestamps; pairing with a ZSET is standard practice.) Refs: LMOVE doc’s pattern. ([Redis][5]) --- # 6) Minimal test matrix * Push/pop happy path (both ends), with/without COUNT. * Blocking pop: immediate availability, block + timeout, wake on push, multiple keys order, FIFO across multiple waiters. * LMOVE/BLMOVE: RIGHT→LEFT pipeline, block + wake, cross-list atomicity, ACK via LREM. * Type errors and key deletion on last pop.