npm package: @glorhythm/redis
Description: Glorhythm Redis client library for Node.js
Author: glorhythm
Latest version: 1.0.0-beta.6

# 🧩 @glorhythm/redis

**Glorhythm Redis client library for Node.js**, built on top of [**ioredis**](https://github.com/luin/ioredis) — providing a **type-safe**, **multi-connection**, and **config-driven** Redis interface integrated with [`@glorhythm/config-loader`](https://www.npmjs.com/package/@glorhythm/config-loader).

---

## 📦 Package Info

| Property           | Value                                      |
| ------------------ | ------------------------------------------ |
| **Name**           | `@glorhythm/redis`                         |
| **Version**        | `1.0.0-beta`                               |
| **Author**         | `glorhythm`                                |
| **License**        | MIT                                        |
| **Description**    | Glorhythm Redis client library for Node.js |
| **Peer Dependeny** | `@glorhythm/config-loader` `ioredis`       |

---

## 🚀 Overview

This package provides a **centralized Redis manager** for Node.js services in the **Glorhythm ecosystem**.  
It uses configuration from `@glorhythm/config-loader` to automatically initialize one or more Redis instances and exposes a simple, typed API to retrieve connections.

### ✅ Key Features

- 🔌 Multiple named Redis connections (`default`, `cache`, `pubsub`, etc.)
- 💤 Lazy connect & auto-reconnect via `ioredis`
- ♻️ Built-in retry strategy and offline queue
- 🧠 Type-safe config paths via `DotPath` and `PathValue`
- 🛑 Graceful shutdown with listener cleanup
- ⚙️ Integration with `@glorhythm/config-loader`

---

## 📥 Installation

```bash
npm install @glorhythm/redis @glorhythm/config-loader ioredis
```

or with Yarn:

```bash
yarn add @glorhythm/redis @glorhythm/config-loader@ ioredis
```

---

## 🧱 Folder Structure

Expected project layout:

```
<project>/
│── src/
|   ├── configs/
|   │   └── redis.ts
|   └── index.ts
├── .env
├── package.json
```

---

## ⚙️ Configuration Example

### `configs/redis.ts`

```ts
import type { RedisConfig } from "@glorhythm/redis";

const redis: RedisConfig = {
  default: {
    host: process.env.REDIS_HOST ?? "127.0.0.1",
    port: Number(process.env.REDIS_PORT ?? 6379),
    db: 0,
  },
  cache: {
    host: process.env.REDIS_CACHE_HOST ?? "127.0.0.1",
    port: Number(process.env.REDIS_CACHE_PORT ?? 6379),
    db: 1,
  },
  pubsub: {
    host: process.env.REDIS_PUBSUB_HOST ?? "127.0.0.1",
    port: Number(process.env.REDIS_PUBSUB_PORT ?? 6379),
    db: 2,
  },
};

export default redis;
```

### `.env`

```env
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
NODE_ENV=development
```

---

## ⚡ Quick Start

```ts
// src/index.ts
import Redis from "@glorhythm/redis";
import { ConfigLoader } from "@glorhythm/config-loader";

(async () => {
  // 1️⃣ Initialize config loader
  ConfigLoader.load();

  // 2️⃣ Get Redis connections
  const redis = Redis.connection(); // default connection
  const cache = Redis.connection("cache"); // named connection

  // 3️⃣ Use Redis normally
  await redis.set("hello", "world");
  console.log(await redis.get("hello"));

  // 4️⃣ Graceful shutdown
  await Redis.shutdown();
})();
```

---

## 🧩 API Reference

### `Redis.connection(key?: string): IORedis`

Returns a Redis client for the specified key.

- **key** — (optional) connection name from your config (defaults to `"default"`)
- **Returns** — `IORedis` instance (from [`ioredis`](https://github.com/luin/ioredis))

Example:

```ts
const main = Redis.connection();
const pubsub = Redis.connection("pubsub");

await main.set("ping", "pong");
await pubsub.publish("events", "update");
```

---

### `Redis.shutdown(): Promise<void>`

Gracefully closes all active Redis connections and removes event listeners.

```ts
process.on("SIGTERM", async () => {
  await Redis.shutdown();
  process.exit(0);
});
```

---

## ⚙️ Internals

- Automatically initializes all connections from `Config('redis')`
- Uses `lazyConnect: true` and retry strategy:
  ```ts
  retryStrategy: (times) => Math.min(times * 100, 5000);
  ```
- Cleans up all listeners on shutdown for memory safety
- Tracks instances in a `Map<RedisKeys, IORedis>`

---

## 🧪 Example Use Cases

### 🔁 Cache Layer

```ts
const cache = Redis.connection("cache");
await cache.set("session:123", JSON.stringify({ userId: 42 }), "EX", 3600);
```

### 📣 Pub/Sub

```ts
const pub = Redis.connection("pubsub");
const sub = Redis.connection("pubsub");

await sub.subscribe("notifications");
sub.on("message", (channel, msg) => {
  console.log(`[${channel}] ${msg}`);
});

await pub.publish("notifications", "New trade executed!");
```

### 🧰 Graceful Service Exit

```ts
process.on("SIGINT", async () => {
  await Redis.shutdown();
  console.log("Redis closed cleanly.");
  process.exit(0);
});
```

---

## 🧹 Error Handling

| Error                                              | Reason                                                   | Fix                                       |
| -------------------------------------------------- | -------------------------------------------------------- | ----------------------------------------- |
| `Redis config must include a "default" connection` | Missing `"default"` key in `configs/redis.ts`            | Add `default` connection                  |
| `Redis connection "xyz" not found`                 | Invalid or missing connection name                       | Ensure key exists in config               |
| `ConfigLoader not initialized`                     | Forgot to call `ConfigLoader.load()` before using Redis  | Add `ConfigLoader.load()` at app startup  |
| `.env file not found`                              | Loader can’t locate `.env` one level above executed file | Ensure `.env` is at `<project_root>/.env` |

---

## 🧾 License

MIT © [Glorhythm](https://github.com/glorhythm)

---

**Glorhythm Redis — the typed, unified Redis layer for your Node.js ecosystem.**