# API Usage

## 🔌 Overview

If you need more power or are familiar with the Redis Java API and want to use features beyond the standard cache interface, the bx-redis module provides direct access to the underlying Redis connections and providers. Behind the scenes, the module leverages the [Jedis library](https://github.com/redis/jedis) for Redis connectivity.

This page documents the low-level API functions available for advanced Redis operations.

## 🛠️ Available Functions

The module provides several global BoxLang functions to access the underlying Redis infrastructure:

| Function                   | Purpose                                       | Returns                  |
| -------------------------- | --------------------------------------------- | ------------------------ |
| `redisGetProvider()`       | Get the cache provider implementation         | `IRedisCache` interface  |
| `redisGetConnectionPool()` | Get the Jedis connection pool (non-clustered) | `JedisPool`              |
| `redisGetCluster()`        | Get the Redis cluster connection              | `JedisCluster`           |
| `redisGetClusterNodes()`   | Get map of cluster node connections           | `Map<String, JedisPool>` |

## 📋 Function Reference

### redisGetProvider()

Returns the BoxLang Redis cache provider implementation. This gives you access to the `IRedisCache` interface, which extends BoxLang's standard `ICacheProvider` with Redis-specific functionality.

**Syntax:**

```js
provider = redisGetProvider( [ cacheName ] )
```

**Parameters:**

| Parameter   | Type   | Required | Default     | Description                            |
| ----------- | ------ | -------- | ----------- | -------------------------------------- |
| `cacheName` | string | No       | `"default"` | The name of the configured Redis cache |

**Returns:** `ortus.boxlang.modules.redis.cache.IRedisCache`

**Throws:** `InvalidCacheType` if the specified cache is not a Redis cache

**Example:**

```js
// Get the provider for the default cache
provider = redisGetProvider();

// Get the provider for a named cache
sessionProvider = redisGetProvider( "sessions" );

// Access Redis-specific methods
keys = provider.getKeys();
stats = provider.getStats();
```

**Use Cases:**

* Accessing Redis-specific cache operations
* Getting cache statistics and metadata
* Performing bulk operations
* Direct cache provider manipulation

### redisGetConnectionPool()

Returns the Jedis connection pool for non-clustered Redis caches. This provides direct access to the `redis.clients.jedis.JedisPool` for low-level Redis operations.

**Syntax:**

```js
pool = redisGetConnectionPool( [ cacheName ] )
```

**Parameters:**

| Parameter   | Type   | Required | Default     | Description                                                    |
| ----------- | ------ | -------- | ----------- | -------------------------------------------------------------- |
| `cacheName` | string | No       | `"default"` | The name of the configured Redis cache (must be non-clustered) |

**Returns:** `redis.clients.jedis.JedisPool`

**Throws:**

* `InvalidCacheType` if the cache is not a Redis cache
* Exception if called on a clustered cache

**Example:**

```js
// Get connection pool
pool = redisGetConnectionPool( "sessions" );

// Get a connection from the pool
try {
    var jedis = pool.getResource();

    // Perform Redis operations
    jedis.set( "mykey", "myvalue" );
    var value = jedis.get( "mykey" );

    // Connection is auto-closed via try-with-resources
} finally {
    if( !isNull( jedis ) ) {
        jedis.close();
    }
}
```

**Use Cases:**

* Direct Jedis API access
* Redis commands not exposed through cache interface
* Performance-critical operations requiring connection pooling
* Custom Redis operations

{% hint style="warning" %}
**Important:** Always return connections to the pool using `jedis.close()` or use try-with-resources patterns to prevent connection leaks.
{% endhint %}

### redisGetCluster()

Returns the Redis cluster connection for clustered deployments. Provides access to `redis.clients.jedis.JedisCluster` for cluster-specific operations.

**Syntax:**

```js
cluster = redisGetCluster( [ cacheName ] )
```

**Parameters:**

| Parameter   | Type   | Required | Default     | Description                                                |
| ----------- | ------ | -------- | ----------- | ---------------------------------------------------------- |
| `cacheName` | string | No       | `"default"` | The name of the configured Redis cache (must be clustered) |

**Returns:** `redis.clients.jedis.JedisCluster`

**Throws:**

* `InvalidCacheType` if the cache is not a Redis cache
* Exception if called on a non-clustered cache

**Example:**

```js
// Get cluster connection
cluster = redisGetCluster( "distributedCache" );

// Perform cluster operations
cluster.set( "user:123", serializeJSON( userData ) );
var user = cluster.get( "user:123" );

// Get cluster info
var clusterInfo = cluster.clusterNodes();
var clusterSlots = cluster.clusterSlots();
```

**Use Cases:**

* Cluster-specific Redis commands
* Cluster topology inspection
* Slot management
* Multi-key operations across cluster

### redisGetClusterNodes()

Returns a map of all cluster node connections. Each entry provides a `JedisPool` for a specific cluster node.

**Syntax:**

```js
nodes = redisGetClusterNodes( [ cacheName ] )
```

**Parameters:**

| Parameter   | Type   | Required | Default     | Description                                                |
| ----------- | ------ | -------- | ----------- | ---------------------------------------------------------- |
| `cacheName` | string | No       | `"default"` | The name of the configured Redis cache (must be clustered) |

**Returns:** `Map<String, redis.clients.jedis.JedisPool>`

**Throws:**

* `InvalidCacheType` if the cache is not a Redis cache
* Exception if called on a non-clustered cache

**Example:**

```js
// Get all cluster nodes
nodes = redisGetClusterNodes( "distributedCache" );

// Iterate through nodes
for( var nodeKey in nodes ) {
    var nodePool = nodes[ nodeKey ];

    try {
        var jedis = nodePool.getResource();
        var info = jedis.info();
        writeOutput( "Node: #nodeKey# - #info#<br>" );
    } finally {
        if( !isNull( jedis ) ) {
            jedis.close();
        }
    }
}
```

**Use Cases:**

* Node-specific operations
* Health checking individual nodes
* Gathering per-node statistics
* Debugging cluster issues

## 💡 Advanced Usage Examples

### Custom Redis Command Execution

```js
// Execute raw Redis commands
pool = redisGetConnectionPool( "default" );

try {
    var jedis = pool.getResource();

    // Use Redis commands not in standard cache API
    jedis.lpush( "queue:tasks", "task1" );
    jedis.lpush( "queue:tasks", "task2" );

    var task = jedis.rpop( "queue:tasks" );

    // Set expiration in milliseconds
    jedis.pexpire( "temp:data", 5000 );

} finally {
    if( !isNull( jedis ) ) {
        jedis.close();
    }
}
```

### Pipeline Operations

```js
// Batch multiple commands for better performance
pool = redisGetConnectionPool( "default" );

try {
    var jedis = pool.getResource();
    var pipeline = jedis.pipelined();

    // Queue multiple operations
    for( var i = 1; i <= 100; i++ ) {
        pipeline.set( "key:#i#", "value:#i#" );
    }

    // Execute all at once
    pipeline.sync();

} finally {
    if( !isNull( jedis ) ) {
        jedis.close();
    }
}
```

### Transaction Support

```js
// Execute atomic transactions
pool = redisGetConnectionPool( "default" );

try {
    var jedis = pool.getResource();

    // Start transaction
    var transaction = jedis.multi();

    transaction.set( "account:123:balance", "1000" );
    transaction.set( "account:456:balance", "2000" );
    transaction.incr( "total:accounts" );

    // Execute transaction
    var results = transaction.exec();

} finally {
    if( !isNull( jedis ) ) {
        jedis.close();
    }
}
```

### Cluster Slot Information

```js
// Get cluster slot mappings
cluster = redisGetCluster( "distributedCache" );

// Get slot assignments
var slots = cluster.clusterSlots();

// Find which node handles a specific key
var keySlot = jedis.clusterKeySlot( "mykey" );
```

### Monitoring and Statistics

```js
// Gather Redis statistics
provider = redisGetProvider( "default" );

// Get cache statistics
var stats = provider.getStats();
writeOutput( "Hits: #stats.hits#<br>" );
writeOutput( "Misses: #stats.misses#<br>" );
writeOutput( "Size: #stats.size#<br>" );

// Get all keys (use with caution in production)
var allKeys = provider.getKeys();
```

## ⚠️ Best Practices

### Connection Management

* **Always close Jedis resources** - Use try/finally blocks or BoxLang's try-with-resources
* **Don't hold connections** - Get, use, and return connections quickly
* **Pool size configuration** - Configure appropriate connection pool sizes in your cache settings

```js
// GOOD: Proper connection handling
try {
    var jedis = pool.getResource();
    jedis.set( "key", "value" );
} finally {
    if( !isNull( jedis ) ) {
        jedis.close();
    }
}

// BAD: Connection leak
var jedis = pool.getResource();
jedis.set( "key", "value" );
// Connection never returned!
```

### Error Handling

* **Catch Redis-specific exceptions** - Handle `JedisException` and connection errors
* **Implement retry logic** - For transient network failures
* **Validate cache type** - Check cache is Redis before calling these functions

```js
try {
    var provider = redisGetProvider( "myCache" );
    // Use provider
} catch( InvalidCacheType e ) {
    writeLog( "Cache is not a Redis cache: #e.message#" );
}
```

### Performance Considerations

* **Use pipelining** - For bulk operations to reduce round trips
* **Avoid KEYS command** - Use SCAN in production environments
* **Connection pooling** - Reuse connections via the pool
* **Cluster awareness** - Use cluster-aware operations for distributed caches

### Security

* **Protect credentials** - Use environment variables for Redis passwords
* **Limit command access** - Use Redis ACLs if available
* **Network security** - Use SSL/TLS for production deployments
* **Connection validation** - Enable pool validation to detect stale connections

## 🔍 Debugging

### Enable Debug Logging

```js
// Log connection pool statistics
pool = redisGetConnectionPool( "default" );
writeOutput( "Active: #pool.getNumActive()#<br>" );
writeOutput( "Idle: #pool.getNumIdle()#<br>" );
writeOutput( "Waiting: #pool.getNumWaiters()#<br>" );
```

### Test Connectivity

```js
// Test Redis connection
try {
    var jedis = pool.getResource();
    var response = jedis.ping();
    writeOutput( "Redis responded: #response#" );
} catch( any e ) {
    writeOutput( "Connection failed: #e.message#" );
} finally {
    if( !isNull( jedis ) ) {
        jedis.close();
    }
}
```

### Monitor Commands

```js
// Enable Redis command monitoring (development only)
try {
    var jedis = pool.getResource();

    // MONITOR command streams all Redis commands
    // WARNING: Very high performance impact
    var monitor = jedis.monitor( function( command ) {
        writeLog( "Redis: #command#" );
    } );

} finally {
    if( !isNull( jedis ) ) {
        jedis.close();
    }
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://boxlang.ortusbooks.com/boxlang-+-++/modules/bx-redis/api-usage.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
