Module: Familia::Validation::CommandRecorder

Extended by:
CommandRecorder
Included in:
CommandRecorder
Defined in:
lib/familia/validation/command_recorder.rb

Overview

Enhanced command recorder that captures Redis commands with full context for validation purposes. Extends the existing DatabaseLogger functionality to provide detailed command tracking including transaction boundaries.

Examples:

Basic usage

CommandRecorder.start_recording
# ... perform Redis operations
commands = CommandRecorder.stop_recording
puts commands.map(&:to_s)

Transaction recording

CommandRecorder.start_recording
Familia.transaction do |conn|
  conn.hset("key", "field", "value")
  conn.incr("counter")
end
commands = CommandRecorder.stop_recording
commands.transaction_blocks.length #=> 1
commands.transaction_blocks.first.commands.length #=> 2

Defined Under Namespace

Modules: Middleware Classes: CommandSequence, PipelineBlock, RecordedCommand, TransactionBlock

Instance Method Summary collapse

Instance Method Details

#clearObject

Clear all recorded data



303
304
305
# File 'lib/familia/validation/command_recorder.rb', line 303

def clear
  @recorded_commands.value.clear
end

#current_sequenceObject

Get the current command sequence (for inspection during recording)



298
299
300
# File 'lib/familia/validation/command_recorder.rb', line 298

def current_sequence
  @recorded_commands.value
end

#in_pipeline?Boolean

Check if we’re currently in a pipeline

Returns:

  • (Boolean)


283
284
285
# File 'lib/familia/validation/command_recorder.rb', line 283

def in_pipeline?
  @pipeline_stack.value.any?
end

#in_transaction?Boolean

Check if we’re currently in a transaction

Returns:

  • (Boolean)


278
279
280
# File 'lib/familia/validation/command_recorder.rb', line 278

def in_transaction?
  @transaction_stack.value.any?
end

#pipeline_depthObject

Get current pipeline nesting depth



293
294
295
# File 'lib/familia/validation/command_recorder.rb', line 293

def pipeline_depth
  @pipeline_stack.value.length
end

#record_command(command:, args:, result:, timestamp:, duration_us:, context: {}) ⇒ Object

Record a Redis command with full context



243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/familia/validation/command_recorder.rb', line 243

def record_command(command:, args:, result:, timestamp:, duration_us:, context: {})
  return unless recording?

  # Enhance context with transaction/pipeline state
  enhanced_context = context.merge(
    transaction: in_transaction?,
    pipeline: in_pipeline?,
    transaction_depth: transaction_depth,
    pipeline_depth: pipeline_depth
  )

  recorded_cmd = RecordedCommand.new(
    command: command,
    args: args,
    result: result,
    timestamp: timestamp,
    duration_us: duration_us,
    context: enhanced_context
  )

  sequence = @recorded_commands.value
  sequence.add_command(recorded_cmd)

  # Handle transaction boundaries
  case recorded_cmd.command
  when 'MULTI'
    sequence.start_transaction(enhanced_context)
    @transaction_stack.value.push(Time.now)
  when 'EXEC', 'DISCARD'
    sequence.end_transaction if sequence.current_transaction
    @transaction_stack.value.pop
  end
end

#recording?Boolean

Check if currently recording

Returns:

  • (Boolean)


238
239
240
# File 'lib/familia/validation/command_recorder.rb', line 238

def recording?
  @recording_state.value == true
end

#start_recordingObject

Start recording Redis commands for the current thread



222
223
224
225
226
227
# File 'lib/familia/validation/command_recorder.rb', line 222

def start_recording
  @recording_state.value = true
  @recorded_commands.value = CommandSequence.new
  @transaction_stack.value = []
  @pipeline_stack.value = []
end

#stop_recordingObject

Stop recording and return the recorded command sequence



230
231
232
233
234
235
# File 'lib/familia/validation/command_recorder.rb', line 230

def stop_recording
  @recording_state.value = false
  sequence = @recorded_commands.value
  @recorded_commands.value = CommandSequence.new
  sequence
end

#transaction_depthObject

Get current transaction nesting depth



288
289
290
# File 'lib/familia/validation/command_recorder.rb', line 288

def transaction_depth
  @transaction_stack.value.length
end