|
| 1 | +# BabelQueue — Redis (Java) |
| 2 | + |
| 3 | +`com.babelqueue:babelqueue-redis` — a Redis transport for |
| 4 | +[BabelQueue](https://babelqueue.com), built on the [Lettuce](https://lettuce.io) |
| 5 | +client and the framework-agnostic |
| 6 | +[`babelqueue-core`](https://github.com/BabelQueue/babelqueue-java). |
| 7 | + |
| 8 | +A canonical-envelope **publisher** and a URN-routed **consumer**, so a Redis-based Java |
| 9 | +service speaks the same wire contract (envelope shape, URN identity, trace propagation) |
| 10 | +as the PHP/Laravel, Python, Go, Node and .NET SDKs. Implements |
| 11 | +[§1 of the broker-bindings contract](https://babelqueue.com) — the reliable-queue list |
| 12 | +pattern. |
| 13 | + |
| 14 | +## Install (Maven) |
| 15 | + |
| 16 | +```xml |
| 17 | +<dependency> |
| 18 | + <groupId>com.babelqueue</groupId> |
| 19 | + <artifactId>babelqueue-redis</artifactId> |
| 20 | + <version>1.0.0</version> |
| 21 | +</dependency> |
| 22 | +``` |
| 23 | + |
| 24 | +It pulls `babelqueue-core` and `io.lettuce:lettuce-core` transitively. |
| 25 | + |
| 26 | +## Use |
| 27 | + |
| 28 | +```java |
| 29 | +RedisClient client = RedisClient.create("redis://localhost:6379"); |
| 30 | +RedisCommands<String, String> redis = client.connect().sync(); // the command seam |
| 31 | + |
| 32 | +// produce |
| 33 | +String id = RedisPublisher.create(redis, "orders") |
| 34 | + .publish("urn:babel:orders:created", Map.of("order_id", 1042)); |
| 35 | + |
| 36 | +// consume |
| 37 | +RedisConsumer consumer = RedisConsumer.builder(redis, "orders") |
| 38 | + .handler("urn:babel:orders:created", (env, body) -> { |
| 39 | + // env.data(), env.traceId(), env.attempts() ... |
| 40 | + }) |
| 41 | + .onError((err, env, body) -> log.warn("bad message", err)) |
| 42 | + .build(); |
| 43 | +consumer.run(); // blocking-reserves until the thread is interrupted |
| 44 | +``` |
| 45 | + |
| 46 | +Point the `RedisClient` at any Redis (local, cluster via the appropriate client, or a |
| 47 | +managed instance). The command seam is Lettuce's `RedisCommands<String, String>` |
| 48 | +interface, so it is trivially mockable in your own tests. |
| 49 | + |
| 50 | +## Contract mapping (§1) |
| 51 | + |
| 52 | +| Envelope | Redis | |
| 53 | +| :--- | :--- | |
| 54 | +| body | the list element — the canonical envelope JSON, **byte-for-byte, no wrapping** | |
| 55 | +| `job` (URN) | read from the body and routed consumer-side (Redis lists carry no native metadata) | |
| 56 | +| produce | `RPUSH <queue> <envelope>` | |
| 57 | +| reserve | `BLMOVE <queue> <queue>:processing LEFT RIGHT` (head → tail; crash-safe in-flight) | |
| 58 | +| ack | `LREM <queue>:processing 1 <envelope>` | |
| 59 | +| `attempts` | taken from the body unchanged (Redis has no native delivery counter) | |
| 60 | + |
| 61 | +Redis lists have **no native attribute channel**, so — unlike the SQS/RabbitMQ/Kafka |
| 62 | +bindings — there is **no property projection**. The single cross-SDK invariant is |
| 63 | +**payload identity**: the stored element is the exact envelope bytes, with no outer |
| 64 | +job-structure and no added fields. |
| 65 | + |
| 66 | +Retry is **at-least-once**: a throwing handler leaves the message on the |
| 67 | +`<queue>:processing` list (a recovery sweep can requeue it); a successful handler `LREM`s |
| 68 | +it. The poll loop never stops on a bad message — observe via `onError` / `onUnknownUrn`. |
| 69 | +The envelope is unchanged (`schema_version` stays `1`); Redis is purely additive. |
| 70 | + |
| 71 | +> **Scope.** This is a **Java-owned reliable queue**, mirroring the Go runtime's |
| 72 | +> reliable-queue mechanism. Pointed at a queue this SDK owns end-to-end it is a complete, |
| 73 | +> crash-safe transport. **Full parity with Laravel's reserved-sorted-set reservation on a |
| 74 | +> _shared_ PHP+Java Redis queue is a separate task** (see broker-bindings §1.4): a |
| 75 | +> consumer reading a queue produced by the Laravel driver must replicate Laravel's |
| 76 | +> reserve/ack semantics. |
| 77 | +
|
| 78 | +## Build & test |
| 79 | + |
| 80 | +```bash |
| 81 | +mvn verify |
| 82 | +``` |
| 83 | + |
| 84 | +Unit tests mock the `RedisCommands` seam (no Redis, no network) and capture the |
| 85 | +`RPUSH`/`BLMOVE`/`LREM` calls with Mockito. JaCoCo gates the build at ≥90% line coverage. |
| 86 | + |
| 87 | +## License |
| 88 | + |
| 89 | +MIT |
0 commit comments