Class: Turbocable::NullAdapter

Inherits:
Object
  • Object
show all
Defined in:
lib/turbocable/null_adapter.rb

Overview

A drop-in replacement for NatsConnection that records every publish call in an in-memory ring buffer instead of hitting NATS.

Usage in test suites

# spec_helper.rb / rails_helper.rb
RSpec.configure do |config|
  config.around(:each) do |example|
    Turbocable.configure { |c| c.adapter = :null }
    example.run
    Turbocable::NullAdapter.reset!
  end
end

# In a spec:
it "broadcasts the payload" do
  Turbocable.broadcast("chat_room_42", text: "hello")
  recorded = Turbocable::NullAdapter.broadcasts
  expect(recorded.size).to eq(1)
  expect(recorded.first[:subject]).to eq("TURBOCABLE.chat_room_42")
end

Thread safety

All access to the shared ring buffer is serialized through a class-level Mutex. Instances of NullAdapter are stateless — they delegate recording to class-level state so that callers can inspect broadcasts without keeping a reference to the adapter instance.

Ring buffer

Older entries are evicted once the buffer reaches MAX_BUFFER records. This prevents unbounded memory growth in long-running test suites.

Defined Under Namespace

Classes: NullAck

Constant Summary collapse

MAX_BUFFER =

Default maximum number of broadcast records kept in memory.

1_000

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(buffer_size: MAX_BUFFER) ⇒ NullAdapter

Returns a new instance of NullAdapter.

Parameters:

  • buffer_size (Integer) (defaults to: MAX_BUFFER)

    maximum number of records to keep



77
78
79
# File 'lib/turbocable/null_adapter.rb', line 77

def initialize(buffer_size: MAX_BUFFER)
  @buffer_size = buffer_size
end

Class Method Details

.broadcastsArray<Hash>

Returns a snapshot of all recorded broadcasts since the last reset!.

Each element is a Hash with keys:

  • :subject — the full NATS subject (e.g. “TURBOCABLE.chat_room_42”)

  • :payload — encoded bytes as published

  • :codec — always nil at the adapter layer (codec is resolved by Client before reaching the adapter)

  • :atTime of the publish call

Returns:

  • (Array<Hash>)


55
56
57
# File 'lib/turbocable/null_adapter.rb', line 55

def broadcasts
  @mutex.synchronize { @broadcasts.dup }
end

.record(subject:, payload:, at:, buffer_size:) ⇒ Object

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.



68
69
70
71
72
73
# File 'lib/turbocable/null_adapter.rb', line 68

def record(subject:, payload:, at:, buffer_size:)
  @mutex.synchronize do
    @broadcasts << {subject: subject, payload: payload, codec: nil, at: at}
    @broadcasts.shift while @broadcasts.size > buffer_size
  end
end

.reset!void

This method returns an undefined value.

Clears all recorded broadcasts. Call this between test examples to prevent cross-example pollution. Thread-safe.



63
64
65
# File 'lib/turbocable/null_adapter.rb', line 63

def reset!
  @mutex.synchronize { @broadcasts.clear }
end

Instance Method Details

#closevoid

This method returns an undefined value.

No-op. Satisfies the adapter interface so Turbocable.reset! can call close on the adapter without a conditional.



115
116
# File 'lib/turbocable/null_adapter.rb', line 115

def close
end

#key_valueObject

Not supported on the null adapter. Raises NotImplementedError so that callers don’t silently succeed when running against the null adapter in contexts where KV access is required (e.g. publish_public_key!).

Raises:

  • (NotImplementedError)


105
106
107
108
109
# File 'lib/turbocable/null_adapter.rb', line 105

def key_value(*)
  raise NotImplementedError,
    "NullAdapter does not support key_value. " \
    "Use the :nats adapter when you need KV access."
end

#ping(timeout: 2.0) ⇒ true

Always returns true — the null adapter is always “healthy”.

Parameters:

  • timeout (Float) (defaults to: 2.0)

    accepted but ignored

Returns:

  • (true)


96
97
98
# File 'lib/turbocable/null_adapter.rb', line 96

def ping(timeout: 2.0)
  true
end

#publish(subject, bytes, timeout:) ⇒ NullAck

Records the publish in the class-level ring buffer and returns a fake ack.

Parameters:

  • subject (String)
  • bytes (String)
  • timeout (Float)

    accepted but ignored

Returns:



87
88
89
90
# File 'lib/turbocable/null_adapter.rb', line 87

def publish(subject, bytes, timeout:)
  self.class.record(subject: subject, payload: bytes, at: Time.now, buffer_size: @buffer_size)
  NullAck.new
end