diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js index f535db2..a601d10 100644 --- a/docs/.vitepress/config.js +++ b/docs/.vitepress/config.js @@ -70,7 +70,7 @@ export default defineConfig({ collapsed: false, items: [ { - text: 'mule-chunking-connector', + text: 'Chunking Connector', collapsed: false, items: [ { text: 'Overview', link: '/connectors/mule-chunking-connector/' }, @@ -86,7 +86,7 @@ export default defineConfig({ ] }, { - text: 'mule-idp-connector', + text: 'IDP Connector', collapsed: false, items: [ { text: 'Overview', link: '/connectors/mule-idp-connector/' }, @@ -111,6 +111,33 @@ export default defineConfig({ { text: 'Universal REST Smart Connector', link: '/connectors/mule-idp-connector/mulesoft-idp-universal-rest-smart-connector' }, { text: 'Dataweave', link: '/connectors/mule-idp-connector/dataweave' } ] + }, + { + text: 'Lettuce Redis Connector', + collapsed: false, + items: [ + { text: 'Overview', link: '/connectors/mule-lettuce-redis-connector/' }, + { text: 'Set Up', link: '/connectors/mule-lettuce-redis-connector/set-up' }, + { + text: 'Operations', + collapsed: true, + items: [ + { text: 'Operations Overview', link: '/connectors/mule-lettuce-redis-connector/operations/' }, + { text: 'Server', link: '/connectors/mule-lettuce-redis-connector/operations/server' }, + { text: 'Key / Value', link: '/connectors/mule-lettuce-redis-connector/operations/key-value' }, + { text: 'Hash', link: '/connectors/mule-lettuce-redis-connector/operations/hash' }, + { text: 'List', link: '/connectors/mule-lettuce-redis-connector/operations/list' }, + { text: 'Set', link: '/connectors/mule-lettuce-redis-connector/operations/set' }, + { text: 'Sorted Set', link: '/connectors/mule-lettuce-redis-connector/operations/sorted-set' }, + { text: 'Geospatial', link: '/connectors/mule-lettuce-redis-connector/operations/geospatial' }, + { text: 'Stream', link: '/connectors/mule-lettuce-redis-connector/operations/stream' }, + { text: 'Channel', link: '/connectors/mule-lettuce-redis-connector/operations/channel' }, + { text: 'Send Command', link: '/connectors/mule-lettuce-redis-connector/operations/send-command' }, + { text: 'Search Operations', link: '/connectors/mule-lettuce-redis-connector/operations/search-operations' } + ] + }, + { text: 'Sources (Listeners)', link: '/connectors/mule-lettuce-redis-connector/sources' } + ] } ] }, @@ -121,7 +148,7 @@ export default defineConfig({ collapsed: false, items: [ { - text: 'mule-pdfbox-module', + text: 'PDFBox Module', collapsed: false, items: [ { text: 'Overview', link: '/modules/mule-pdfbox-module/' }, diff --git a/docs/connectors/mule-lettuce-redis-connector/index.md b/docs/connectors/mule-lettuce-redis-connector/index.md new file mode 100644 index 0000000..be1d381 --- /dev/null +++ b/docs/connectors/mule-lettuce-redis-connector/index.md @@ -0,0 +1,70 @@ +--- +title: Mule Lettuce Redis Connector +description: Direct access to Redis commands from Mule applications, built on the Lettuce reactive Redis client. +--- + +# Lettuce Redis Connector + +A low-level connector providing Mule applications with direct access to Redis commands, built on the [Lettuce](https://lettuce.io/) reactive Redis client library. Published on Maven Central under `cloud.anypoint`. + +The connector's goal is to provide full coverage of all documented Redis commands, organized by Redis data structure. For commands not yet implemented as dedicated operations, the [Send Command](./operations/send-command) operation lets you execute any arbitrary Redis command. + +## Features + +- **Broad command coverage**: Dedicated operations for strings, hashes, lists, sets, sorted sets, geospatial indexes, and streams +- **Pub/Sub event sources**: Trigger Mule flows in real time from Redis channels using SUBSCRIBE and PSUBSCRIBE +- **Dynamic command execution**: [Send Command](./operations/send-command) executes any Redis command not yet available as a dedicated operation +- **Automated SCAN iteration**: [Search Operations](./operations/search-operations) handle Redis cursor management internally, streaming full result sets without manual loop logic +- **Maven Central**: Install with a single Maven dependency — no local builds required + +## Quick Example + +```xml + + + + + + + + + + + + + +``` + +## Supported Command Categories + +| Category | Operations | Page | +|----------|-----------|------| +| Server | PING | [Server](./operations/server) | +| Key / Value | APPEND, COPY, DECR, DEL, EXPIRE, GET, GETDEL, GETEX, GETRANGE, GETSET, INCR, MGET, MSET, PERSIST, PEXPIRE, PTTL, SCAN, SET, TOUCH, TTL | [Key / Value](./operations/key-value) | +| Hash | HEXISTS, HGET, HGETALL, HINCRBY, HLEN, HMGET, HSCAN, HSET | [Hash](./operations/hash) | +| List | BLMOVE, BLPOP, BRPOP, LMOVE, LPOP, LPUSH, LSET, RPOP, RPUSH | [List](./operations/list) | +| Set | SADD, SCARD, SDIFF, SISMEMBER, SMEMBERS, SMISMEMBER, SPOP, SRANDMEMBER, SREM, SSCAN | [Set](./operations/set) | +| Sorted Set | ZADD, ZINCRBY, ZRANK, ZSCAN, ZSCORE | [Sorted Set](./operations/sorted-set) | +| Geospatial | GEOADD, GEODIST, GEOPOS, GEOSEARCH | [Geospatial](./operations/geospatial) | +| Stream | XACK, XADD, XDEL, XGROUP CREATE, XGROUP DESTROY, XINFO GROUPS, XRANGE, XREAD, XREADGROUP, XTRIM | [Stream](./operations/stream) | +| Channel | PUBLISH | [Channel](./operations/channel) | +| Send Command | Any Redis command (dynamic) | [Send Command](./operations/send-command) | +| Search Operations | Automated SCAN, HSCAN, SSCAN, ZSCAN iteration | [Search Operations](./operations/search-operations) | +| Sources (Listeners) | SUBSCRIBE, PSUBSCRIBE | [Sources](./sources) | + +## Requirements + +- **Mule Runtime**: 4.6.0 or later +- **Java**: 8, 11, or 17 +- **Redis**: Any version supporting the commands you use + +## Learn More + +- [Set Up Guide](./set-up) — Installation and connection configuration +- [Operations Reference](./operations/) — All operations by category +- [Sources (Listeners)](./sources) — Pub/Sub event-driven flows +- [GitHub Repository](https://github.com/anypointcloud/mule-lettuce-redis-connector) — Source code and issues diff --git a/docs/connectors/mule-lettuce-redis-connector/operations/channel.md b/docs/connectors/mule-lettuce-redis-connector/operations/channel.md new file mode 100644 index 0000000..17b617c --- /dev/null +++ b/docs/connectors/mule-lettuce-redis-connector/operations/channel.md @@ -0,0 +1,110 @@ +--- +title: Channel Commands — Lettuce Redis Connector +description: Reference for channel (Pub/Sub) Redis commands in the Mule Lettuce Redis Connector +--- + +# Channel Commands + +Channel commands are used to send messages to Redis Pub/Sub channels. To receive messages, see [Sources (Listeners)](../sources). + +This page covers: **PUBLISH** + +--- + +## PUBLISH + +Publish a message to a Redis Pub/Sub channel. + +> 📘 **Redis Reference**: [PUBLISH](https://redis.io/docs/latest/commands/publish/) + +### XML Example + +```xml + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `channel` | String | Yes | — | The name of the channel to publish to | +| `message` | String | Yes | — | The message content to publish | + +### Output + +**Type**: `Long` + +The number of subscribers that received the message. A return value of `0` means no clients were subscribed to the channel when the message was published. + +::: warning Message Delivery +Redis Pub/Sub is fire-and-forget. If no subscriber is listening when PUBLISH is called, the message is lost. For durable messaging, consider using [Redis Streams](./stream) instead. +::: + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | Connection failure or server error | + +### Usage + +::: info Configuration +PUBLISH uses the **standard configuration** (`lettuce-redis:config`), not the pub/sub configuration. Only the SUBSCRIBE and PSUBSCRIBE sources require the pub/sub configuration. +::: + +**Common pattern: Publish and subscribe in the same application** + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +### See Also + +- [Sources (Listeners)](../sources) — SUBSCRIBE and PSUBSCRIBE for receiving messages +- [Redis Streams](./stream) — Durable, persistent messaging with consumer groups diff --git a/docs/connectors/mule-lettuce-redis-connector/operations/geospatial.md b/docs/connectors/mule-lettuce-redis-connector/operations/geospatial.md new file mode 100644 index 0000000..dbbd296 --- /dev/null +++ b/docs/connectors/mule-lettuce-redis-connector/operations/geospatial.md @@ -0,0 +1,347 @@ +--- +title: Geospatial Commands — Lettuce Redis Connector +description: Reference for geospatial Redis commands in the Mule Lettuce Redis Connector +--- + +# Geospatial Commands + +Geospatial commands operate on Redis geospatial indexes — sorted sets where each member represents a location with longitude and latitude coordinates. Useful for location-based queries like "find nearby points" or "calculate distance between locations". + +This page covers: **GEOADD**, **GEODIST**, **GEOPOS**, **GEOSEARCH** + +--- + +## GEOADD + +Add one or more geospatial items (longitude, latitude, name) to a geospatial index. + +> 📘 **Redis Reference**: [GEOADD](https://redis.io/docs/latest/commands/geoadd/) + +### XML Example + +```xml + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The geospatial index key | +| `items` | List\ | Yes | — | Locations to add. At least one required. Each item has: `name` (String), `longitude` (double), `latitude` (double). | +| `nx` | boolean | No | `false` | Only add new members (do not update existing) | +| `xx` | boolean | No | `false` | Only update existing members (do not add new) | +| `ch` | boolean | No | `false` | Change the return value to count **changed** members instead of **added** members | + +**GeospatialItem structure**: +```dataweave +{ + name: "location-name", // String + longitude: -122.4194, // double + latitude: 37.7749 // double +} +``` + +### Output + +**Type**: `Long` + +The number of elements added to the index. When `ch=true`, returns the number of elements added or updated. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | No items provided, or invalid coordinates | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a sorted set (geospatial index) | + +--- + +## GEOPOS + +Get the longitude and latitude coordinates of one or more members in a geospatial index. + +> 📘 **Redis Reference**: [GEOPOS](https://redis.io/docs/latest/commands/geopos/) + +### XML Example + +```xml + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The geospatial index key | +| `members` | List\ | Yes | — | Member names to look up. At least one required. Payload by default via `@Content`. | + +### Output + +**Type**: `List` + +A list of locations, one for each input member. If a member does not exist, its entry in the list is `null`. + +**GeoLocation structure**: +```dataweave +{ + longitude: -122.4194, // double + latitude: 37.7749 // double +} +``` + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | No members provided | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a geospatial index | + +--- + +## GEODIST + +Calculate the distance between two members in a geospatial index. + +> 📘 **Redis Reference**: [GEODIST](https://redis.io/docs/latest/commands/geodist/) + +### XML Example + +```xml + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The geospatial index key | +| `member1` | String | Yes | — | First member | +| `member2` | String | Yes | — | Second member | +| `unit` | DistanceUnit | No | `M` | Unit for the returned distance: `M` (meters), `KM` (kilometers), `FT` (feet), `MI` (miles) | + +**DistanceUnit values**: `M`, `KM`, `FT`, `MI` + +### Output + +**Type**: `Double` + +The distance between the two members in the specified unit. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a geospatial index | + +--- + +## GEOSEARCH + +Search for members in a geospatial index within a specified area. + +> 📘 **Redis Reference**: [GEOSEARCH](https://redis.io/docs/latest/commands/geosearch/) + +GEOSEARCH is the most complex operation in the connector due to its many configuration options. It supports searching by radius or by box, from a member location or from explicit coordinates, with optional result options (coordinates, distance, geohash). + +::: warning Static Configuration Required +The `searchCenter` and `searchBy` parameters are `@Expression(NOT_SUPPORTED)` — they **must** be configured statically in XML. DataWeave expressions cannot be used for these parameters. +::: + +### XML Examples + +**Search by radius from a member:** + +```xml + + + + + +``` + +**Search by radius from coordinates:** + +```xml + + + + + + + + +``` + +**Search by box:** + +```xml + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The geospatial index key | +| `searchCenter` | GeoSearchCenter | Yes | — | Origin of the search. See structures below. | +| `searchBy` | GeoSearchBy | Yes | — | Search shape (radius or box). See structures below. | +| `sortOrder` | SortOrder | Yes | — | Sort results by distance: `NONE`, `ASC`, or `DESC` | +| `count` | Integer | No | — | Maximum number of results to return | +| `countAny` | boolean | No | `false` | If true, return any `count` results (not necessarily the closest) | +| `searchResultOptions` | GeoSearchResultOption | Yes | — | What to include in results: `withCoord`, `withDist`, `withHash` | + +**GeoSearchCenter** (choose one): + +| Type | Structure | +|------|-----------| +| `fromMember` | `{fromMember: "member-name"}` | +| `fromLatLong` | `{fromLatLong: {latitude: 37.7749, longitude: -122.4194}}` | + +**GeoSearchBy** (choose one): + +| Type | Structure | +|------|-----------| +| `byRadius` | `{byRadius: {radius: 10.0, unit: 'KM'}}` | +| `byBox` | `{byBox: {width: 20.0, height: 15.0, unit: 'KM'}}` | + +**GeoSearchResultOption** (parameter group): + +| Field | Type | Default | Description | +|-------|------|---------|-------------| +| `withCoord` | boolean | `false` | Include coordinates in results | +| `withDist` | boolean | `false` | Include distance from search center in results | +| `withHash` | boolean | `false` | Include geohash integer in results | + +**SortOrder values**: `NONE`, `ASC`, `DESC` + +**DistanceUnit values** (for radius and box): `M`, `KM`, `FT`, `MI` + +### Output + +**Type**: `List` (dynamic, resolved by metadata based on `searchResultOptions`) + +**When no result options are enabled** (`withCoord=false`, `withDist=false`, `withHash=false`): +- **Type**: `List` — Member names only + +**When one or more result options are enabled**: +- **Type**: `List` — Each element is a map with the following fields: + - `"member"` → String (always present) — The member name + - `"latitude"` → Number (if `withCoord=true`) — Latitude coordinate + - `"longitude"` → Number (if `withCoord=true`) — Longitude coordinate + - `"distance"` → Number (if `withDist=true`) — Distance from search center + - `"hash"` → Number (if `withHash=true`) — Geohash value + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | Invalid search parameters | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a geospatial index | + +### Complete Example: Nearby Store Finder + +```xml + + + + + + + + + + + + + + + +``` diff --git a/docs/connectors/mule-lettuce-redis-connector/operations/hash.md b/docs/connectors/mule-lettuce-redis-connector/operations/hash.md new file mode 100644 index 0000000..fcb005b --- /dev/null +++ b/docs/connectors/mule-lettuce-redis-connector/operations/hash.md @@ -0,0 +1,354 @@ +--- +title: Hash Commands — Lettuce Redis Connector +description: Reference for hash Redis commands in the Mule Lettuce Redis Connector +--- + +# Hash Commands + +Hash commands operate on Redis hashes — maps between string fields and string values. Hashes are ideal for representing objects with multiple fields. + +This page covers: **HEXISTS**, **HGET**, **HGETALL**, **HINCRBY**, **HLEN**, **HMGET**, **HSCAN**, **HSET** + +--- + +## HSET + +Set one or more fields in a hash. + +> 📘 **Redis Reference**: [HSET](https://redis.io/docs/latest/commands/hset/) + +### XML Example + +```xml + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The hash key | +| `fields` | Map\ | Yes | — | Field-value pairs to set. Map must not be empty. Payload by default via `@Content`. | + +### Output + +**Type**: `Long` + +The number of **new** fields added. Updates to existing fields are not counted. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | Fields map is empty | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a hash | + +--- + +## HGET + +Get the value of a hash field. + +> 📘 **Redis Reference**: [HGET](https://redis.io/docs/latest/commands/hget/) + +### XML Example + +```xml + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The hash key | +| `field` | String | Yes | — | The field name to retrieve | + +### Output + +**Type**: `String` (media type: `text/plain`) + +The value of the field. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:NIL` | Field does not exist in the hash | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a hash | + +--- + +## HGETALL + +Get all fields and values in a hash. + +> 📘 **Redis Reference**: [HGETALL](https://redis.io/docs/latest/commands/hgetall/) + +### XML Example + +```xml + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The hash key | + +### Output + +**Type**: `Map` + +A map of all field-value pairs in the hash. Returns an empty map if the hash does not exist. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a hash | + +--- + +## HMGET + +Get the values of multiple hash fields. + +> 📘 **Redis Reference**: [HMGET](https://redis.io/docs/latest/commands/hmget/) + +### XML Example + +```xml + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The hash key | +| `fieldNames` | List\ | Yes | — | Field names to retrieve. At least one required. Fields must be defined inline (`allowInlineDefinition=true, allowReferences=false`). | + +### Output + +**Type**: `Map` + +A map of field names to values. If a field does not exist in the hash, its value in the map is `null`. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | No field names provided | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a hash | + +--- + +## HEXISTS + +Check if a field exists in a hash. + +> 📘 **Redis Reference**: [HEXISTS](https://redis.io/docs/latest/commands/hexists/) + +### XML Example + +```xml + + + + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The hash key | +| `field` | String | Yes | — | The field to check | + +### Output + +**Type**: `Boolean` + +- `true` if the field exists in the hash +- `false` if the field does not exist or the hash does not exist + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a hash | + +--- + +## HLEN + +Get the number of fields in a hash. + +> 📘 **Redis Reference**: [HLEN](https://redis.io/docs/latest/commands/hlen/) + +### XML Example + +```xml + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The hash key | + +### Output + +**Type**: `Long` + +The number of fields in the hash. Returns `0` if the hash does not exist. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a hash | + +--- + +## HINCRBY + +Increment the integer value of a hash field by the specified amount. + +> 📘 **Redis Reference**: [HINCRBY](https://redis.io/docs/latest/commands/hincrby/) + +### XML Example + +```xml + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The hash key | +| `field` | String | Yes | — | The field to increment | +| `increment` | Long | Yes | — | The amount to add (can be negative for decrement) | + +### Output + +**Type**: `Long` + +The new value of the field after the increment. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a hash, or field does not hold an integer value | + +--- + +## HSCAN + +Incrementally iterate hash fields using a cursor. + +> 📘 **Redis Reference**: [HSCAN](https://redis.io/docs/latest/commands/hscan/) + +::: tip Automated Cursor Management +For most use cases, consider using [Search Hash Fields](./search-operations#search-hash-fields) instead, which handles cursor iteration automatically and streams all field-value pairs. Use HSCAN directly only when you need fine-grained control over pagination. +::: + +### XML Example + +```xml + + + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The hash key to scan | +| `cursor` | Integer | Yes | — | Cursor position. Use `0` to start a new scan. | +| `match` | String | No | — | Glob-style pattern to filter field names | +| `count` | Integer | No | — | Hint for the number of elements to return per iteration | + +### Output + +**Type**: `Map` + +A map of field-value pairs matching the pattern for this scan iteration. + +**Attributes**: `ScanAttributes` — Contains the `cursor` field with the next cursor value. When `cursor` is `0`, the scan is complete. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a hash | diff --git a/docs/connectors/mule-lettuce-redis-connector/operations/index.md b/docs/connectors/mule-lettuce-redis-connector/operations/index.md new file mode 100644 index 0000000..2957085 --- /dev/null +++ b/docs/connectors/mule-lettuce-redis-connector/operations/index.md @@ -0,0 +1,146 @@ +--- +title: Operations +description: Complete reference of all operations in the Mule Lettuce Redis Connector, organized by Redis command category. +--- + +# Operations + +The Mule Lettuce Redis Connector provides operations in two categories: + +- **Category A — Redis Command Mirrors**: Operations that map directly to a single Redis command. These are reference-style: if you know the Redis command, the operation works the same way. +- **Category B — Value-Add Features**: Operations that go beyond a single command, providing automation or capabilities not available in raw Redis. + +--- + +## Category A: Redis Command Operations + +### Server + +| Operation | Redis Command | Page | +|-----------|--------------|------| +| PING | [PING](https://redis.io/docs/latest/commands/ping/) | [Server](./server#ping) | + +### Key / Value + +| Operation | Redis Command | Page | +|-----------|--------------|------| +| APPEND | [APPEND](https://redis.io/docs/latest/commands/append/) | [Key / Value](./key-value#append) | +| COPY | [COPY](https://redis.io/docs/latest/commands/copy/) | [Key / Value](./key-value#copy) | +| DECR | [DECR](https://redis.io/docs/latest/commands/decr/) | [Key / Value](./key-value#decr) | +| DEL | [DEL](https://redis.io/docs/latest/commands/del/) | [Key / Value](./key-value#del) | +| EXPIRE | [EXPIRE](https://redis.io/docs/latest/commands/expire/) | [Key / Value](./key-value#expire) | +| GET | [GET](https://redis.io/docs/latest/commands/get/) | [Key / Value](./key-value#get) | +| GETDEL | [GETDEL](https://redis.io/docs/latest/commands/getdel/) | [Key / Value](./key-value#getdel) | +| GETEX | [GETEX](https://redis.io/docs/latest/commands/getex/) | [Key / Value](./key-value#getex) | +| GETRANGE | [GETRANGE](https://redis.io/docs/latest/commands/getrange/) | [Key / Value](./key-value#getrange) | +| GETSET | [GETSET](https://redis.io/docs/latest/commands/getset/) | [Key / Value](./key-value#getset) | +| INCR | [INCR](https://redis.io/docs/latest/commands/incr/) | [Key / Value](./key-value#incr) | +| MGET | [MGET](https://redis.io/docs/latest/commands/mget/) | [Key / Value](./key-value#mget) | +| MSET | [MSET](https://redis.io/docs/latest/commands/mset/) | [Key / Value](./key-value#mset) | +| PERSIST | [PERSIST](https://redis.io/docs/latest/commands/persist/) | [Key / Value](./key-value#persist) | +| PEXPIRE | [PEXPIRE](https://redis.io/docs/latest/commands/pexpire/) | [Key / Value](./key-value#pexpire) | +| PTTL | [PTTL](https://redis.io/docs/latest/commands/pttl/) | [Key / Value](./key-value#pttl) | +| SCAN | [SCAN](https://redis.io/docs/latest/commands/scan/) | [Key / Value](./key-value#scan) | +| SET | [SET](https://redis.io/docs/latest/commands/set/) | [Key / Value](./key-value#set) | +| TOUCH | [TOUCH](https://redis.io/docs/latest/commands/touch/) | [Key / Value](./key-value#touch) | +| TTL | [TTL](https://redis.io/docs/latest/commands/ttl/) | [Key / Value](./key-value#ttl) | + +### Hash + +| Operation | Redis Command | Page | +|-----------|--------------|------| +| HEXISTS | [HEXISTS](https://redis.io/docs/latest/commands/hexists/) | [Hash](./hash#hexists) | +| HGET | [HGET](https://redis.io/docs/latest/commands/hget/) | [Hash](./hash#hget) | +| HGETALL | [HGETALL](https://redis.io/docs/latest/commands/hgetall/) | [Hash](./hash#hgetall) | +| HINCRBY | [HINCRBY](https://redis.io/docs/latest/commands/hincrby/) | [Hash](./hash#hincrby) | +| HLEN | [HLEN](https://redis.io/docs/latest/commands/hlen/) | [Hash](./hash#hlen) | +| HMGET | [HMGET](https://redis.io/docs/latest/commands/hmget/) | [Hash](./hash#hmget) | +| HSCAN | [HSCAN](https://redis.io/docs/latest/commands/hscan/) | [Hash](./hash#hscan) | +| HSET | [HSET](https://redis.io/docs/latest/commands/hset/) | [Hash](./hash#hset) | + +### List + +| Operation | Redis Command | Page | +|-----------|--------------|------| +| BLMOVE | [BLMOVE](https://redis.io/docs/latest/commands/blmove/) | [List](./list#blmove) | +| BLPOP | [BLPOP](https://redis.io/docs/latest/commands/blpop/) | [List](./list#blpop) | +| BRPOP | [BRPOP](https://redis.io/docs/latest/commands/brpop/) | [List](./list#brpop) | +| LMOVE | [LMOVE](https://redis.io/docs/latest/commands/lmove/) | [List](./list#lmove) | +| LPOP | [LPOP](https://redis.io/docs/latest/commands/lpop/) | [List](./list#lpop) | +| LPUSH | [LPUSH](https://redis.io/docs/latest/commands/lpush/) | [List](./list#lpush) | +| LSET | [LSET](https://redis.io/docs/latest/commands/lset/) | [List](./list#lset) | +| RPOP | [RPOP](https://redis.io/docs/latest/commands/rpop/) | [List](./list#rpop) | +| RPUSH | [RPUSH](https://redis.io/docs/latest/commands/rpush/) | [List](./list#rpush) | + +### Set + +| Operation | Redis Command | Page | +|-----------|--------------|------| +| SADD | [SADD](https://redis.io/docs/latest/commands/sadd/) | [Set](./set#sadd) | +| SCARD | [SCARD](https://redis.io/docs/latest/commands/scard/) | [Set](./set#scard) | +| SDIFF | [SDIFF](https://redis.io/docs/latest/commands/sdiff/) | [Set](./set#sdiff) | +| SISMEMBER | [SISMEMBER](https://redis.io/docs/latest/commands/sismember/) | [Set](./set#sismember) | +| SMEMBERS | [SMEMBERS](https://redis.io/docs/latest/commands/smembers/) | [Set](./set#smembers) | +| SMISMEMBER | [SMISMEMBER](https://redis.io/docs/latest/commands/smismember/) | [Set](./set#smismember) | +| SPOP | [SPOP](https://redis.io/docs/latest/commands/spop/) | [Set](./set#spop) | +| SRANDMEMBER | [SRANDMEMBER](https://redis.io/docs/latest/commands/srandmember/) | [Set](./set#srandmember) | +| SREM | [SREM](https://redis.io/docs/latest/commands/srem/) | [Set](./set#srem) | +| SSCAN | [SSCAN](https://redis.io/docs/latest/commands/sscan/) | [Set](./set#sscan) | + +### Sorted Set + +| Operation | Redis Command | Page | +|-----------|--------------|------| +| ZADD | [ZADD](https://redis.io/docs/latest/commands/zadd/) | [Sorted Set](./sorted-set#zadd) | +| ZINCRBY | [ZINCRBY](https://redis.io/docs/latest/commands/zincrby/) | [Sorted Set](./sorted-set#zincrby) | +| ZRANK | [ZRANK](https://redis.io/docs/latest/commands/zrank/) | [Sorted Set](./sorted-set#zrank) | +| ZSCAN | [ZSCAN](https://redis.io/docs/latest/commands/zscan/) | [Sorted Set](./sorted-set#zscan) | +| ZSCORE | [ZSCORE](https://redis.io/docs/latest/commands/zscore/) | [Sorted Set](./sorted-set#zscore) | + +### Geospatial + +| Operation | Redis Command | Page | +|-----------|--------------|------| +| GEOADD | [GEOADD](https://redis.io/docs/latest/commands/geoadd/) | [Geospatial](./geospatial#geoadd) | +| GEODIST | [GEODIST](https://redis.io/docs/latest/commands/geodist/) | [Geospatial](./geospatial#geodist) | +| GEOPOS | [GEOPOS](https://redis.io/docs/latest/commands/geopos/) | [Geospatial](./geospatial#geopos) | +| GEOSEARCH | [GEOSEARCH](https://redis.io/docs/latest/commands/geosearch/) | [Geospatial](./geospatial#geosearch) | + +### Stream + +| Operation | Redis Command | Page | +|-----------|--------------|------| +| XACK | [XACK](https://redis.io/docs/latest/commands/xack/) | [Stream](./stream#xack) | +| XADD | [XADD](https://redis.io/docs/latest/commands/xadd/) | [Stream](./stream#xadd) | +| XDEL | [XDEL](https://redis.io/docs/latest/commands/xdel/) | [Stream](./stream#xdel) | +| XGROUP CREATE | [XGROUP CREATE](https://redis.io/docs/latest/commands/xgroup-create/) | [Stream](./stream#xgroup-create) | +| XGROUP DESTROY | [XGROUP DESTROY](https://redis.io/docs/latest/commands/xgroup-destroy/) | [Stream](./stream#xgroup-destroy) | +| XINFO GROUPS | [XINFO GROUPS](https://redis.io/docs/latest/commands/xinfo-groups/) | [Stream](./stream#xinfo-groups) | +| XRANGE | [XRANGE](https://redis.io/docs/latest/commands/xrange/) | [Stream](./stream#xrange) | +| XREAD | [XREAD](https://redis.io/docs/latest/commands/xread/) | [Stream](./stream#xread) | +| XREADGROUP | [XREADGROUP](https://redis.io/docs/latest/commands/xreadgroup/) | [Stream](./stream#xreadgroup) | +| XTRIM | [XTRIM](https://redis.io/docs/latest/commands/xtrim/) | [Stream](./stream#xtrim) | + +### Channel + +| Operation | Redis Command | Page | +|-----------|--------------|------| +| PUBLISH | [PUBLISH](https://redis.io/docs/latest/commands/publish/) | [Channel](./channel#publish) | + +--- + +## Category B: Value-Add Operations + +| Operation | Description | Page | +|-----------|-------------|------| +| Send Command | Execute any Redis command dynamically by name. Use for commands not yet available as dedicated operations. | [Send Command](./send-command) | +| Search Keys | Stream all keys matching a pattern via automated SCAN cursor iteration | [Search Operations](./search-operations#search-keys) | +| Search Hash Fields | Stream all fields in a hash via automated HSCAN cursor iteration | [Search Operations](./search-operations#search-hash-fields) | +| Search Set Members | Stream all members in a set via automated SSCAN cursor iteration | [Search Operations](./search-operations#search-set-members) | +| Search Sorted Set Members | Stream all members and scores in a sorted set via automated ZSCAN cursor iteration | [Search Operations](./search-operations#search-sorted-set-members) | + +--- + +## Sources (Event Listeners) + +Sources are not operations — they are Mule event listeners that trigger flows when Redis delivers a message. See the [Sources](../sources) page for SUBSCRIBE and PSUBSCRIBE. diff --git a/docs/connectors/mule-lettuce-redis-connector/operations/key-value.md b/docs/connectors/mule-lettuce-redis-connector/operations/key-value.md new file mode 100644 index 0000000..daad9b7 --- /dev/null +++ b/docs/connectors/mule-lettuce-redis-connector/operations/key-value.md @@ -0,0 +1,903 @@ +--- +title: Key / Value Commands — Lettuce Redis Connector +description: Reference for key/value Redis commands in the Mule Lettuce Redis Connector +--- + +# Key / Value Commands + +Key/Value commands operate on Redis string values — the most basic Redis data type. Strings can hold any kind of data: text, JSON, serialized objects, or binary data. + +This page covers: **APPEND**, **COPY**, **DECR**, **DEL**, **EXPIRE**, **GET**, **GETDEL**, **GETEX**, **GETRANGE**, **GETSET**, **INCR**, **MGET**, **MSET**, **PERSIST**, **PEXPIRE**, **PTTL**, **SCAN**, **SET**, **TOUCH**, **TTL** + +--- + +## SET + +Set a key to hold a string value, with optional expiry and conditional flags. + +> 📘 **Redis Reference**: [SET](https://redis.io/docs/latest/commands/set/) + +### XML Example + +```xml + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The key to set | +| `value` | String | Yes | — | The value to store (payload by default via `@Content`) | +| `xx` | boolean | No | `false` | Only set if key already exists | +| `nx` | boolean | No | `false` | Only set if key does NOT exist (use for "create if not exists" semantics) | +| `get` | boolean | No | `false` | Return the old value before setting the new one | +| `ex` | Integer | No | — | Expiry time in seconds | +| `px` | Integer | No | — | Expiry time in milliseconds | +| `exat` | Integer | No | — | Expiry as Unix timestamp in seconds | +| `pxat` | Integer | No | — | Expiry as Unix timestamp in milliseconds | +| `keepttl` | boolean | No | `false` | Retain the existing TTL (if key already exists with a TTL) | + +::: info Mutually Exclusive TTL Options +Only one of `ex`, `px`, `exat`, `pxat`, or `keepttl` should be specified. The Redis server enforces this constraint. +::: + +### Output + +**Type**: `String` (media type: `text/plain`) + +- Returns `"OK"` when the operation succeeds +- Returns the old value if `get="true"` was specified + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | + +--- + +## GET + +Retrieve the string value of a key. + +> 📘 **Redis Reference**: [GET](https://redis.io/docs/latest/commands/get/) + +### XML Example + +```xml + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The key to retrieve | + +### Output + +**Type**: `String` (media type: `text/plain`) + +The value stored at the key. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:NIL` | Key does not exist | +| `REDIS:COMMAND` | General command execution error | + +::: warning GET Throws on Missing Keys +If the key does not exist, GET throws a `REDIS:NIL` error rather than returning `null`. Use error handling to manage missing keys gracefully. +::: + +**Error handling pattern:** + +```xml + + + + + + + + + + + +``` + +--- + +## MGET + +Retrieve the values of multiple keys in a single operation. + +> 📘 **Redis Reference**: [MGET](https://redis.io/docs/latest/commands/mget/) + +::: tip MGET Implementation Note +This operation is fully implemented and working, but is not listed in the connector's README. It is safe to use in production. +::: + +### XML Example + +```xml + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `keys` | List\ | Yes | — | One or more keys to retrieve. At least one required. | + +### Output + +**Type**: `List` + +A list of values in the same order as the input keys. If a key does not exist or holds the wrong type, the corresponding list entry is `null`. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | No keys provided | +| `REDIS:COMMAND` | General command execution error | + +--- + +## MSET + +Set multiple key-value pairs atomically. + +> 📘 **Redis Reference**: [MSET](https://redis.io/docs/latest/commands/mset/) + +### XML Example + +```xml + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `keyValues` | Map\ | Yes | — | Map of key-value pairs to set. Payload by default via `@Content`. | + +### Output + +**Type**: `Void` + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | + +--- + +## APPEND + +Append a string to the value of a key. If the key does not exist, it is created with the appended string as its value. + +> 📘 **Redis Reference**: [APPEND](https://redis.io/docs/latest/commands/append/) + +### XML Example + +```xml + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The key to append to | +| `value` | String | Yes | — | The string to append (payload by default via `@Content`) | + +### Output + +**Type**: `Long` + +The new total length of the string after appending. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:WRONG_TYPE` | Key exists but holds a non-string value | +| `REDIS:COMMAND` | General command execution error | + +--- + +## INCR + +Increment the integer value of a key by 1. + +> 📘 **Redis Reference**: [INCR](https://redis.io/docs/latest/commands/incr/) + +### XML Example + +```xml + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The key whose value to increment | + +### Output + +**Type**: `Long` + +The value of the key after incrementing. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:WRONG_TYPE` | Key exists but does not hold a string representation of an integer | +| `REDIS:COMMAND` | General command execution error | + +--- + +## DECR + +Decrement the integer value of a key by 1. + +> 📘 **Redis Reference**: [DECR](https://redis.io/docs/latest/commands/decr/) + +### XML Example + +```xml + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The key whose value to decrement | + +### Output + +**Type**: `Long` + +The value of the key after decrementing. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:WRONG_TYPE` | Key exists but does not hold an integer value | +| `REDIS:COMMAND` | General command execution error | + +--- + +## DEL + +Delete one or more keys. + +> 📘 **Redis Reference**: [DEL](https://redis.io/docs/latest/commands/del/) + +### XML Example + +```xml + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `keys` | List\ | Yes | — | One or more keys to delete | + +### Output + +**Type**: `Long` + +The number of keys that were deleted. Keys that did not exist are not counted. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | + +--- + +## EXPIRE + +Set a key's time to live (TTL) in seconds, with optional conditional flags. + +> 📘 **Redis Reference**: [EXPIRE](https://redis.io/docs/latest/commands/expire/) + +### XML Example + +```xml + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The key to set expiry on | +| `seconds` | Integer | Yes | — | TTL in seconds | +| `nx` | boolean | No | `false` | Only set expiry if key currently has no TTL | +| `xx` | boolean | No | `false` | Only set expiry if key already has a TTL | +| `gt` | boolean | No | `false` | Only set expiry if new TTL is greater than current TTL | +| `lt` | boolean | No | `false` | Only set expiry if new TTL is less than current TTL | + +### Output + +**Type**: `Boolean` + +- `true` if the expiry was set +- `false` if the expiry was not set (key doesn't exist or conditional flag prevented the operation) + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | Invalid combination of conditional flags | +| `REDIS:COMMAND` | General command execution error | + +--- + +## PEXPIRE + +Set a key's time to live (TTL) in milliseconds. + +> 📘 **Redis Reference**: [PEXPIRE](https://redis.io/docs/latest/commands/pexpire/) + +### XML Example + +```xml + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The key to set expiry on | +| `milliseconds` | Integer | Yes | — | TTL in milliseconds | +| `nx` | boolean | No | `false` | Only set expiry if key currently has no TTL | +| `xx` | boolean | No | `false` | Only set expiry if key already has a TTL | +| `gt` | boolean | No | `false` | Only set expiry if new TTL > current TTL | +| `lt` | boolean | No | `false` | Only set expiry if new TTL < current TTL | + +### Output + +**Type**: `Boolean` + +- `true` if the expiry was set +- `false` otherwise + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | Invalid combination of conditional flags | +| `REDIS:COMMAND` | General command execution error | + +--- + +## PERSIST + +Remove the expiration from a key, making it persistent. + +> 📘 **Redis Reference**: [PERSIST](https://redis.io/docs/latest/commands/persist/) + +### XML Example + +```xml + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The key to remove expiry from | + +### Output + +**Type**: `Boolean` + +- `true` if the TTL was removed +- `false` if the key does not exist or had no TTL + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | + +--- + +## TTL + +Get the remaining time to live (TTL) of a key in seconds. + +> 📘 **Redis Reference**: [TTL](https://redis.io/docs/latest/commands/ttl/) + +### XML Example + +```xml + + + + + + + + + + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The key to inspect | + +### Output + +**Type**: `Long` + +- Remaining TTL in seconds (positive value) +- `-1` if the key exists but has no associated expiry +- `-2` if the key does not exist + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | + +--- + +## PTTL + +Get the remaining time to live (TTL) of a key in milliseconds. + +> 📘 **Redis Reference**: [PTTL](https://redis.io/docs/latest/commands/pttl/) + +### XML Example + +```xml + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The key to inspect | + +### Output + +**Type**: `Long` + +- Remaining TTL in milliseconds (positive value) +- `-1` if the key exists but has no TTL +- `-2` if the key does not exist + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | + +--- + +## GETRANGE + +Get a substring of the value stored at a key. + +> 📘 **Redis Reference**: [GETRANGE](https://redis.io/docs/latest/commands/getrange/) + +### XML Example + +```xml + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The key to read from | +| `start` | Integer | Yes | — | Start index (inclusive, 0-based). Negative values count from the end. | +| `end` | Integer | Yes | — | End index (inclusive). Negative values count from the end. | + +### Output + +**Type**: `String` (media type: `text/plain`) + +The substring of the stored value. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:NIL` | Key does not exist | +| `REDIS:WRONG_TYPE` | Key exists but holds a non-string value | +| `REDIS:COMMAND` | General command execution error | + +--- + +## GETDEL + +Atomically get the value of a key and delete it. + +> 📘 **Redis Reference**: [GETDEL](https://redis.io/docs/latest/commands/getdel/) + +### XML Example + +```xml + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The key to get and delete | + +### Output + +**Type**: `String` (media type: `text/plain`) + +The value before deletion. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:NIL` | Key does not exist | +| `REDIS:WRONG_TYPE` | Key exists but holds a non-string value | +| `REDIS:COMMAND` | General command execution error | + +--- + +## GETEX + +Get the value of a key and optionally set or update its expiration. + +> 📘 **Redis Reference**: [GETEX](https://redis.io/docs/latest/commands/getex/) + +### XML Example + +```xml + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The key to get | +| `ex` | Long | No | — | Set expiry in seconds | +| `px` | Long | No | — | Set expiry in milliseconds | +| `exat` | Long | No | — | Set expiry as Unix timestamp in seconds | +| `pxat` | Long | No | — | Set expiry as Unix timestamp in milliseconds | +| `persist` | boolean | No | `false` | Remove the TTL | + +::: info Mutually Exclusive Parameters +Only one of `ex`, `px`, `exat`, `pxat`, or `persist` should be specified. The Redis server enforces this constraint. +::: + +### Output + +**Type**: `String` (media type: `text/plain`) + +The current value of the key. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:NIL` | Key does not exist | +| `REDIS:COMMAND` | General command execution error | + +--- + +## GETSET + +Set a key to a new value and return the old value. + +> 📘 **Redis Reference**: [GETSET](https://redis.io/docs/latest/commands/getset/) + +### XML Example + +```xml + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The key to set | +| `value` | String | Yes | — | The new value to store (payload by default via `@Content`) | + +### Output + +**Type**: `String` (media type: `text/plain`) + +The old value before the SET operation. Returns `null` if the key did not exist. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:WRONG_TYPE` | Key exists but holds a non-string value | +| `REDIS:COMMAND` | General command execution error | + +--- + +## COPY + +Copy a key to a new key, optionally to a different database. + +> 📘 **Redis Reference**: [COPY](https://redis.io/docs/latest/commands/copy/) + +### XML Example + +```xml + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `source` | String | Yes | — | Source key to copy from | +| `destination` | String | Yes | — | Destination key to copy to | +| `destinationDb` | Integer | No | — | Target database index (if copying to a different database) | +| `replace` | boolean | No | `false` | Overwrite destination if it already exists | + +### Output + +**Type**: `Boolean` + +- `true` if the key was copied +- `false` if the source key does not exist or destination exists and `replace=false` + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | + +--- + +## TOUCH + +Update the last access time of one or more keys without changing their values. + +> 📘 **Redis Reference**: [TOUCH](https://redis.io/docs/latest/commands/touch/) + +### XML Example + +```xml + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `keys` | List\ | Yes | — | One or more keys to touch | + +### Output + +**Type**: `Void` + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | No keys provided | +| `REDIS:COMMAND` | General command execution error | + +--- + +## SCAN + +Incrementally iterate the keyspace using a cursor. + +> 📘 **Redis Reference**: [SCAN](https://redis.io/docs/latest/commands/scan/) + +::: tip Automated Cursor Management +For most use cases, consider using [Search Keys](./search-operations#search-keys) instead, which handles cursor iteration automatically and streams all matching keys. Use SCAN directly only when you need fine-grained control over pagination. +::: + +### XML Example + +```xml + + + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `cursor` | Integer | Yes | — | Cursor position. Use `0` to start a new scan. | +| `match` | String | No | — | Glob-style pattern to filter keys (e.g., `user:*`, `product:*:cache`) | +| `count` | Integer | No | — | Hint for the number of elements to return. Redis may return more or fewer. | +| `type` | String | No | — | Filter by Redis type (`string`, `list`, `set`, `zset`, `hash`, `stream`) | + +### Output + +**Type**: `List` + +A list of keys matching the pattern for this scan iteration. + +**Attributes**: `ScanAttributes` — Contains the `cursor` field with the next cursor value. When `cursor` is `0`, the scan is complete. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | + +### Manual Cursor Iteration Pattern + +```xml + + + + + + + + + + + + + + + + + + + + + + + +``` diff --git a/docs/connectors/mule-lettuce-redis-connector/operations/list.md b/docs/connectors/mule-lettuce-redis-connector/operations/list.md new file mode 100644 index 0000000..6e89804 --- /dev/null +++ b/docs/connectors/mule-lettuce-redis-connector/operations/list.md @@ -0,0 +1,450 @@ +--- +title: List Commands — Lettuce Redis Connector +description: Reference for list Redis commands in the Mule Lettuce Redis Connector +--- + +# List Commands + +List commands operate on Redis lists — ordered collections of strings. Lists are doubly-linked, so adding elements to the head or tail is very fast. + +This page covers: **BLMOVE**, **BLPOP**, **BRPOP**, **LMOVE**, **LPOP**, **LPUSH**, **LSET**, **RPOP**, **RPUSH** + +--- + +## LPUSH + +Prepend one or more values to a list. + +> 📘 **Redis Reference**: [LPUSH](https://redis.io/docs/latest/commands/lpush/) + +### XML Example + +```xml + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The list key | +| `members` | List\ | Yes | — | Values to prepend. At least one required. Payload by default via `@Content`. | + +### Output + +**Type**: `Long` + +The length of the list after the operation. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | No members provided | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a list | + +--- + +## RPUSH + +Append one or more values to a list. + +> 📘 **Redis Reference**: [RPUSH](https://redis.io/docs/latest/commands/rpush/) + +### XML Example + +```xml + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The list key | +| `members` | List\ | Yes | — | Values to append. At least one required. Payload by default via `@Content`. | + +### Output + +**Type**: `Long` + +The length of the list after the operation. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | No members provided | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a list | + +--- + +## LPOP + +Remove and return the first element(s) from a list. + +> 📘 **Redis Reference**: [LPOP](https://redis.io/docs/latest/commands/lpop/) + +### XML Example + +```xml + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The list key | +| `count` | Integer | No | — | Number of elements to pop. When omitted, pops one element. | + +### Output + +**Type**: `List` + +The operation always returns a `List` regardless of whether `count` is provided: +- When `count` is **not** specified: list contains a single element (the popped element) +- When `count` **is** specified: list contains up to `count` popped elements + +::: warning Metadata Mismatch +Anypoint Studio's design-time metadata indicates this operation returns a `String` when `count` is not provided. At runtime, the operation always returns a `List`. When writing DataWeave expressions, treat the output as a list. This mismatch is tracked in [issue #4](https://github.com/MuleSoft-Forge/mule-lettuce-redis-connector/issues/4). +::: + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a list | + +--- + +## RPOP + +Remove and return the last element(s) from a list. + +> 📘 **Redis Reference**: [RPOP](https://redis.io/docs/latest/commands/rpop/) + +### XML Example + +```xml + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The list key | +| `count` | Integer | No | — | Number of elements to pop | + +### Output + +**Type**: `List` + +The operation always returns a `List` regardless of whether `count` is provided: +- When `count` is **not** specified: list contains a single element (the popped element) +- When `count` **is** specified: list contains up to `count` popped elements + +::: warning Metadata Mismatch +Anypoint Studio's design-time metadata indicates this operation returns a `String` when `count` is not provided. At runtime, the operation always returns a `List`. When writing DataWeave expressions, treat the output as a list. This mismatch is tracked in [issue #4](https://github.com/MuleSoft-Forge/mule-lettuce-redis-connector/issues/4). +::: + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a list | + +--- + +## BLPOP + +Remove and return the first element from one of multiple lists, blocking until an element is available or timeout occurs. + +> 📘 **Redis Reference**: [BLPOP](https://redis.io/docs/latest/commands/blpop/) + +### XML Example + +```xml + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `keys` | List\ | Yes | — | One or more list keys to wait on. At least one required. The first list to have an element available is popped. | +| `timeoutSeconds` | Double | Yes | — | Seconds to wait. Use `0` to block indefinitely. | + +### Output + +**Type**: `Map` + +A single-entry map where: +- **Key**: The list key that had an element +- **Value**: The popped element + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | No keys provided | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | One of the keys is not a list | +| `REDIS:TIMEOUT` | Timeout reached with no element available | + +--- + +## BRPOP + +Remove and return the last element from one of multiple lists, blocking until an element is available or timeout occurs. + +> 📘 **Redis Reference**: [BRPOP](https://redis.io/docs/latest/commands/brpop/) + +### XML Example + +```xml + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `keys` | List\ | Yes | — | One or more list keys. At least one required. | +| `timeoutSeconds` | Double | Yes | — | Seconds to wait. Use `0` to block indefinitely. | + +### Output + +**Type**: `Map` + +A single-entry map: the key that had an element and the popped value. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | No keys provided | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | One of the keys is not a list | +| `REDIS:TIMEOUT` | Timeout reached with no element available | + +--- + +## LMOVE + +Atomically move an element from one list to another. + +> 📘 **Redis Reference**: [LMOVE](https://redis.io/docs/latest/commands/lmove/) + +### XML Example + +```xml + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `source` | String | Yes | — | Source list key | +| `destination` | String | Yes | — | Destination list key | +| `whereFrom` | ListEnd | Yes | — | Which end to pop from the source list: `LEFT` or `RIGHT` | +| `whereTo` | ListEnd | Yes | — | Which end to push to the destination list: `LEFT` or `RIGHT` | + +**ListEnd values**: `LEFT`, `RIGHT` + +### Output + +**Type**: `String` (media type: `text/plain`) + +The element that was moved. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Source or destination is not a list | + +### Queue Transfer Pattern + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +--- + +## BLMOVE + +Atomically move an element from one list to another, blocking until an element is available or timeout occurs. + +> 📘 **Redis Reference**: [BLMOVE](https://redis.io/docs/latest/commands/blmove/) + +### XML Example + +```xml + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `source` | String | Yes | — | Source list key | +| `destination` | String | Yes | — | Destination list key | +| `whereFrom` | ListEnd | Yes | — | Which end to pop from: `LEFT` or `RIGHT` | +| `whereTo` | ListEnd | Yes | — | Which end to push to: `LEFT` or `RIGHT` | +| `timeout` | Double | Yes | — | Seconds to wait for an element. Use `0.0` to block indefinitely. | + +### Output + +**Type**: `String` (media type: `text/plain`) + +The element that was moved. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Source or destination is not a list | + +--- + +## LSET + +Set the value of an element in a list by its index. + +> 📘 **Redis Reference**: [LSET](https://redis.io/docs/latest/commands/lset/) + +### XML Example + +```xml + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The list key | +| `index` | Long | Yes | — | Index of the element to set (0-based). Negative indices count from the end (-1 is last element). | +| `element` | String | Yes | — | The new value (payload by default via `@Content`) | + +### Output + +**Type**: `Void` + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:OUT_OF_RANGE` | Index is out of range for the list | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a list | diff --git a/docs/connectors/mule-lettuce-redis-connector/operations/search-operations.md b/docs/connectors/mule-lettuce-redis-connector/operations/search-operations.md new file mode 100644 index 0000000..27e6da4 --- /dev/null +++ b/docs/connectors/mule-lettuce-redis-connector/operations/search-operations.md @@ -0,0 +1,350 @@ +--- +title: Search Operations — Lettuce Redis Connector +description: Automated SCAN-based iteration for keys, hash fields, set members, and sorted set members +--- + +# Search Operations + +## The Problem with Manual SCAN + +When you need to iterate over large keyspaces or collections in Redis, you can't just ask for "all keys" or "all set members" — that would lock the server for too long. Instead, Redis uses cursor-based iteration commands: SCAN, HSCAN, SSCAN, and ZSCAN. + +Here's what manual cursor iteration looks like: + +1. Call SCAN with cursor `0` +2. Process the returned keys +3. Read the new cursor value from the response +4. Call SCAN again with the new cursor +5. Repeat steps 2-4 until the cursor returns to `0` +6. Handle the edge case where a page returns 0 results but the cursor is not yet `0` + +In Mule XML, this requires flow-ref recursion, choice routers, and careful state management — verbose, error-prone, and cluttered with iteration logic instead of business logic. + +**Search Operations solve this problem.** They handle all the cursor management automatically and integrate natively with `` and batch processing. You just write a simple loop — the connector takes care of the rest. + +--- + +## How Search Operations Work + +Search Operations are implemented as Mule SDK `PagingProvider`s. This means: + +- They stream results in pages, making repeated SCAN calls under the hood +- The connector maintains cursor state automatically until the full result set is returned +- You use them with ``, batch jobs, or any component that consumes iterables +- You never see or manage the cursor — it's completely transparent + +Under the hood, the connector: +1. Starts a SCAN loop with cursor `0` +2. Calls the Redis SCAN command and retrieves a page of results +3. Passes that page to your flow +4. Stores the new cursor value internally +5. Repeats until cursor returns to `0`, indicating the scan is complete + +--- + +## The Four Search Operations + +### Search Keys + +**Automates:** [SCAN](./key-value#scan) + +**When to use:** Iterating over all keys in the database, optionally filtered by pattern or type. + +#### Example + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +#### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `match` | String | No | — | Glob-style pattern filter (e.g., `"user:*"`, `"cache:???"`). Only keys matching this pattern are returned. | +| `type` | String | No | — | Redis type filter: `"string"`, `"hash"`, `"list"`, `"set"`, `"zset"`, or `"stream"`. Only keys of this type are returned. | +| `pageSizeHint` | Integer | No | — | Hint to Redis for number of elements per SCAN call. Redis may return more or fewer elements. | + +#### Output + +**Type (per iteration):** `String` + +Each iteration of `` receives a single key name as a String. + +--- + +### Search Hash Fields + +**Automates:** [HSCAN](./hash#hscan) + +**When to use:** Iterating over all field-value pairs in a hash, optionally filtered by field name pattern. + +#### Example + +```xml + + + + + + + + + + + + + + { + name: key, + value: value +}]]> + + + + +``` + +#### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | Hash key to scan | +| `match` | String | No | — | Pattern filter on field names (e.g., `"email_*"`, `"theme_*"`) | +| `pageSizeHint` | Integer | No | — | Elements per HSCAN call hint | + +#### Output + +**Type (per iteration):** `Map` + +Each iteration receives a map of field-value pairs from one page of the HSCAN result. The map may contain multiple fields depending on how Redis batched the results. + +--- + +### Search Set Members + +**Automates:** [SSCAN](./set#sscan) + +**When to use:** Iterating over all members of a set, optionally filtered by pattern. + +#### Example + +```xml + + + + + + + + + + + + + + + +``` + +#### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | Set key to scan | +| `match` | String | No | — | Pattern filter on member values | +| `pageSizeHint` | Integer | No | — | Elements per SSCAN call hint | + +#### Output + +**Type (per iteration):** `String` + +Each iteration receives a single set member as a String. + +--- + +### Search Sorted Set Members + +**Automates:** [ZSCAN](./sorted-set#zscan) + +**When to use:** Iterating over all members and scores in a sorted set, optionally filtered by member name pattern. + +#### Example + +```xml + + + + + + + + + + + + + + + + page pluck (score, member) -> { + playerId: member, + score: score + } +}]]> + + + +``` + +#### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | Sorted set key to scan | +| `match` | String | No | — | Pattern filter on member names | +| `pageSizeHint` | Integer | No | — | Elements per ZSCAN call hint | + +#### Output + +**Type (per iteration):** `Map` + +Each iteration receives a map where keys are member names (Strings) and values are scores (Doubles). The map contains member-score pairs from one page of the ZSCAN result. + +--- + +## When to Use Search Operations vs Manual SCAN + +| Scenario | Use | +|----------|-----| +| Iterate over all matches and process them | **Search Operations** — automatic, clean, works with `` and batch | +| Stop early after finding N results | **Manual SCAN** — you control the loop and can break out | +| Need access to the raw cursor value | **Manual SCAN** — Search Operations hide the cursor | +| Need to resume a scan from a saved cursor | **Manual SCAN** — Search Operations always start from cursor `0` | +| Production iteration over large keyspaces | **Search Operations** — handles edge cases automatically | +| Filter results with complex logic during iteration | **Search Operations** — iterate with ``, filter with `` | + +--- + +## Important Notes + +### SCAN Is Not Atomic + +Redis SCAN commands are not snapshots — data can change during iteration. If keys are added or removed while you're scanning, they may or may not appear in your results. This is a Redis behavior, not a connector limitation. + +If you need a consistent view of data at a point in time, consider: +- Using Redis transactions (MULTI/EXEC) with smaller, known key sets +- Snapshoting data to a temporary key first, then scanning that +- Accepting eventual consistency and designing your logic to be idempotent + +### `pageSizeHint` Is a Hint, Not a Guarantee + +The `pageSizeHint` parameter maps to Redis's `COUNT` option. Redis uses it as a hint for how many elements to scan per iteration, but the actual number returned can be more or less depending on: +- The internal representation of the data structure +- Hash table density and resizing +- The `match` filter (filtered results may be smaller than the hint) + +The connector handles this transparently — you don't need to worry about variable page sizes. + +### Performance Tuning + +For very large keyspaces (millions of keys), SCAN can take many round trips to Redis. The `pageSizeHint` parameter helps you tune the tradeoff: + +- **Smaller hints** (e.g., `10-50`) → More round trips, lower memory usage per call, lower server load per call +- **Larger hints** (e.g., `500-1000`) → Fewer round trips, higher memory usage per call, higher server load per call + +Start with the default (Redis decides) and only tune if you see performance issues. + +--- + +## Example: Batch Processing with Search Operations + +Search Operations integrate seamlessly with Mule's batch processing: + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +--- + +## See Also + +- [SCAN](./key-value#scan) — Manual key scanning with cursor control +- [HSCAN](./hash#hscan) — Manual hash field scanning +- [SSCAN](./set#sscan) — Manual set member scanning +- [ZSCAN](./sorted-set#zscan) — Manual sorted set member scanning diff --git a/docs/connectors/mule-lettuce-redis-connector/operations/send-command.md b/docs/connectors/mule-lettuce-redis-connector/operations/send-command.md new file mode 100644 index 0000000..1eb725d --- /dev/null +++ b/docs/connectors/mule-lettuce-redis-connector/operations/send-command.md @@ -0,0 +1,217 @@ +--- +title: Send Command — Lettuce Redis Connector +description: Execute any Redis command dynamically when no dedicated operation exists +--- + +# Send Command + +## When to Use Send Command + +The Lettuce Redis Connector implements dedicated operations for the most commonly used Redis commands — SET, GET, LPUSH, ZADD, and dozens more. But Redis has hundreds of commands, and new ones are added in every server release. When you need a command that the connector doesn't have a dedicated operation for, **Send Command** is your escape hatch. + +Use Send Command when you need to: +- Execute a Redis command not yet implemented as a dedicated operation +- Use new commands added in recent Redis server versions +- Call commands from Redis modules (RedisJSON, RedisGraph, etc.) +- Work with custom or experimental commands + +**The tradeoff:** You lose type safety and design-time metadata. The connector can't validate your arguments at design time or automatically infer the return type — you're responsible for knowing the command's signature and specifying how to interpret the response. + +--- + +## How It Works + +Send Command uses Lettuce's low-level dispatch mechanism to send an arbitrary command string with arguments directly to the Redis server. You specify three things: + +1. **Command name** — the Redis command (e.g., `"LLEN"`, `"TYPE"`, `"RANDOMKEY"`) +2. **Arguments** — an ordered list of strings representing the command's arguments +3. **Return type** — what kind of response you expect from Redis (`STATUS`, `STRING`, `LONG`, or `ARRAY`) + +The connector sends the command, receives the response from Redis, and converts it to a Mule-friendly type based on the `returnType` you specified. + +--- + +## The `returnType` Parameter — Understanding Your Options + +The `returnType` parameter is the most important part of using Send Command. It tells the connector how to interpret Redis's response. Choose the wrong type and you'll get a runtime error. + +| Return Type | Redis Response Type | Mule Output Type | Use When | +|-------------|---------------------|-------------------|----------| +| `STATUS` | Simple status string (e.g., `"OK"`, `"QUEUED"`) | `String` | Commands that return a status message: SET (without GET option), PING, SELECT, FLUSHDB | +| `STRING` | Bulk string | `String` | Commands that return a string value: GET, HGET, LINDEX, TYPE | +| `LONG` | Integer | `Long` | Commands that return a number: INCR, DECR, DBSIZE, LLEN, SCARD | +| `ARRAY` | Array | `List` | Commands that return multiple values: KEYS, MGET, LRANGE, SMEMBERS | + +::: tip How to Pick the Right Return Type +Check the [Redis command documentation](https://redis.io/commands) for the command you're using. Every command page lists its return type — map that to one of the four `returnType` values above. +::: + +::: warning NIL Responses +If the command returns nil (e.g., GET on a nonexistent key) and you specified `returnType=STRING` or `returnType=ARRAY`, the connector throws a `REDIS:NIL` error. Use an error handler to catch this if nil is a valid outcome for your use case. +::: + +--- + +## Example: Using a Command Not in the Connector + +Let's say you need to check the length of a Redis list using the `LLEN` command. The connector doesn't have a dedicated LLEN operation, so you use Send Command: + +```xml + + + + + + + + + + + +``` + +**What's happening here:** +- **`command="LLEN"`** — we're calling the Redis LLEN command +- **`arguments="#[['pending-tasks']]"`** — LLEN takes one argument: the list key +- **`returnType="LONG"`** — LLEN returns an integer (the list length) + +After the operation, `payload` contains the number of items in the list as a `Long`. + +--- + +## Example: Getting a Key's Type + +Redis's `TYPE` command returns the data type of a key (`string`, `hash`, `list`, etc.). Since it returns a string status, use `returnType=STRING`: + +```xml + + + + + + + + + + + + + + + + + + +``` + +--- + +## Example: Combining with DataWeave + +When using `returnType=ARRAY`, the result is a `List`. You can transform it with DataWeave just like any other list: + +```xml + + + + + + + + + + + +``` + +--- + +## Error Handling + +Send Command can throw several error types depending on what goes wrong: + +| Error Type | When It's Thrown | How to Handle | +|------------|------------------|---------------| +| `REDIS:NIL` | Redis returned nil and `returnType` is `STRING` or `ARRAY` | Use an error handler to provide a default value or alternate logic | +| `REDIS:WRONG_TYPE` | The key holds a different data type than the command expects | Check the key type first or catch and handle gracefully | +| `REDIS:COMMAND` | Redis rejected the command (wrong arguments, unknown command, etc.) | Verify command syntax and argument count | +| `REDIS:TIMEOUT` | Redis server did not respond in time | Retry or alert on infrastructure issues | + +### Example: Handling NIL Gracefully + +```xml + + + + + + + + + + + + + + +``` + +--- + +## Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `command` | String | Yes | — | Redis command name (e.g., `"LLEN"`, `"TYPE"`, `"RANDOMKEY"`) | +| `arguments` | List\ | Yes | — | Command arguments in order. Use an empty list `#[[]]` for commands with no arguments. | +| `returnType` | CommandReturnType | Yes | — | Expected return type: `STATUS`, `STRING`, `LONG`, or `ARRAY` | + +### Output + +**Type**: `Object` (resolved dynamically based on `returnType`) + +- `STATUS` → `String` +- `STRING` → `String` +- `LONG` → `Long` +- `ARRAY` → `List` + +--- + +## Tips + +- **Check the Redis docs for return type:** If you're unsure which `returnType` to use, check the official [Redis command reference](https://redis.io/commands) — every command page lists the return type +- **Arguments are always strings:** Even if a command takes a number (like `LRANGE key 0 10`), pass the arguments as strings: `#[['mylist', '0', '10']]` +- **Keys go in the arguments list:** Unlike dedicated operations, Send Command doesn't have a separate `key` parameter — the key is just the first (or second, or third) argument depending on the command +- **Use dedicated operations when available:** Send Command is powerful but less convenient than dedicated operations. If a command has a dedicated operation (like SET, GET, ZADD), prefer that — you get better metadata, validation, and autocomplete + +--- + +## See Also + +- [Key-Value Operations](./key-value) — Dedicated operations for common commands like SET, GET, MGET +- [List Operations](./list) — LPUSH, RPOP, LMOVE, and other list commands +- [Hash Operations](./hash) — HSET, HGET, HINCRBY, and more diff --git a/docs/connectors/mule-lettuce-redis-connector/operations/server.md b/docs/connectors/mule-lettuce-redis-connector/operations/server.md new file mode 100644 index 0000000..d3a92c8 --- /dev/null +++ b/docs/connectors/mule-lettuce-redis-connector/operations/server.md @@ -0,0 +1,77 @@ +--- +title: Server Commands — Lettuce Redis Connector +description: Reference for server Redis commands in the Mule Lettuce Redis Connector +--- + +# Server Commands + +Server commands are used to check the health and responsiveness of the Redis server. + +This page covers: **PING** + +--- + +## PING + +Test connectivity to the Redis server and optionally echo a custom message. + +> 📘 **Redis Reference**: [PING](https://redis.io/docs/latest/commands/ping/) + +### XML Example + +```xml + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `message` | String | No | — | If provided, Redis echoes this message back instead of "PONG" | + +### Output + +**Type**: `String` (media type: `text/plain`) + +- When no `message` parameter is provided: returns `"PONG"` +- When a `message` is provided: returns the message string + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | Connection failure or server error | + +### Usage + +PING is commonly used for: +- Health checks in monitoring flows +- Verifying connectivity before executing operations +- Validating configuration changes + +```xml + + + + + + + + + + + + + + + + + + +``` diff --git a/docs/connectors/mule-lettuce-redis-connector/operations/set.md b/docs/connectors/mule-lettuce-redis-connector/operations/set.md new file mode 100644 index 0000000..0f7e468 --- /dev/null +++ b/docs/connectors/mule-lettuce-redis-connector/operations/set.md @@ -0,0 +1,455 @@ +--- +title: Set Commands — Lettuce Redis Connector +description: Reference for set Redis commands in the Mule Lettuce Redis Connector +--- + +# Set Commands + +Set commands operate on Redis sets — unordered collections of unique strings. Sets are useful for membership testing, removing duplicates, and set algebra operations. + +This page covers: **SADD**, **SCARD**, **SDIFF**, **SISMEMBER**, **SMEMBERS**, **SMISMEMBER**, **SPOP**, **SRANDMEMBER**, **SREM**, **SSCAN** + +--- + +## SADD + +Add one or more members to a set. + +> 📘 **Redis Reference**: [SADD](https://redis.io/docs/latest/commands/sadd/) + +### XML Example + +```xml + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The set key | +| `members` | List\ | Yes | — | Members to add. Payload by default via `@Content`. | + +### Output + +**Type**: `Long` + +The number of members **actually added** to the set. Members that were already in the set are not counted. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a set | + +--- + +## SREM + +Remove one or more members from a set. + +> 📘 **Redis Reference**: [SREM](https://redis.io/docs/latest/commands/srem/) + +### XML Example + +```xml + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The set key | +| `members` | List\ | Yes | — | Members to remove. Payload by default via `@Content`. | + +### Output + +**Type**: `Long` + +The number of members removed from the set. Members that were not in the set are not counted. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a set | + +--- + +## SMEMBERS + +Get all members of a set. + +> 📘 **Redis Reference**: [SMEMBERS](https://redis.io/docs/latest/commands/smembers/) + +### XML Example + +```xml + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The set key | + +### Output + +**Type**: `List` + +All members of the set. Returns an empty list if the set does not exist. + +::: warning Large Sets +For sets with many members, consider using [Search Set Members](./search-operations#search-set-members) which streams results incrementally via SSCAN. +::: + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a set | + +--- + +## SISMEMBER + +Check if a value is a member of a set. + +> 📘 **Redis Reference**: [SISMEMBER](https://redis.io/docs/latest/commands/sismember/) + +### XML Example + +```xml + + + + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The set key | +| `member` | String | Yes | — | The member to test | + +### Output + +**Type**: `Boolean` + +- `true` if the member is in the set +- `false` if the member is not in the set or the set does not exist + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a set | + +--- + +## SMISMEMBER + +Check if multiple values are members of a set. + +> 📘 **Redis Reference**: [SMISMEMBER](https://redis.io/docs/latest/commands/smismember/) + +### XML Example + +```xml + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The set key | +| `members` | List\ | Yes | — | Members to test. Payload by default via `@Content`. | + +### Output + +**Type**: `List` + +A list of boolean values, one for each input member, in the same order. Each value is: +- `true` if the corresponding member is in the set +- `false` if the corresponding member is not in the set + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a set | + +--- + +## SCARD + +Get the number of members in a set (cardinality). + +> 📘 **Redis Reference**: [SCARD](https://redis.io/docs/latest/commands/scard/) + +### XML Example + +```xml + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The set key | + +### Output + +**Type**: `Long` + +The number of members in the set. Returns `0` if the set does not exist. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a set | + +--- + +## SDIFF + +Compute the difference between the first set and all subsequent sets. + +> 📘 **Redis Reference**: [SDIFF](https://redis.io/docs/latest/commands/sdiff/) + +### XML Example + +```xml + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The first set (base set) | +| `keys` | List\ | Yes | — | Additional sets to subtract from the first set | + +### Output + +**Type**: `List` + +Members that are in the first set but not in any of the other sets. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | One of the keys is not a set | + +--- + +## SPOP + +Remove and return one or more random members from a set. + +> 📘 **Redis Reference**: [SPOP](https://redis.io/docs/latest/commands/spop/) + +### XML Example + +```xml + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The set key | +| `count` | Integer | No | — | Number of members to pop. When omitted, pops one member. | + +### Output + +**Type**: `Object` (dynamic, resolved by metadata) + +- When `count` is **not** specified: `String` (the single popped member) +- When `count` **is** specified: `List` (the popped members) + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a set | + +--- + +## SRANDMEMBER + +Get one or more random members from a set without removing them. + +> 📘 **Redis Reference**: [SRANDMEMBER](https://redis.io/docs/latest/commands/srandmember/) + +### XML Example + +```xml + + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The set key | +| `count` | Integer | No | — | Number of members to return. **Positive** = unique results; **Negative** = duplicates allowed. | + +### Output + +**Type**: `List` + +Random members from the set. If `count` is not specified, returns a single-element list. + +::: info Count Sign Matters +- **Positive `count`**: Returns up to `count` **unique** members (no duplicates) +- **Negative `count`**: Returns exactly `abs(count)` members, **duplicates allowed** +::: + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a set | + +--- + +## SSCAN + +Incrementally iterate set members using a cursor. + +> 📘 **Redis Reference**: [SSCAN](https://redis.io/docs/latest/commands/sscan/) + +::: tip Automated Cursor Management +For most use cases, consider using [Search Set Members](./search-operations#search-set-members) instead, which handles cursor iteration automatically and streams all members. Use SSCAN directly only when you need fine-grained control over pagination. +::: + +### XML Example + +```xml + + + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The set key to scan | +| `cursor` | Integer | Yes | — | Cursor position. Use `0` to start a new scan. | +| `match` | String | No | — | Glob-style pattern to filter members | +| `count` | Integer | No | — | Hint for the number of elements to return per iteration | + +### Output + +**Type**: `List` + +A list of members matching the pattern for this scan iteration. + +**Attributes**: `ScanAttributes` — Contains the `cursor` field with the next cursor value. When `cursor` is `0`, the scan is complete. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a set | diff --git a/docs/connectors/mule-lettuce-redis-connector/operations/sorted-set.md b/docs/connectors/mule-lettuce-redis-connector/operations/sorted-set.md new file mode 100644 index 0000000..a63c6f9 --- /dev/null +++ b/docs/connectors/mule-lettuce-redis-connector/operations/sorted-set.md @@ -0,0 +1,269 @@ +--- +title: Sorted Set Commands — Lettuce Redis Connector +description: Reference for sorted set Redis commands in the Mule Lettuce Redis Connector +--- + +# Sorted Set Commands + +Sorted set commands operate on Redis sorted sets — collections of unique strings, each associated with a score. Members are ordered by score, making sorted sets useful for leaderboards, priority queues, and range queries. + +This page covers: **ZADD**, **ZINCRBY**, **ZRANK**, **ZSCAN**, **ZSCORE** + +--- + +## ZADD + +Add one or more members with scores to a sorted set, with optional conditional flags. + +> 📘 **Redis Reference**: [ZADD](https://redis.io/docs/latest/commands/zadd/) + +### XML Example + +```xml + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The sorted set key | +| `memberScores` | Map\ | Yes | — | Member-to-score pairs. Payload by default via `@Content`. | +| `xx` | boolean | No | `false` | Only update existing members (do not add new) | +| `nx` | boolean | No | `false` | Only add new members (do not update existing) | +| `gt` | boolean | No | `false` | Only update if the new score is **greater than** the current score | +| `lt` | boolean | No | `false` | Only update if the new score is **less than** the current score | +| `ch` | boolean | No | `false` | Change the return value to count **changed** members instead of **added** members | + +### Output + +**Type**: `Long` + +- By default: the number of **new** members added (updates to existing members are not counted) +- When `ch=true`: the number of members **added or changed** + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a sorted set | + +--- + +## ZSCORE + +Get the score of a member in a sorted set. + +> 📘 **Redis Reference**: [ZSCORE](https://redis.io/docs/latest/commands/zscore/) + +### XML Example + +```xml + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The sorted set key | +| `member` | String | Yes | — | The member whose score to retrieve | + +### Output + +**Type**: `Double` + +The score of the member. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a sorted set | + +--- + +## ZRANK + +Get the rank (index) of a member in a sorted set, optionally with its score. + +> 📘 **Redis Reference**: [ZRANK](https://redis.io/docs/latest/commands/zrank/) + +### XML Example + +```xml + + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The sorted set key | +| `member` | String | Yes | — | The member to get the rank of | +| `withScore` | boolean | No | `false` | If `true`, return both rank and score together | + +### Output + +**Type**: `Object` (dynamic, resolved by metadata) + +- When `withScore=false`: `Long` — The rank (0-based index in sorted order) +- When `withScore=true`: `Map` with keys: + - `"rank"` → Long + - `"score"` → Double + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:NIL` | Member does not exist in the sorted set | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a sorted set | + +--- + +## ZINCRBY + +Increment the score of a member in a sorted set. + +> 📘 **Redis Reference**: [ZINCRBY](https://redis.io/docs/latest/commands/zincrby/) + +### XML Example + +```xml + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The sorted set key | +| `increment` | Double | Yes | — | The amount to add to the member's score (can be negative) | +| `member` | String | Yes | — | The member whose score to increment | + +### Output + +**Type**: `Double` + +The new score of the member after the increment. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a sorted set | + +--- + +## ZSCAN + +Incrementally iterate sorted set members and scores using a cursor. + +> 📘 **Redis Reference**: [ZSCAN](https://redis.io/docs/latest/commands/zscan/) + +::: tip Automated Cursor Management +For most use cases, consider using [Search Sorted Set Members](./search-operations#search-sorted-set-members) instead, which handles cursor iteration automatically and streams all member-score pairs. Use ZSCAN directly only when you need fine-grained control over pagination. +::: + +### XML Example + +```xml + + + + + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The sorted set key to scan | +| `cursor` | Integer | Yes | — | Cursor position. Use `0` to start a new scan. | +| `match` | String | No | — | Glob-style pattern to filter member names | +| `count` | Integer | No | — | Hint for the number of elements to return per iteration | + +### Output + +**Type**: `List>` + +A list where each element is a single-entry map representing one member-score pair: +```json +[ + {"player:123": 1500.0}, + {"player:456": 1200.0}, + {"player:789": 1800.0} +] +``` + +**Attributes**: `ScanAttributes` — Contains the `cursor` field with the next cursor value. When `cursor` is `0`, the scan is complete. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a sorted set | diff --git a/docs/connectors/mule-lettuce-redis-connector/operations/stream.md b/docs/connectors/mule-lettuce-redis-connector/operations/stream.md new file mode 100644 index 0000000..73f3248 --- /dev/null +++ b/docs/connectors/mule-lettuce-redis-connector/operations/stream.md @@ -0,0 +1,630 @@ +--- +title: Stream Commands — Lettuce Redis Connector +description: Reference for stream Redis commands in the Mule Lettuce Redis Connector +--- + +# Stream Commands + +Stream commands operate on Redis streams — append-only log data structures designed for messaging and event sourcing. Streams support consumer groups for distributed processing, making them ideal for building scalable message queues and event-driven architectures. + +This page covers: **XACK**, **XADD**, **XDEL**, **XGROUP CREATE**, **XGROUP DESTROY**, **XINFO GROUPS**, **XRANGE**, **XREAD**, **XREADGROUP**, **XTRIM** + +--- + +## XADD + +Append a new entry to a stream, optionally with automatic eviction to cap stream size. + +> 📘 **Redis Reference**: [XADD](https://redis.io/docs/latest/commands/xadd/) + +### XML Example + +```xml + + + + + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The stream key | +| `noMkStream` | boolean | No | `false` | If `true`, do not create the stream if it doesn't exist | +| `id` | String | No | `"*"` | Entry ID. Use `"*"` for auto-generation (recommended). | +| `evictionOption` | StreamEvictionOption | No | — | Eviction policy to cap stream size (MaxLenEvictionOption or MinIdEvictionOption) | +| `entry` | Map\ | Yes | — | Field-value pairs for the entry. At least one required. Payload by default via `@Content`. | + +**StreamEvictionOption** (choose one): + +| Type | Fields | +|------|--------| +| `MaxLenEvictionOption` | `maxLength` (long), `exactTrimming` (boolean, default `true`), `limit` (Integer, optional) | +| `MinIdEvictionOption` | `id` (String), `exactTrimming` (boolean, default `true`), `limit` (Integer, optional) | + +**Eviction notes**: +- `exactTrimming=false` allows approximate trimming for better performance +- `limit` caps the number of entries deleted in a single trim operation + +### Output + +**Type**: `String` (media type: `text/plain`) + +The ID of the newly added entry (e.g., `"1609459200000-0"`). + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | Entry map is empty, or invalid ID | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a stream | + +--- + +## XRANGE + +Retrieve a range of entries from a stream. + +> 📘 **Redis Reference**: [XRANGE](https://redis.io/docs/latest/commands/xrange/) + +### XML Example + +```xml + + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The stream key | +| `start` | String | Yes | — | Range start ID. Use `"-"` for the beginning of the stream. | +| `end` | String | Yes | — | Range end ID. Use `"+"` for the end of the stream. | +| `count` | Integer | No | — | Maximum number of entries to return | + +### Output + +**Type**: `Map>` + +A map where: +- **Key**: Entry ID (e.g., `"1609459200000-0"`) +- **Value**: Map of field-value pairs for that entry + +Example: +```json +{ + "1609459200000-0": {"orderId": "12345", "status": "created"}, + "1609459200001-0": {"orderId": "12346", "status": "created"} +} +``` + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | Invalid start or end ID | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key exists but is not a stream | + +--- + +## XREAD + +Read entries from one or more streams, optionally blocking until new entries arrive. + +> 📘 **Redis Reference**: [XREAD](https://redis.io/docs/latest/commands/xread/) + +### XML Example + +```xml + + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `count` | Integer | No | — | Maximum entries per stream | +| `block` | Integer | No | — | Milliseconds to block waiting for new entries. Omit for non-blocking. | +| `streamWatermarks` | List\ | Yes | — | Stream keys and last-read IDs. At least one required. Use `"0"` to read from the beginning, `"$"` to read only new entries. | + +**StreamWatermark structure**: +```dataweave +{ + key: "stream-key", // String + id: "$" // String (entry ID or special value) +} +``` + +**Special ID values**: +- `"0"` — Read from the beginning of the stream +- `"$"` — Read only entries added **after** this call + +### Output + +**Type**: `Map>` + +A map where: +- **Key**: Stream key +- **Value**: List of StreamEntry objects + +**StreamEntry structure**: +```dataweave +{ + id: "1609459200000-0", // String + entry: {orderId: "12345", ...} // Map +} +``` + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | No stream watermarks provided | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | One of the keys is not a stream | + +--- + +## XREADGROUP + +Read entries from one or more streams as part of a consumer group. + +> 📘 **Redis Reference**: [XREADGROUP](https://redis.io/docs/latest/commands/xreadgroup/) + +### XML Example + +```xml + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `group` | String | Yes | — | Consumer group name | +| `consumer` | String | Yes | — | Consumer name within the group | +| `count` | Long | No | — | Maximum entries per stream | +| `block` | Long | No | — | Milliseconds to block waiting for new entries | +| `noack` | boolean | No | `false` | If `true`, do not track acknowledgment (auto-acknowledge) | +| `streamWatermarks` | List\ | Yes | — | Stream keys and IDs. At least one required. Use `">"` to read undelivered entries. | + +**Special ID value for consumer groups**: +- `">"` — Read only entries **not yet delivered** to any consumer in the group + +### Output + +**Type**: `Map>` + +Same structure as XREAD. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | No stream watermarks provided, or group/consumer invalid | +| `REDIS:COMMAND` | General command execution error (e.g., group does not exist) | +| `REDIS:WRONG_TYPE` | One of the keys is not a stream | + +### Consumer Group Processing Pattern + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +--- + +## XACK + +Acknowledge one or more entries as processed by a consumer group. + +> 📘 **Redis Reference**: [XACK](https://redis.io/docs/latest/commands/xack/) + +### XML Example + +```xml + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The stream key | +| `group` | String | Yes | — | Consumer group name | +| `ids` | List\ | Yes | — | Entry IDs to acknowledge. At least one required. | + +### Output + +**Type**: `Long` + +The number of entries successfully acknowledged. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | No IDs provided | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key is not a stream | + +--- + +## XDEL + +Delete one or more entries from a stream. + +> 📘 **Redis Reference**: [XDEL](https://redis.io/docs/latest/commands/xdel/) + +### XML Example + +```xml + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The stream key | +| `ids` | List\ | Yes | — | Entry IDs to delete. At least one required. | + +### Output + +**Type**: `Long` + +The number of entries deleted. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:ARGUMENT` | No IDs provided | +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key is not a stream | + +--- + +## XTRIM + +Trim a stream to a specified length or minimum ID. + +> 📘 **Redis Reference**: [XTRIM](https://redis.io/docs/latest/commands/xtrim/) + +::: warning Static Configuration Required +The `evictionOption` parameter is `@Expression(NOT_SUPPORTED)` — it **must** be configured statically in XML. DataWeave expressions cannot be used for this parameter. +::: + +### XML Example + +```xml + + + + + + + + + + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The stream key | +| `evictionOption` | StreamEvictionOption | Yes | — | Eviction policy (MaxLenEvictionOption or MinIdEvictionOption). Must be static XML. | + +**StreamEvictionOption** (same as XADD): + +| Type | Fields | +|------|--------| +| `MaxLenEvictionOption` | `maxLength` (long), `exactTrimming` (boolean), `limit` (Integer, optional) | +| `MinIdEvictionOption` | `id` (String), `exactTrimming` (boolean), `limit` (Integer, optional) | + +### Output + +**Type**: `Long` + +The number of entries deleted. + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key is not a stream | + +--- + +## XGROUP CREATE + +Create a new consumer group for a stream. + +> 📘 **Redis Reference**: [XGROUP CREATE](https://redis.io/docs/latest/commands/xgroup-create/) + +### XML Example + +```xml + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The stream key | +| `group` | String | Yes | — | Consumer group name to create | +| `lastEntryId` | String | No | `"$"` | ID of the last entry the group has seen. Use `"$"` to start from the current end, `"0"` to process all existing entries. | +| `mkstream` | boolean | Yes | — | If `true`, create the stream if it does not exist | +| `entriesRead` | Long | No | — | Number of entries already read (for accurate lag tracking) | + +### Output + +**Type**: `Void` + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error (e.g., group already exists) | +| `REDIS:WRONG_TYPE` | Key exists but is not a stream | + +--- + +## XGROUP DESTROY + +Destroy a consumer group. + +> 📘 **Redis Reference**: [XGROUP DESTROY](https://redis.io/docs/latest/commands/xgroup-destroy/) + +### XML Example + +```xml + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The stream key | +| `group` | String | Yes | — | Consumer group name to destroy | + +### Output + +**Type**: `Boolean` + +- `true` if the group was destroyed +- `false` if the group did not exist + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key is not a stream | + +--- + +## XINFO GROUPS + +Get information about all consumer groups for a stream. + +> 📘 **Redis Reference**: [XINFO GROUPS](https://redis.io/docs/latest/commands/xinfo-groups/) + +### XML Example + +```xml + + + + + + +``` + +### Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `key` | String | Yes | — | The stream key | + +### Output + +**Type**: `List>` + +A list of maps, one for each consumer group. Each map contains: + +| Field | Type | Description | +|-------|------|-------------| +| `name` | String | Consumer group name | +| `consumers` | Long | Number of consumers in the group | +| `pending` | Long | Number of entries pending acknowledgment | +| `last-delivered-id` | String | ID of the last entry delivered to a consumer | +| `entries-read` | Long | Number of entries read by the group | +| `lag` | Long | Number of entries in the stream not yet delivered | + +### Errors + +| Error Type | Condition | +|------------|-----------| +| `REDIS:COMMAND` | General command execution error | +| `REDIS:WRONG_TYPE` | Key is not a stream | diff --git a/docs/connectors/mule-lettuce-redis-connector/set-up.md b/docs/connectors/mule-lettuce-redis-connector/set-up.md new file mode 100644 index 0000000..908e0a9 --- /dev/null +++ b/docs/connectors/mule-lettuce-redis-connector/set-up.md @@ -0,0 +1,206 @@ +--- +title: Set Up +description: Installation and configuration guide for the Mule Lettuce Redis Connector. +--- + +# Set Up + +| Version | Min runtime version | Compatible Java versions | Description | +| ------- | ------------------- | ------------------------ | ----------- | +| [0.1.24](https://central.sonatype.com/artifact/cloud.anypoint/mule-lettuce-redis-connector/0.1.24) | 4.6.0 | Java 8, Java 11, Java 17 | Latest release | + +## Requirements + +- **Mule Runtime**: 4.6.0 or later +- **Java**: 8, 11, or 17 +- **Maven**: 3.9.8 or later +- **Redis server**: Any version supporting the commands you use + +## Installation + +### Step 1: Add Maven Dependency + +Add the following dependency to your Mule application's `pom.xml`: + +```xml + + cloud.anypoint + mule-lettuce-redis-connector + 0.1.24 + mule-plugin + +``` + +### Step 2: Choose Your Configuration Type + +The connector provides two configuration elements. Use the one that matches your use case: + +| Configuration | XML element | Use for | +|--------------|-------------|---------| +| Standard | `lettuce-redis:config` | All operations (GET, SET, HSET, LPUSH, XADD, PUBLISH, Send Command, Search Operations, etc.) | +| Pub/Sub | `lettuce-redis:pubsub-config` | Sources only (SUBSCRIBE and PSUBSCRIBE event listeners) | + +## Standard Configuration + +Use `lettuce-redis:config` for all regular operations. This covers every command in the Key/Value, Hash, List, Set, Sorted Set, Geospatial, Stream, and Channel categories, as well as Send Command and Search Operations. + +```xml + + + +``` + +### Connection Parameters + +| Parameter | Type | Required | Default | Description | +|-----------|------|----------|---------|-------------| +| `host` | String | Yes | — | Redis server hostname or IP address | +| `tls` | boolean | Yes | — | Enable TLS/SSL encryption for the connection | +| `port` | int | Yes | — | Redis server port (Redis default is 6379) | +| `password` | String | Yes | — | Redis AUTH password. See note below about credential management. | +| `commandTimeout` | Integer | No | — | Fixed timeout for all commands. Used together with `commandTimeoutUnit`. | +| `commandTimeoutUnit` | TimeUnit | No | — | Time unit for `commandTimeout` (e.g., `MILLISECONDS`, `SECONDS`). Required when `commandTimeout` is set. | + +::: warning Password Is Required and Does Not Support DataWeave Expressions +The `password` parameter currently accepts only a literal string or a Mule property placeholder. DataWeave expressions are not supported. Use Mule's secure configuration properties to keep credentials out of your flow XML. +::: + +### Credential Management + +Always store the Redis password in a secure properties file rather than hardcoding it in your flow XML: + +**`src/main/resources/secure-config.yaml`** (encrypted, add to `.gitignore`): +```yaml +redis: + password: "your-redis-password" +``` + +**Global configuration** (or `src/main/mule/global.xml`): +```xml + + + + + + + +``` + +### Command Timeout Configuration + +To configure a fixed command timeout, provide both `commandTimeout` and `commandTimeoutUnit`: + +```xml + + + +``` + +Valid `commandTimeoutUnit` values: `NANOSECONDS`, `MICROSECONDS`, `MILLISECONDS`, `SECONDS`, `MINUTES`, `HOURS`, `DAYS`. + +### TLS Configuration + +To connect to a Redis server with TLS enabled, set `tls="true"`: + +```xml + + + +``` + +--- + +## Pub/Sub Configuration + +Use `lettuce-redis:pubsub-config` **only** for the SUBSCRIBE and PSUBSCRIBE sources (event listeners). This is a separate configuration element from the standard one. + +```xml + + + +``` + +::: tip Why a Separate Configuration? +Redis Pub/Sub requires a different underlying connection type than regular commands. In the Lettuce client, these are `StatefulRedisConnection` (standard) and `StatefulRedisPubSubConnection` (pub/sub) — they are not interchangeable. The connector uses separate config elements to make this distinction explicit and prevent misconfiguration. +::: + +**Connection parameters are identical** to the standard configuration — same host, port, tls, password, and timeout options. + +### PUBLISH vs SUBSCRIBE + +| Operation | Configuration to use | +|-----------|---------------------| +| `PUBLISH` (sending messages) | `lettuce-redis:config` (standard) | +| `SUBSCRIBE` source (receiving messages) | `lettuce-redis:pubsub-config` | +| `PSUBSCRIBE` source (pattern listening) | `lettuce-redis:pubsub-config` | + +--- + +## Using Both Configurations in the Same Application + +Applications that both publish and subscribe to Redis channels need both configurations: + +```xml + + + + + + + + + + + + + + + + + + +``` + +## Next Steps + +- [Operations Reference](./operations/) — All available operations by category +- [Sources (Listeners)](./sources) — Setting up Pub/Sub event-driven flows +- [GitHub Repository](https://github.com/anypointcloud/mule-lettuce-redis-connector) — Source code and issues diff --git a/docs/connectors/mule-lettuce-redis-connector/sources.md b/docs/connectors/mule-lettuce-redis-connector/sources.md new file mode 100644 index 0000000..21bde13 --- /dev/null +++ b/docs/connectors/mule-lettuce-redis-connector/sources.md @@ -0,0 +1,242 @@ +--- +title: Sources (Listeners) +description: Real-time Redis Pub/Sub event listeners for Mule flows using SUBSCRIBE and PSUBSCRIBE. +--- + +# Sources (Listeners) + +## What Are Sources? + +In the Mule SDK, a *source* is an event listener — a component that sits at the beginning of a flow and triggers it when something happens externally. Unlike operations (which your flow calls), sources wait and react. + +Redis Pub/Sub lets applications publish messages to channels and receive them in real time. The connector exposes two sources: + +| Source | Redis Command | Use when | +|--------|--------------|----------| +| SUBSCRIBE | SUBSCRIBE | You know the exact channel names to listen on | +| PSUBSCRIBE | PSUBSCRIBE | You want to match channels by glob pattern (e.g., `user:*:events`) | + +Each message published to a subscribed channel or matching pattern triggers one Mule event through the connected flow. + +::: tip Pub/Sub Is Fire-and-Forget +If no subscriber is listening when a message is published, the message is lost. Redis Pub/Sub is not a message queue — it does not persist messages. For durable messaging, consider Redis Streams (XADD/XREADGROUP) instead. +::: + +## Prerequisites + +Sources require the **Pub/Sub configuration** (`lettuce-redis:pubsub-config`), not the standard configuration. See [Set Up](./set-up#pub-sub-configuration) for how to create it and why it must be separate. + +```xml + + + +``` + +--- + +## SUBSCRIBE + +### What It Does + +SUBSCRIBE listens on one or more **exact** channel names. Every message published to any of those channels triggers one Mule event with the message as the payload. + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `channels` | List\ | Yes | One or more exact channel names to subscribe to | + +### Output + +| Field | Type | Description | +|-------|------|-------------| +| `payload` | String | The message content | +| `attributes.channel` | String | The channel the message was received on | + +### Example + +```xml + + + + + + + + + + +``` + +### Subscribing to Multiple Channels + +A single SUBSCRIBE source can listen on multiple channels at once: + +```xml + +``` + +Use `attributes.channel` in a `` router to handle each channel differently: + +```xml + + + + + + + + + + + + + + + +``` + +--- + +## PSUBSCRIBE + +### What It Does + +PSUBSCRIBE subscribes to channels by **glob pattern** rather than exact name. Any channel whose name matches the pattern will deliver messages to the flow. + +Use PSUBSCRIBE when you need to listen on a family of related channels whose names are not known at design time, or when you want to avoid maintaining a large list of exact channel names. + +### Parameters + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `patterns` | List\ | Yes | One or more glob patterns. Channels matching any pattern trigger the flow. | + +### Output + +| Field | Type | Description | +|-------|------|-------------| +| `payload` | String | The message content | +| `attributes.channel` | String | The actual channel name the message was received on (not the pattern) | + +### Pattern Matching Examples + +| Pattern | Matches | Does Not Match | +|---------|---------|----------------| +| `user:*` | `user:123`, `user:abc` | `order:123`, `users:123` | +| `user:*:events` | `user:123:events`, `user:abc:events` | `user:events`, `user:123:logs` | +| `*:updated` | `order:updated`, `product:updated` | `order:update`, `updated` | +| `[io]*` | `orders`, `inventory` | `pricing`, `users` | +| `h?llo` | `hello`, `hallo` | `heello`, `hllo` | + +::: tip Pattern Syntax +Redis pattern matching supports `*` (any sequence of characters), `?` (any single character), and `[...]` (character classes), same as shell globbing. +::: + +### Example + +```xml + + + + + + + + + + + + +``` + +### PSUBSCRIBE vs SUBSCRIBE + +| | SUBSCRIBE | PSUBSCRIBE | +|--|-----------|------------| +| Channel matching | Exact name | Glob pattern | +| `attributes.channel` | The subscribed channel | The actual channel that matched | +| Best for | Known, fixed channel names | Dynamic or family-of-channels scenarios | +| Multiple channels? | Yes — list multiple names | Yes — list multiple patterns | + +--- + +## Common Patterns + +### Publish and Subscribe in the Same Application + +PUBLISH uses the **standard** config; SUBSCRIBE/PSUBSCRIBE use the **pub/sub** config. Both can coexist in the same application: + +```xml + + + + + + + + + + + + + + + + + + + + + + + +``` + +--- + +## Important Notes + +- **Each source instance maintains its own dedicated Redis connection.** A Pub/Sub connection cannot be shared with regular operations — this is why the separate `lettuce-redis:pubsub-config` is required. +- **Messages are fire-and-forget.** If the subscriber's flow is not running when a message is published, that message is lost. +- **PUBLISH returns the subscriber count.** The output of the PUBLISH operation is a `Long` indicating how many subscribers received the message. A return value of `0` means no one was listening. +- **Pattern subscription delivers the actual channel name**, not the pattern, in `attributes.channel`. If you subscribed with `user:*:events` and a message arrived on `user:42:events`, `attributes.channel` is `"user:42:events"`. + +## See Also + +- [Set Up — Pub/Sub Configuration](./set-up#pub-sub-configuration) +- [Channel Operations — PUBLISH](./operations/channel#publish)