Module: Familia::Connection

Includes:
Middleware, Operations
Included in:
Familia
Defined in:
lib/familia/connection.rb,
lib/familia/connection/behavior.rb,
lib/familia/connection/handlers.rb,
lib/familia/connection/middleware.rb,
lib/familia/connection/operations.rb,
lib/familia/connection/operation_core.rb,
lib/familia/connection/pipelined_core.rb,
lib/familia/connection/transaction_core.rb,
lib/familia/connection/individual_command_proxy.rb

Overview

The Connection module provides Database connection management for Familia. It allows easy setup and access to Database clients across different URIs with robust connection pooling for thread safety.

Defined Under Namespace

Modules: Behavior, Middleware, OperationCore, Operations, PipelineCore, TransactionCore Classes: BaseConnectionHandler, CachedConnectionHandler, CreateConnectionHandler, FiberConnectionHandler, FiberTransactionHandler, IndividualCommandProxy, ParentDelegationHandler, ProviderConnectionHandler, ResponsibilityChain, StandaloneConnectionHandler

Constant Summary collapse

DefaultConnectionHandler =
CreateConnectionHandler

Instance Attribute Summary collapse

Attributes included from Middleware

#enable_database_counter, #enable_database_logging

Instance Method Summary collapse

Methods included from Operations

#pipelined, #transaction, #with_dbclient, #with_isolated_dbclient

Methods included from Middleware

#clear_fiber_connection!, #fiber_connection=, #increment_middleware_version!, #middleware_version, #reconnect!

Instance Attribute Details

#connection_providerProc

The provider should accept a URI string and return a Redis connection already connected to the correct database specified in the URI.

Examples:

Setting a connection provider

Familia.connection_provider = ->(uri) do
  pool = ConnectionPool.new { Redis.new(url: uri) }
  pool.with { |conn| conn }
end

Returns:

  • (Proc)

    A callable that provides Database connections



42
43
44
# File 'lib/familia/connection.rb', line 42

def connection_provider
  @connection_provider
end

#uriURI Also known as: url

Returns The default URI for Database connections.

Returns:

  • (URI)

    The default URI for Database connections



31
32
33
# File 'lib/familia/connection.rb', line 31

def uri
  @uri
end

Instance Method Details

#build_connection_chainObject

Builds the connection chain with handlers in priority order



113
114
115
116
117
118
119
# File 'lib/familia/connection.rb', line 113

def build_connection_chain
  ResponsibilityChain.new
    .add_handler(Familia::Connection::FiberTransactionHandler.new)
    .add_handler(FiberConnectionHandler.new)
    .add_handler(ProviderConnectionHandler.new)
    .add_handler(CreateConnectionHandler.new)
end

#create_dbclient(uri = nil) ⇒ Redis Also known as: connect, isolated_dbclient

Creates a new Database connection instance.

This method always creates a fresh connection and does not use caching. Each call returns a new Redis client instance that you are responsible for managing and closing when done.

Examples:

Creating a new connection

client = Familia.create_dbclient('redis://localhost:6379')
client.ping
client.close

Parameters:

  • uri (String, URI, nil) (defaults to: nil)

    The URI of the Database server to connect to. If nil, uses the default URI from Familia.uri.

Returns:

  • (Redis)

    A new Database client connection.

Raises:

  • (ArgumentError)

    If no URI is specified.



80
81
82
83
84
85
86
87
# File 'lib/familia/connection.rb', line 80

def create_dbclient(uri = nil)
  parsed_uri = normalize_uri(uri)

  # Register middleware only once, globally
  register_middleware_once

  Redis.new(parsed_uri.conf)
end

#dbclient(uri = nil) ⇒ Redis

Retrieves a Database connection using the Chain of Responsibility pattern. Handles DB selection automatically based on the URI.

Thread-safe: Uses double-checked locking pattern to avoid mutex overhead on the hot path. Only acquires mutex during initial lazy initialization. MRI's GIL provides implicit memory barriers making this pattern safe.

Examples:

Familia.dbclient('redis://localhost:6379/1')

Familia.dbclient(2)  # Use DB 2 with default server

Returns:

  • (Redis)

    The Database client for the specified URI



101
102
103
104
105
106
107
108
109
110
# File 'lib/familia/connection.rb', line 101

def dbclient(uri = nil)
  # Fast path - read with local variable to ensure single read
  chain = @connection_chain
  return chain.handle(uri) if chain

  # Slow path - initialization only
  @connection_chain_mutex.synchronize do
    @connection_chain ||= build_connection_chain
  end.handle(uri)
end

#normalize_uri(uri) ⇒ Object

Normalizes various URI formats to a consistent URI object Made public so handlers can use it



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/familia/connection.rb', line 123

def normalize_uri(uri)
  case uri
  when Integer
    new_uri = Familia.uri.dup
    new_uri.db = uri
    new_uri
  when ->(obj) { obj.is_a?(String) || obj.instance_of?(::String) }
    URI.parse(uri)
  when URI
    uri
  when nil
    Familia.uri
  else
    raise ArgumentError, "Invalid URI type: #{uri.class.name}"
  end
end