memorydatabase

package
v0.0.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 2, 2025 License: GPL-3.0 Imports: 7 Imported by: 3

README

MemoryDatabase

This service manages interactions with memory databases. Currently supports Redis as the primary memory database implementation.

Overview

The MemoryDatabase service provides a high-level abstraction for memory database operations. It uses a Client interface pattern, allowing you to easily swap implementations and test your code with mocks. The service currently supports Redis through the RedisClient implementation.

Features

  • High-level interface for key-value operations
  • TTL support for automatic expiration of stored values

Usage

MemoryDatabase requires a Client interface for being used. This library offers Redis as a Client implementation.

Client Interface
type Client interface {
    WriteString(context.Context, string, string, int) error
    ReadString(context.Context, string) (string, bool, error)
    IsClientInitiated() bool
}
Basic Example
package main

import (
    "context"
    "log"
    "os"

    "github.com/a-castellano/go-services/memorydatabase"
    redisconfig "github.com/a-castellano/go-types/redis"
)

func main() {
    // Create Redis configuration from environment variables
    config, err := redisconfig.NewConfig()
    if err != nil {
        log.Fatal(err)
    }

    // Create Redis client
    redisClient := memorydatabase.NewRedisClient(config)

    // Initialize the client (establishes connection and validates it)
    ctx := context.Background()
    if err := redisClient.Initiate(ctx); err != nil {
        log.Fatal(err)
    }

    // Create MemoryDatabase instance with the Redis client
    memoryDatabase := memorydatabase.NewMemoryDatabase(&redisClient)

    // Write a value with TTL (time-to-live in seconds)
    err = memoryDatabase.WriteString(ctx, "user:123", "John Doe", 3600) // 1 hour TTL
    if err != nil {
        log.Fatal(err)
    }

    // Read the value
    value, found, err := memoryDatabase.ReadString(ctx, "user:123")
    if err != nil {
        log.Fatal(err)
    }

    if found {
        log.Printf("User: %s", value)
    } else {
        log.Println("User not found")
    }
}

API Reference

MemoryDatabase
NewMemoryDatabase(client Client) MemoryDatabase

Creates a new MemoryDatabase instance with the provided client.

WriteString(ctx context.Context, key string, value string, ttl int) error

Writes a string value to the memory database with the specified TTL (time-to-live in seconds).

Parameters:

  • ctx: Context for the operation
  • key: The key to store the value under
  • value: The string value to store
  • ttl: Time-to-live in seconds (0 for no expiration)

Returns: Error if the operation fails

ReadString(ctx context.Context, key string) (string, bool, error)

Reads a string value from the memory database by key.

Parameters:

  • ctx: Context for the operation
  • key: The key to read

Returns:

  • string: The value (empty if not found)
  • bool: True if the key was found
  • error: Error if the operation fails
RedisClient
NewRedisClient(redisConfig *redisconfig.Config) RedisClient

Creates a new RedisClient instance with the provided configuration.

Initiate(ctx context.Context) error

Establishes a connection to the Redis server and validates it with a ping.

Parameters:

  • ctx: Context for the operation

Returns: Error if connection fails

IsClientInitiated() bool

Returns true if the Redis client has been successfully initialized.

WriteString(ctx context.Context, key string, value string, ttl int) error

Stores a string value in Redis with the specified TTL.

ReadString(ctx context.Context, key string) (string, bool, error)

Retrieves a string value from Redis by key.

Configuration

The Redis client uses configuration from the go-types library. Environment variables are used to configure the connection:

  • REDIS_HOST: Redis server hostname or IP address
  • REDIS_PORT: Redis server port (default: 6379)
  • REDIS_PASSWORD: Redis server password (optional)
  • REDIS_DATABASE: Redis database number (default: 0)
Example Configuration
export REDIS_HOST=localhost
export REDIS_PORT=6379
export REDIS_PASSWORD=mysecret
export REDIS_DATABASE=0

Testing

The service includes comprehensive unit and integration tests. Unit tests use mocked Redis clients, while integration tests require a real Redis server.

Running Tests
# Run unit tests only
make test_memorydatabase_unit

# Run integration tests (requires Redis server)
make test_memorydatabase

# Run all tests
make test
Integration Testing

For integration tests, you need a Redis server running. You can use the provided Docker Compose setup:

docker-compose -f development/docker-compose.yml up -d valkey

Important Note: The integration tests use hardcoded IP addresses (172.17.0.2) to ensure consistent behavior across different environments. The Docker Compose configuration uses the same IP range (172.17.0.0/16) to avoid network conflicts and ensure tests run reliably.

Then run the integration tests:

REDIS_HOST=localhost REDIS_PORT=6379 make test_integration

Error Handling

The service provides detailed error messages for different failure scenarios:

  • Connection failures: Network issues, invalid host/port
  • Authentication failures: Invalid password
  • Operation failures: Redis server errors
  • Initialization failures: Client not properly initialized
Common Error Scenarios
// Client not initialized
if !redisClient.IsClientInitiated() {
    return errors.New("client is not initiated, cannot perform operation")
}

// Connection failure
if err := redisClient.Initiate(ctx); err != nil {
    return fmt.Errorf("failed to connect to Redis: %w", err)
}

// Key not found (not an error, but handled specially)
if err == goredis.Nil {
    return "", false, nil // Key doesn't exist
}

Dependencies

Documentation

Overview

Package memorydatabase provides a service for managing interactions with memory databases. Currently supports Redis as the primary memory database implementation.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Client

type Client interface {
	// WriteString stores a string value with the given key and TTL (time-to-live) in seconds.
	// Returns an error if the operation fails.
	WriteString(context.Context, string, string, int) error

	// ReadString retrieves a string value by key.
	// Returns the value, a boolean indicating if the key was found, and any error.
	ReadString(context.Context, string) (string, bool, error)

	// IsClientInitiated returns true if the client has been successfully initialized.
	IsClientInitiated() bool
}

Client interface defines the contract for memory database operations. Implementations must provide methods for reading and writing string values, as well as checking if the client has been properly initialized.

type MemoryDatabase

type MemoryDatabase struct {
	// contains filtered or unexported fields
}

MemoryDatabase provides a high-level interface for memory database operations. It uses a Client implementation to perform actual database operations.

func NewMemoryDatabase added in v0.0.3

func NewMemoryDatabase(client Client) MemoryDatabase

NewMemoryDatabase creates a new MemoryDatabase instance with the provided client. The client must implement the Client interface.

func (*MemoryDatabase) ReadString

func (memorydatabase *MemoryDatabase) ReadString(ctx context.Context, key string) (string, bool, error)

ReadString reads a string value from the memory database using the underlying client. This is a wrapper method that checks if the client is initialized before performing the operation. Returns the value, a boolean indicating if the key was found, and any error. Returns an error if the client is not initialized.

func (*MemoryDatabase) WriteString

func (memorydatabase *MemoryDatabase) WriteString(ctx context.Context, key string, value string, ttl int) error

WriteString writes a string value to the memory database using the underlying client. This is a wrapper method that checks if the client is initialized before performing the operation. Returns an error if the client is not initialized or if the write operation fails.

type RedisClient

type RedisClient struct {
	// contains filtered or unexported fields
}

RedisClient implements the Client interface for Redis database operations. It manages the connection to a Redis server and provides methods for reading/writing data.

func NewRedisClient

func NewRedisClient(redisConfig *redisconfig.Config) RedisClient

NewRedisClient creates a new RedisClient instance with the provided configuration. The client is not automatically initialized - call Initiate() to establish the connection.

func (*RedisClient) Initiate

func (client *RedisClient) Initiate(ctx context.Context) error

Initiate establishes a connection to the Redis server and validates it with a ping. This method must be called before any read/write operations can be performed. It handles both IP addresses and domain names for the Redis host.

func (*RedisClient) IsClientInitiated added in v0.0.4

func (client *RedisClient) IsClientInitiated() bool

IsClientInitiated returns true if the Redis client has been successfully initialized and is ready to perform operations.

func (*RedisClient) ReadString

func (client *RedisClient) ReadString(ctx context.Context, key string) (string, bool, error)

ReadString retrieves a string value from Redis by key. Returns the value, a boolean indicating if the key was found, and any error. If the key doesn't exist, the boolean will be false and the string will be empty.

func (*RedisClient) WriteString

func (client *RedisClient) WriteString(ctx context.Context, key string, value string, ttl int) error

WriteString stores a string value in Redis with the specified key and TTL. The TTL is specified in seconds. Use 0 for no expiration (infinite TTL). Returns an error if the operation fails or if the client is not initialized.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL