Module: StepTrack

Extended by:
StepTrack
Included in:
StepTrack
Defined in:
lib/step_track.rb,
lib/step_track/version.rb

Constant Summary collapse

REF =
"step_track/%{track}"
DEFAULT_CONFIG =
{merge_key: :merge, error_key: :error}.freeze
VERSION =
"0.5.2"

Instance Method Summary collapse

Instance Method Details

#done(track) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# File 'lib/step_track.rb', line 42

def done(track)
  require_init!(track)
  track_ref = Thread.current[ref(track)]
  Thread.current[ref(track)] = nil
  steps = track_ref.delete(:steps)
  steps.each { |step| step.delete(:time) }
  result = {
    step_count: steps.count,
    caller: track_ref[:caller],
    duration: Time.now.to_f - track_ref[:time].to_f,
    track_id: track_ref[:track_id]
  }
  if err = steps.detect { |s| s.key?(track_ref[:error_key]) }
    last_step = err.dup
  else
    last_step = steps.last&.dup || {}
  end
  result[:final_step_name] = last_step.delete(:step_name)
  merge_down_steps!(result, steps)
  return track_ref[:callback].call(result)
end

#get_callerObject



9
10
11
# File 'lib/step_track.rb', line 9

def get_caller
  @caller ||= ->() { caller[1].sub(Dir.pwd + "/", "") }
end

#init(track, config = {}) ⇒ Object

Raises:

  • (ArgumentError)


17
18
19
20
21
22
23
24
25
26
# File 'lib/step_track.rb', line 17

def init(track, config={})
  raise ArgumentError, "callback block required" unless block_given?
  Thread.current[ref(track)] = {
    track_id: config[:track_id] || Thread.current.object_id.to_s,
    steps: [],
    callback: Proc.new,
    time: Time.now,
    caller: config&.[](:caller) || get_caller.()
  }.merge(DEFAULT_CONFIG).merge(config)
end

#partition_into(payload, name) ⇒ Object



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

def partition_into(payload, name)
  payload, other = payload.partition do |k, _v|
    k.to_s !~ /^step_#{name}_/
  end.map(&:to_h)
  prev_pattern = /^step_#{name}_([^\d].*)$/
  other = other.reduce([{}]) do |acc, (k, v)|
    match = k.to_s.match(prev_pattern)
    unless match
      acc << {}
      digit = k.to_s.match(/^step_#{name}_(\d+)/).captures.first
      prev_pattern = /^step_#{name}_#{digit}_(.*)$/
      match = k.to_s.match(prev_pattern)
    end
    acc.last[match.captures.first.to_sym] = v
    next acc
  end.reject(&:empty?)
  return payload, other
end

#push(track, name, payload = {}) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/step_track.rb', line 28

def push(track, name, payload={})
  require_init!(track)
  track_ref = Thread.current[ref(track)]
  merge_step = track_ref[:steps].pop if payload.delete(track_ref[:merge_key])
  last_step = track_ref[:steps].last
  track_ref[:steps] << (merge_step || {}).merge(
    split: Time.now.to_f - (last_step&.[](:time) || track_ref[:time]).to_f,
    duration: Time.now.to_f - track_ref[:time].to_f,
    time: Time.now,
    caller: merge_step&.[](:caller) || get_caller.(),
    step_name: merge_step&.[](:step_name) || name
  ).merge(payload)
end

#set_caller(&blk) ⇒ Object



13
14
15
# File 'lib/step_track.rb', line 13

def set_caller(&blk)
  @caller = blk
end

#track_id(track) ⇒ Object



64
65
66
67
# File 'lib/step_track.rb', line 64

def track_id(track)
  require_init!(track)
  return Thread.current[ref(track)][:track_id]
end