Module: Kumi::Core::Analyzer::Checkpoint

Defined in:
lib/kumi/core/analyzer/checkpoint.rb

Class Method Summary collapse

Class Method Details

.dirObject

—- Config (ENV) —-



19
# File 'lib/kumi/core/analyzer/checkpoint.rb', line 19

def dir         = ENV["KUMI_CHECKPOINT_DIR"]    || "tmp/analysis_snapshots"

.enabled?Boolean

Interface shape matches Debug =====


11
12
13
14
15
16
# File 'lib/kumi/core/analyzer/checkpoint.rb', line 11

def enabled?
  return false if ENV["KUMI_CHECKPOINT"] == "0"

  ENV["KUMI_CHECKPOINT"] == "1" ||
    !resume_from.nil? || !resume_at.nil? || !stop_after.nil?
end

.entering(pass_name:, idx:, state:) ⇒ Object



39
40
41
42
43
# File 'lib/kumi/core/analyzer/checkpoint.rb', line 39

def entering(pass_name:, idx:, state:)
  return unless enabled?

  snapshot(pass_name:, idx:, phase: :before, state:) if phases.include?(:before)
end

.formatsObject

marshal|json|both



21
# File 'lib/kumi/core/analyzer/checkpoint.rb', line 21

def formats     = (ENV["KUMI_CHECKPOINT_FORMAT"] || "marshal").split(",").map! { _1.strip.downcase } # marshal|json|both

.leaving(pass_name:, idx:, state:) ⇒ Object



45
46
47
48
49
# File 'lib/kumi/core/analyzer/checkpoint.rb', line 45

def leaving(pass_name:, idx:, state:)
  return unless enabled?

  snapshot(pass_name:, idx:, phase: :after, state:) if phases.include?(:after)
end

.load_initial_state(default_state) ⇒ Object

Lifecycle (called by analyzer) =====


27
28
29
30
31
32
33
34
35
36
37
# File 'lib/kumi/core/analyzer/checkpoint.rb', line 27

def load_initial_state(default_state)
  path = resume_from
  return default_state unless path && File.exist?(path)

  data = File.binread(path)
  if path.end_with?(".msh")
    StateSerde.load_marshal(data)
  else
    StateSerde.load_json(data)
  end
end

.phasesObject



20
# File 'lib/kumi/core/analyzer/checkpoint.rb', line 20

def phases      = (ENV["KUMI_CHECKPOINT_PHASE"] || "before,after").split(",").map! { _1.strip.downcase.to_sym }

.resume_atObject

pass short name



23
# File 'lib/kumi/core/analyzer/checkpoint.rb', line 23

def resume_at   = ENV.fetch("KUMI_RESUME_AT", nil)   # pass short name

.resume_fromObject

file path (.msh or .json)



22
# File 'lib/kumi/core/analyzer/checkpoint.rb', line 22

def resume_from = ENV.fetch("KUMI_RESUME_FROM", nil) # file path (.msh or .json)

.snapshot(pass_name:, idx:, phase:, state:) ⇒ Object

Implementation =====


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/kumi/core/analyzer/checkpoint.rb', line 52

def snapshot(pass_name:, idx:, phase:, state:)
  FileUtils.mkdir_p(dir)
  base = File.join(dir, "%03d_#{pass_name}_#{phase}" % idx)
  files = []

  if formats.include?("marshal") || formats.include?("both")
    path = "#{base}.msh"
    File.binwrite(path, StateSerde.dump_marshal(state))
    files << path
  end

  if formats.include?("json") || formats.include?("both")
    path = "#{base}.json"
    File.write(path, StateSerde.dump_json(state, pretty: true))
    files << path
  end

  # Fold checkpoint info into the same per-pass logs the Debugger uses.
  Core::Analyzer::Debug.info(:checkpoint, phase:, idx:, files:) if Core::Analyzer::Debug.enabled?

  files
end

.stop_afterObject

pass short name



24
# File 'lib/kumi/core/analyzer/checkpoint.rb', line 24

def stop_after  = ENV.fetch("KUMI_STOP_AFTER", nil)  # pass short name