class WSDirector::Protocols::Base

Base protocol describes basic actions

Attributes

client[R]
task[R]

Public Class Methods

new(task) click to toggle source
# File lib/wsdirector/protocols/base.rb, line 11
def initialize(task)
  @task = task
end

Public Instance Methods

debug(step) click to toggle source

Prints provided message

# File lib/wsdirector/protocols/base.rb, line 46
def debug(step)
  print(step.fetch("message"))
end
handle_step(step) click to toggle source
# File lib/wsdirector/protocols/base.rb, line 19
def handle_step(step)
  type = step.delete("type")
  raise Error, "Unknown step: #{type}" unless respond_to?(type)

  return unless task.sampled?(step)

  public_send(type, step)
end
init_client(**options) click to toggle source
# File lib/wsdirector/protocols/base.rb, line 15
def init_client(**options)
  @client = build_client(**options)
end
receive(step) click to toggle source
# File lib/wsdirector/protocols/base.rb, line 50
def receive(step)
  expected = step.fetch("data")
  received = client.receive
  raise UnmatchedExpectationError, prepare_receive_error(expected, received) unless
    receive_matches?(expected, received)
rescue ThreadError
  raise NoMessageError, "Expected to receive #{expected} but nothing has been received"
end
receive_all(step) click to toggle source

rubocop: disable Metrics/CyclomaticComplexity

# File lib/wsdirector/protocols/base.rb, line 60
def receive_all(step)
  messages = step.delete("messages")
  raise ArgumentError, "Messages array must be specified" if
    messages.nil? || messages.empty?

  expected =
    Hash[messages.map do |msg|
      multiplier = parse_multiplier(msg.delete("multiplier") || "1")
      [msg["data"], multiplier]
    end]

  total_expected = expected.values.sum
  total_received = 0

  total_expected.times do
    received = client.receive

    total_received += 1

    match = expected.find { |k, _| receive_matches?(k, received) }

    raise UnexpectedMessageError, "Unexpected message received: #{received}" if
      match.nil?

    expected[match.first] -= 1
    expected.delete(match.first) if expected[match.first].zero?
  end
rescue ThreadError
  raise NoMessageError,
    "Expected to receive #{total_expected} messages " \
    "but received only #{total_received}"
end
send(step) click to toggle source

rubocop: enable Metrics/CyclomaticComplexity

# File lib/wsdirector/protocols/base.rb, line 94
def send(step)
  data = step.fetch("data")
  data = JSON.generate(data) if data.is_a?(Hash)
  client.send(data)
end
sleep(step) click to toggle source

Sleeps for a specified number of seconds.

If “shift” is provided than the initial value is shifted by random number from (-shift, shift).

Set “debug” to true to print the delay time.

# File lib/wsdirector/protocols/base.rb, line 34
def sleep(step)
  delay = step.fetch("time").to_f
  shift = step.fetch("shift", 0).to_f

  delay = delay - shift * rand + shift * rand

  print("Sleep for #{delay}s") if step.fetch("debug", false)

  Kernel.sleep delay if delay > 0
end
to_proc() click to toggle source
# File lib/wsdirector/protocols/base.rb, line 104
def to_proc
  proc { |step| handle_step(step) }
end
wait_all(_step) click to toggle source
# File lib/wsdirector/protocols/base.rb, line 100
def wait_all(_step)
  task.global_holder.wait_all
end

Private Instance Methods

build_client(**options) click to toggle source
# File lib/wsdirector/protocols/base.rb, line 112
def build_client(**options)
  Client.new(**options)
end
prepare_receive_error(expected, received) click to toggle source
# File lib/wsdirector/protocols/base.rb, line 122
      def prepare_receive_error(expected, received)
        <<~MSG
          Action failed: #receive
             -- expected: #{expected}
             ++ got: #{received}
        MSG
      end
print(msg) click to toggle source
receive_matches?(expected, received) click to toggle source
# File lib/wsdirector/protocols/base.rb, line 116
def receive_matches?(expected, received)
  received = JSON.parse(received) if expected.is_a?(Hash)

  received == expected
end