Skip to content

String Operations

The DBX TypeScript SDK provides comprehensive string operations with full TypeScript support and high-performance NAPI bindings.

Installation

npm install @0dbx/redis

Basic Usage

import { DbxRedisClient } from "@0dbx/redis";
 
// Create client
const client = new DbxRedisClient("http://localhost:3000");
 
// String operations
await client.string.set("my-key", "hello world", 3600); // with TTL
const value = await client.string.get("my-key");
console.log(value); // "hello world"

WebSocket Client

import { DbxWsClient } from "@0dbx/redis";
 
// Create WebSocket client
const wsClient = new DbxWsClient("ws://localhost:3000/redis_ws");
 
// String operations via WebSocket
await wsClient.string.set("my-key", "hello world");
const value = await wsClient.string.get("my-key");

String Operations

The DBX TypeScript SDK provides comprehensive string operations for Redis. This guide covers all available string methods and their usage patterns.

Overview

String operations are the most basic data type in Redis, supporting simple key-value storage with additional features like expiration and existence checks.

Basic Operations

Creating a String Client

import { DbxRedisClient } from "@0dbx/redis";
 
const client = new DbxRedisClient("http://localhost:3000");
const stringClient = client.string;

Setting Values

// Set a simple string value
await stringClient.set("my-key", "hello world");
 
// Set with TTL (Time To Live) in seconds
await stringClient.set("my-key", "hello world", 3600); // expires in 1 hour
 
// Set with 0 TTL (no expiration)
await stringClient.set("my-key", "hello world", 0);

Getting Values

// Get a string value
const value = await stringClient.get("my-key");
console.log(value); // "hello world"
 
// Get a non-existent key
try {
  const value = await stringClient.get("non-existent-key");
} catch (error) {
  console.log("Key not found");
}

Deleting Values

// Delete a key
await stringClient.delete("my-key");
 
// Check if deletion was successful
try {
  const value = await stringClient.get("my-key");
} catch (error) {
  console.log("Key was successfully deleted");
}

Advanced Operations

Checking Existence

// Check if a key exists
const exists = await stringClient.exists("my-key");
console.log(exists); // true or false

TTL Operations

// Get remaining TTL for a key
const ttl = await stringClient.ttl("my-key");
console.log(ttl); // seconds remaining, -1 if no TTL, -2 if key doesn't exist
 
// Set TTL for an existing key
await stringClient.expire("my-key", 7200); // 2 hours
 
// Remove TTL (make key persistent)
await stringClient.expire("my-key", -1);

Batch Operations

// Perform multiple string operations in a single request
const results = await stringClient.batch([
  { type: "set", key: "key1", value: "value1", ttl: 3600 },
  { type: "set", key: "key2", value: "value2" },
  { type: "get", key: "key3" },
  { type: "delete", key: "key4" },
]);
 
console.log(results);
// [
//   { success: true, key: "key1" },
//   { success: true, key: "key2" },
//   { value: "value3" },
//   { success: true, deleted: true }
// ]

WebSocket String Operations

Creating a WebSocket String Client

import { DbxWsClient } from "@0dbx/redis";
 
const wsClient = new DbxWsClient("ws://localhost:3000/redis_ws");
const wsStringClient = wsClient.string;

WebSocket String Operations

// Set value via WebSocket
await wsStringClient.set("my-key", "hello world");
 
// Get value via WebSocket
const value = await wsStringClient.get("my-key");
 
// Delete value via WebSocket
await wsStringClient.delete("my-key");
 
// Check existence via WebSocket
const exists = await wsStringClient.exists("my-key");
 
// TTL operations via WebSocket
const ttl = await wsStringClient.ttl("my-key");
await wsStringClient.expire("my-key", 3600);

Error Handling

Common Error Patterns

try {
  const value = await stringClient.get("non-existent-key");
} catch (error) {
  if (error.message.includes("not found")) {
    console.log("Key doesn't exist");
  } else if (error.message.includes("timeout")) {
    console.log("Request timed out");
  } else {
    console.error("Unexpected error:", error);
  }
}

Type-Safe Error Handling

interface StringOperationError {
  message: string;
  code?: string;
  status?: number;
}
 
async function safeStringOperation<T>(operation: () => Promise<T>): Promise<T | null> {
  try {
    return await operation();
  } catch (error) {
    const dbxError = error as StringOperationError;
 
    switch (dbxError.code) {
      case "not_found":
        console.warn("Key not found");
        return null;
      case "timeout":
        console.error("Operation timed out");
        return null;
      default:
        console.error("String operation failed:", dbxError.message);
        return null;
    }
  }
}
 
// Usage
const value = await safeStringOperation(() => stringClient.get("my-key"));

Performance Optimization

Connection Reuse

// Create a singleton client for your application
class StringService {
  private static instance: DbxRedisClient;
  private static stringClient: any;
 
  static getInstance(): any {
    if (!StringService.instance) {
      StringService.instance = new DbxRedisClient("http://localhost:3000");
      StringService.stringClient = StringService.instance.string;
    }
    return StringService.stringClient;
  }
}
 
// Use throughout your application
const stringClient = StringService.getInstance();

Batch Operations for Performance

// Instead of multiple individual requests
const promises = [
  stringClient.set("key1", "value1"),
  stringClient.set("key2", "value2"),
  stringClient.set("key3", "value3"),
];
await Promise.all(promises);
 
// Use batch operations for better performance
await stringClient.batch([
  { type: "set", key: "key1", value: "value1" },
  { type: "set", key: "key2", value: "value2" },
  { type: "set", key: "key3", value: "value3" },
]);

Caching Patterns

class CachedStringClient {
  private cache = new Map<string, { value: string; expires: number }>();
  private client: any;
 
  constructor(client: any) {
    this.client = client;
  }
 
  async get(key: string, ttl: number = 300): Promise<string | null> {
    const cached = this.cache.get(key);
 
    if (cached && cached.expires > Date.now()) {
      return cached.value;
    }
 
    try {
      const value = await this.client.get(key);
      this.cache.set(key, {
        value,
        expires: Date.now() + ttl * 1000,
      });
      return value;
    } catch (error) {
      return null;
    }
  }
 
  async set(key: string, value: string, ttl: number = 3600): Promise<void> {
    await this.client.set(key, value, ttl);
    this.cache.set(key, {
      value,
      expires: Date.now() + ttl * 1000,
    });
  }
}
 
// Usage
const cachedClient = new CachedStringClient(stringClient);
await cachedClient.set("my-key", "hello world", 3600);
const value = await cachedClient.get("my-key", 300); // 5-minute cache

Real-World Examples

User Session Management

class SessionManager {
  private client: any;
  private prefix = "session:";
 
  constructor(client: any) {
    this.client = client;
  }
 
  async createSession(userId: string, sessionData: any): Promise<string> {
    const sessionId = this.generateSessionId();
    const key = `${this.prefix}${sessionId}`;
 
    await this.client.set(key, JSON.stringify(sessionData), 86400); // 24 hours
    return sessionId;
  }
 
  async getSession(sessionId: string): Promise<any | null> {
    const key = `${this.prefix}${sessionId}`;
 
    try {
      const data = await this.client.get(key);
      return JSON.parse(data);
    } catch (error) {
      return null;
    }
  }
 
  async extendSession(sessionId: string): Promise<void> {
    const key = `${this.prefix}${sessionId}`;
    await this.client.expire(key, 86400); // Extend to 24 hours
  }
 
  async deleteSession(sessionId: string): Promise<void> {
    const key = `${this.prefix}${sessionId}`;
    await this.client.delete(key);
  }
 
  private generateSessionId(): string {
    return Math.random().toString(36).substring(2) + Date.now().toString(36);
  }
}
 
// Usage
const sessionManager = new SessionManager(stringClient);
const sessionId = await sessionManager.createSession("user123", {
  userId: "user123",
  loginTime: new Date().toISOString(),
  permissions: ["read", "write"],
});
 
const session = await sessionManager.getSession(sessionId);

Configuration Management

class ConfigManager {
  private client: any;
  private prefix = "config:";
 
  constructor(client: any) {
    this.client = client;
  }
 
  async setConfig(key: string, value: any): Promise<void> {
    const configKey = `${this.prefix}${key}`;
    await this.client.set(configKey, JSON.stringify(value));
  }
 
  async getConfig<T>(key: string, defaultValue?: T): Promise<T | null> {
    const configKey = `${this.prefix}${key}`;
 
    try {
      const data = await this.client.get(configKey);
      return JSON.parse(data);
    } catch (error) {
      return defaultValue || null;
    }
  }
 
  async deleteConfig(key: string): Promise<void> {
    const configKey = `${this.prefix}${key}`;
    await this.client.delete(configKey);
  }
}
 
// Usage
const configManager = new ConfigManager(stringClient);
 
await configManager.setConfig("app.settings", {
  theme: "dark",
  language: "en",
  notifications: true,
});
 
const settings = await configManager.getConfig("app.settings");

API Reference

Methods

MethodDescriptionParametersReturns
set(key, value, ttl?)Set a string valuekey: string, value: string, ttl?: numberPromise<void>
get(key)Get a string valuekey: stringPromise<string>
delete(key)Delete a keykey: stringPromise<void>
exists(key)Check if key existskey: stringPromise<boolean>
ttl(key)Get remaining TTLkey: stringPromise<number>
expire(key, ttl)Set TTL for keykey: string, ttl: numberPromise<void>
batch(operations)Batch operationsoperations: Array<BatchOperation>Promise<Array<any>>

Batch Operation Types

interface BatchOperation {
  type: "set" | "get" | "delete" | "exists" | "ttl" | "expire";
  key: string;
  value?: string;
  ttl?: number;
}

Next Steps

TypeScript Configuration

For optimal TypeScript support, ensure your tsconfig.json includes:

{
  "compilerOptions": {
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  }
}

Best Practices

  1. Type Safety: Always use TypeScript for better development experience
  2. Error Handling: Implement proper error handling for all operations
  3. Connection Management: Reuse client instances when possible
  4. Batch Operations: Use MSET/MGET for multiple operations
  5. Expiration: Set appropriate TTL values for temporary data
  6. Key Naming: Use consistent key naming conventions

Performance Tips

  • Use batch operations (MSET/MGET) instead of individual calls
  • Implement connection pooling for high-throughput applications
  • Consider using WebSocket client for real-time applications
  • Cache frequently accessed values in your application layer
  • Use appropriate data types (strings for text, numbers for counters)