Class: Profiler::TestRunner::RunStore

Inherits:
Object
  • Object
show all
Defined in:
lib/profiler/test_runner/run_store.rb

Defined Under Namespace

Classes: Run

Constant Summary collapse

TTL =

1 hour

3600
TERMINAL_STATUSES =
%w[passed failed killed error].freeze

Instance Method Summary collapse

Constructor Details

#initializeRunStore

Returns a new instance of RunStore.



24
25
26
27
# File 'lib/profiler/test_runner/run_store.rb', line 24

def initialize
  @runs  = Concurrent::Hash.new
  @locks = Concurrent::Hash.new
end

Instance Method Details

#allObject



88
89
90
# File 'lib/profiler/test_runner/run_store.rb', line 88

def all
  @runs.values.sort_by { |r| r.started_at || Time.at(0) }.reverse
end

#append_output(id, chunk) ⇒ Object



61
62
63
64
65
66
67
# File 'lib/profiler/test_runner/run_store.rb', line 61

def append_output(id, chunk)
  run = @runs[id]
  return unless run

  run.output_lines.push(chunk)
  signal(id)
end

#create(files:, framework:) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/profiler/test_runner/run_store.rb', line 29

def create(files:, framework:)
  id  = SecureRandom.hex(8)
  run = Run.new(
    id: id,
    status: "pending",
    pid: nil,
    started_at: Time.now,
    finished_at: nil,
    output_lines: Concurrent::Array.new,
    exit_code: nil,
    files: files,
    framework: framework.to_s
  )
  @runs[id]  = run
  @locks[id] = { mutex: Mutex.new, cond: ConditionVariable.new }
  cleanup_old_runs
  run
end

#find(id) ⇒ Object



48
49
50
# File 'lib/profiler/test_runner/run_store.rb', line 48

def find(id)
  @runs[id]
end

#update(id, **attrs) ⇒ Object



52
53
54
55
56
57
58
59
# File 'lib/profiler/test_runner/run_store.rb', line 52

def update(id, **attrs)
  run = @runs[id]
  return unless run

  attrs.each { |k, v| run.send(:"#{k}=", v) }
  signal(id)
  run
end

#wait_for_output(id, position:, timeout: 10) ⇒ Object

Block until new output is available at position or the run terminates. Returns { chunks: […], status: “…”, position: N, finished: bool }.



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/profiler/test_runner/run_store.rb', line 71

def wait_for_output(id, position:, timeout: 10)
  run = @runs[id]
  return { chunks: [], status: "not_found", position: 0, finished: true } unless run

  lock = @locks[id]
  return snapshot(run, position) unless lock

  lock[:mutex].synchronize do
    current = run.output_lines.size
    if current <= position && !TERMINAL_STATUSES.include?(run.status)
      lock[:cond].wait(lock[:mutex], timeout)
    end
  end

  snapshot(run, position)
end