Module: DatabaseCommandCounter

Defined in:
lib/middleware/database_command_counter.rb

Overview

DatabaseCommandCounter is redis-rb middleware for counting commands.

This middleware counts the number of Redis commands executed. It can be useful for performance monitoring and debugging, allowing you to track the volume of Redis operations in your application.

Familia uses the redis-rb gem (v4.8.1 to <6.0), which internally uses RedisClient infrastructure. Users work with Redis.new connections - the RedisClient middleware registration is handled automatically by Familia.

User-Facing API

Enable via Familia configuration: Familia.enable_database_counter = true

Familia automatically calls RedisClient.register(DatabaseCommandCounter) internally.

Middleware Chaining

This middleware works correctly alongside DatabaseLogger because it uses super to properly chain method calls. See DatabaseLogger for detailed explanation of middleware chaining mechanics.

Examples:

Enable Redis command counting (recommended user-facing API)

DatabaseCommandCounter.reset
Familia.enable_database_counter = true

Use with DatabaseLogger

Familia.enable_database_logging = true
Familia.enable_database_counter = true
# Both middlewares registered automatically and execute correctly in sequence

See Also:

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Class Attribute Details

.skip_commandsSet<String> (readonly)

Gets the set of commands to skip counting.

Returns:

  • (Set<String>)

    The commands that won't be counted



57
58
59
# File 'lib/middleware/database_command_counter.rb', line 57

def skip_commands
  @skip_commands
end

Class Method Details

.countInteger

Gets the current count of Redis commands executed.

Returns:

  • (Integer)

    The number of Redis commands executed



61
62
63
# File 'lib/middleware/database_command_counter.rb', line 61

def count
  @count.value
end

.count_commands { ... } ⇒ Integer

Counts the number of Redis commands executed within a block.

This method captures the command count before and after executing the provided block, returning the difference. This is useful for measuring how many Redis commands are executed by a specific operation.

Examples:

Count commands in a block

commands_executed = DatabaseCommandCounter.count_commands do
  dbclient.set('key1', 'value1')
  dbclient.get('key1')
end
# commands_executed will be 2

Yields:

  • [] The block of code to execute while counting commands

Returns:

  • (Integer)

    The number of Redis commands executed within the block



103
104
105
106
107
108
# File 'lib/middleware/database_command_counter.rb', line 103

def count_commands
  start_count = count      # Capture the current command count before execution
  yield                    # Execute the provided block
  end_count = count        # Capture the command count after execution
  end_count - start_count  # Return the difference (commands executed in block)
end

.incrementInteger

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Increments the command count. This method is thread-safe.

Returns:

  • (Integer)

    The new count after incrementing



76
77
78
# File 'lib/middleware/database_command_counter.rb', line 76

def increment
  @count.increment
end

.resetInteger

Resets the command count to zero. This method is thread-safe.

Returns:

  • (Integer)

    The reset count (always 0)



68
69
70
# File 'lib/middleware/database_command_counter.rb', line 68

def reset
  @count.value = 0
end

.skip_command?(command) ⇒ Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Checks if a command should be skipped.

Parameters:

  • command (Array)

    The Redis command array

Returns:

  • (Boolean)

    true if command should be skipped



84
85
86
# File 'lib/middleware/database_command_counter.rb', line 84

def skip_command?(command)
  skip_commands.include?(command.first.to_s.upcase)
end

Instance Method Details

#call(command, _config) ⇒ Object

Counts the Redis command and delegates its execution.

This method is part of the RedisClient middleware chain. It MUST use super instead of yield to properly chain with other middlewares like DatabaseLogger.

Parameters:

  • command (Array)

    The Redis command and its arguments

  • _config (RedisClient::Config, Hash)

    Connection configuration (unused)

Returns:

  • (Object)

    The result of the Redis command execution



125
126
127
128
# File 'lib/middleware/database_command_counter.rb', line 125

def call(command, _config)
  klass.increment unless klass.skip_command?(command)
  super  # CRITICAL: Must use super, not yield, to chain middlewares
end

#call_once(command, _config) ⇒ Object

Counts a call_once command and delegates execution.

Parameters:

  • command (Array)

    The Redis command and its arguments

  • _config (RedisClient::Config, Hash)

    Connection configuration (unused)

Returns:

  • (Object)

    The result of the Redis command execution



148
149
150
151
# File 'lib/middleware/database_command_counter.rb', line 148

def call_once(command, _config)
  klass.increment unless klass.skip_command?(command)
  super  # CRITICAL: Must use super, not yield, to chain middlewares
end

#call_pipelined(commands, _config) ⇒ Array

Counts commands in a pipeline and delegates execution.

Parameters:

  • commands (Array<Array>)

    Array of command arrays

  • _config (RedisClient::Config, Hash)

    Connection configuration (unused)

Returns:

  • (Array)

    Results from pipelined commands



135
136
137
138
139
140
141
# File 'lib/middleware/database_command_counter.rb', line 135

def call_pipelined(commands, _config)
  # Count all commands in the pipeline (except skipped ones)
  commands.each do |command|
    klass.increment unless klass.skip_command?(command)
  end
  super  # CRITICAL: Must use super, not yield, to chain middlewares
end

#klassObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Reference to the module for use in instance methods



113
114
115
# File 'lib/middleware/database_command_counter.rb', line 113

def klass
  DatabaseCommandCounter
end