Module: Familia::Connection::Behavior

Included in:
DataType::Connection, Horreum::Connection
Defined in:
lib/familia/connection/behavior.rb

Overview

Shared connection behavior for both Horreum and DataType classes

This module extracts common connection management functionality that was previously duplicated between Horreum::Connection and DataType::Connection. It provides:

  • URI normalization with logical_database support
  • Connection creation methods
  • Transaction and pipeline execution methods
  • Consistent connection API across object types

Classes including this module must implement:

  • dbclient(uri = nil) - Connection resolution method
  • build_connection_chain (private) - Chain of Responsibility setup

Examples:

Basic usage in a class

class MyDataStore
  include Familia::Connection::Behavior

  def dbclient(uri = nil)
    @connection_chain ||= build_connection_chain
    @connection_chain.handle(uri)
  end

  private

  def build_connection_chain
    # ... handler setup ...
  end
end

Instance Method Summary collapse

Instance Method Details

#connectObject

Alias for create_dbclient (backward compatibility)



117
118
119
# File 'lib/familia/connection/behavior.rb', line 117

def connect(*)
  create_dbclient(*)
end

#create_dbclient(uri = nil) ⇒ Redis

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 = create_dbclient('redis://localhost:6379/1')
client.ping
client.close

Parameters:

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

    The URI of the Database server

Returns:

  • (Redis)

    A new Database client connection



111
112
113
114
# File 'lib/familia/connection/behavior.rb', line 111

def create_dbclient(uri = nil)
  parsed_uri = normalize_uri(uri)
  Familia.create_dbclient(parsed_uri)
end

#multiObject

Alias for transaction (alternate naming)



188
189
190
# File 'lib/familia/connection/behavior.rb', line 188

def multi(&)
  transaction(&)
end

#normalize_uri(uri) ⇒ URI

Normalizes various URI formats to a consistent URI object

Handles multiple input types and considers the logical_database setting when uri is nil or Integer. This method is public so connection handlers can use it for consistent URI processing.

Examples:

Integer database number

normalize_uri(2)  # => URI with db=2 on default server

String URI

normalize_uri('redis://localhost:6379/1')

nil with logical_database

class MyModel
  include Familia::Connection::Behavior
  attr_accessor :logical_database
end
model = MyModel.new
model.logical_database = 3
model.normalize_uri(nil)  # => URI with db=3

Parameters:

  • uri (Integer, String, URI, nil)

    The URI to normalize

Returns:

  • (URI)

    Normalized URI object

Raises:

  • (ArgumentError)

    If URI type is invalid



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/familia/connection/behavior.rb', line 73

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
    # Use logical_database if available, otherwise fall back to Familia.uri
    if respond_to?(:logical_database) && logical_database
      new_uri = Familia.uri.dup
      new_uri.db = logical_database
      new_uri
    else
      Familia.uri
    end
  else
    raise ArgumentError, "Invalid URI type: #{uri.class.name}"
  end
end

#pipeline(&block) ⇒ Object

Alias for pipelined (alternate naming)



249
250
251
# File 'lib/familia/connection/behavior.rb', line 249

def pipeline(&block)
  pipelined(&block)
end

#pipelined {|Redis| ... } ⇒ MultiResult

Note:

Connection Inheritance:

  • Uses object's logical_database setting if configured
  • Inherits class-level database settings
  • Falls back to instance-level dbclient if set
  • Uses global connection chain as final fallback
Note:

Pipeline Context:

  • When called outside global pipeline: Creates local MultiResult
  • When called inside global pipeline: Yields to existing pipeline
  • Maintains proper Fiber-local state for nested calls
Note:

Performance Considerations:

  • Best for multiple independent operations
  • Reduces network latency by batching commands
  • Commands execute independently (some may succeed, others fail)

Executes Redis commands in a pipeline using this object's connection context

Batches multiple Redis commands together and sends them in a single network round-trip for improved performance. Uses the object's database and connection settings. Returns a MultiResult object for consistency.

Examples:

Basic pipeline

obj.pipelined do |conn|
  conn.set('key1', 'value1')
  conn.incr('counter')
  conn.get('key1')
end

Performance optimization

# Instead of multiple round-trips:
obj.save            # Round-trip 1
obj.increment_count # Round-trip 2
obj.update_timestamp # Round-trip 3

# Use pipeline for single round-trip:
obj.pipelined do |conn|
  conn.hmset(obj.dbkey, obj.to_h)
  conn.hincrby(obj.dbkey, 'count', 1)
  conn.hset(obj.dbkey, 'updated_at', Time.now.to_i)
end

Yields:

  • (Redis)

    conn The Redis connection configured for pipelined mode

Returns:

  • (MultiResult)

    Result object with success status and command results

Raises:

See Also:



243
244
245
246
# File 'lib/familia/connection/behavior.rb', line 243

def pipelined(&block)
  ensure_relatives_initialized! if respond_to?(:ensure_relatives_initialized!, true)
  Familia::Connection::PipelineCore.execute_pipeline(-> { dbclient }, &block)
end

#transaction {|Redis| ... } ⇒ MultiResult

Note:

Connection Inheritance:

  • Uses object's logical_database setting if configured
  • Inherits class-level database settings
  • Falls back to instance-level dbclient if set
  • Uses global connection chain as final fallback
Note:

Transaction Context:

  • When called outside global transaction: Creates local MultiResult
  • When called inside global transaction: Yields to existing transaction
  • Maintains proper Fiber-local state for nested calls

Executes a Redis transaction (MULTI/EXEC) using this object's connection context

Provides atomic execution of multiple Redis commands with automatic connection management and operation mode enforcement. Uses the object's database and connection settings. Returns a MultiResult object for consistency.

Examples:

Basic transaction

obj.transaction do |conn|
  conn.set('key1', 'value1')
  conn.set('key2', 'value2')
  conn.get('key1')
end

Reentrant behavior

obj.transaction do |conn|
  conn.set('outer', 'value')

  # Nested transaction reuses same connection
  obj.transaction do |inner_conn|
    inner_conn.set('inner', 'value')
  end
end

Yields:

  • (Redis)

    conn The Redis connection configured for transaction mode

Returns:

  • (MultiResult)

    Result object with success status and command results

Raises:

See Also:



182
183
184
185
# File 'lib/familia/connection/behavior.rb', line 182

def transaction(&)
  ensure_relatives_initialized! if respond_to?(:ensure_relatives_initialized!, true)
  Familia::Connection::TransactionCore.execute_transaction(-> { dbclient }, &)
end

#uri=(uri) ⇒ URI

Sets the URI for this object's database connection

Parameters:

  • uri (String, URI, Integer)

    The new URI

Returns:

  • (URI)

    The normalized URI



126
127
128
# File 'lib/familia/connection/behavior.rb', line 126

def uri=(uri)
  @uri = normalize_uri(uri)
end

#urlObject

Alias for uri (backward compatibility)



131
132
133
# File 'lib/familia/connection/behavior.rb', line 131

def url
  uri
end

#url=(uri) ⇒ Object

Alias for uri= (backward compatibility)



136
137
138
# File 'lib/familia/connection/behavior.rb', line 136

def url=(uri)
  self.uri = uri
end