Class: ActiveRecordGraphExtractor::ProgressTracker

Inherits:
Object
  • Object
show all
Defined in:
lib/activerecord_graph_extractor/progress_tracker.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(enabled: true, output: $stdout, total_records: 0) ⇒ ProgressTracker

Returns a new instance of ProgressTracker.



9
10
11
12
13
14
15
16
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 9

def initialize(enabled: true, output: $stdout, total_records: 0)
  @enabled = enabled
  @output = output
  @start_time = nil
  @total_records = total_records
  @processed_records = 0
  @model_progress = {}
end

Instance Attribute Details

#enabledObject (readonly)

Returns the value of attribute enabled.



7
8
9
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 7

def enabled
  @enabled
end

#model_progressObject (readonly)

Returns the value of attribute model_progress.



7
8
9
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 7

def model_progress
  @model_progress
end

#processed_recordsObject (readonly)

Returns the value of attribute processed_records.



7
8
9
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 7

def processed_records
  @processed_records
end

#start_timeObject (readonly)

Returns the value of attribute start_time.



7
8
9
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 7

def start_time
  @start_time
end

#total_recordsObject (readonly)

Returns the value of attribute total_records.



7
8
9
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 7

def total_records
  @total_records
end

Instance Method Details

#complete?Boolean

Returns:

  • (Boolean)


111
112
113
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 111

def complete?
  @total_records > 0 && @processed_records >= @total_records
end

#complete_extraction(final_count, duration) ⇒ Object



41
42
43
44
45
46
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 41

def complete_extraction(final_count, duration)
  return unless @enabled

  rate = duration > 0 ? (final_count / duration).round(1) : 0
  log_info("✅ Extraction completed! #{format_number(final_count)} records in #{format_duration(duration)} (#{rate} records/sec)")
end

#complete_import(final_count, duration) ⇒ Object



56
57
58
59
60
61
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 56

def complete_import(final_count, duration)
  return unless @enabled

  rate = duration > 0 ? (final_count / duration).round(1) : 0
  log_info("✅ Import completed! #{format_number(final_count)} records in #{format_duration(duration)} (#{rate} records/sec)")
end

#current_memory_usageObject



178
179
180
181
182
183
184
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 178

def current_memory_usage
  if defined?(GC.stat)
    (GC.stat[:heap_allocated_pages] * 4096 / 1024.0 / 1024.0).round(1)
  else
    0.0
  end
end

#elapsed_timeObject



92
93
94
95
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 92

def elapsed_time
  return 0 unless @start_time
  Time.now - @start_time
end

#estimated_time_remainingObject



97
98
99
100
101
102
103
104
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 97

def estimated_time_remaining
  return 0 if @processed_records == 0 || @total_records == 0 || @processed_records >= @total_records
  
  elapsed = elapsed_time
  rate = @processed_records / elapsed
  remaining_records = @total_records - @processed_records
  remaining_records / rate
end

#incrementObject



83
84
85
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 83

def increment
  @processed_records += 1
end

#log_error(message) ⇒ Object



148
149
150
151
152
153
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 148

def log_error(message)
  # Always show errors, even if progress is disabled
  @output.puts("❌ ERROR: #{message}")
rescue StandardError
  # Silently ignore output errors
end

#log_info(message) ⇒ Object



163
164
165
166
167
168
169
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 163

def log_info(message)
  return unless @enabled

  @output.puts(message)
rescue StandardError
  # Silently ignore output errors
end

#log_memory_usageObject



171
172
173
174
175
176
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 171

def log_memory_usage
  return unless @enabled

  memory_mb = current_memory_usage
  log_info("💾 Memory usage: #{memory_mb} MB")
end

#log_model_progress(model_name, current, total = nil) ⇒ Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 63

def log_model_progress(model_name, current, total = nil)
  if total.nil?
    # If only current is provided, assume it's a simple increment
    @model_progress[model_name] ||= { current: 0, total: 1, percentage: 0 }
    @model_progress[model_name][:current] = current
    @model_progress[model_name][:percentage] = 100
  else
    percentage = total > 0 ? (current * 100.0 / total).round(1) : 0
    @model_progress[model_name] = {
      current: current,
      total: total,
      percentage: percentage
    }
    
    if @enabled
      log_info("📝 #{model_name}: #{format_number(current)}/#{format_number(total)} (#{percentage}%)")
    end
  end
end

#log_progress_to_io(io) ⇒ Object



138
139
140
141
142
143
144
145
146
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 138

def log_progress_to_io(io)
  io.puts(to_s)
  io.puts("Elapsed: #{format_duration(elapsed_time)}")
  io.puts("Remaining: #{format_duration(estimated_time_remaining)}")
  
  @model_progress.each do |model, progress|
    io.puts("#{model}: #{progress[:current]}/#{progress[:total]} (#{progress[:percentage]}%)")
  end
end

#log_warning(message) ⇒ Object



155
156
157
158
159
160
161
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 155

def log_warning(message)
  return unless @enabled

  @output.puts("⚠️  WARNING: #{message}")
rescue StandardError
  # Silently ignore output errors
end

#progress_percentageObject



87
88
89
90
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 87

def progress_percentage
  return 0 if @total_records == 0
  (@processed_records * 100.0 / @total_records).round(1)
end

#records_per_secondObject



106
107
108
109
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 106

def records_per_second
  return 0 if @processed_records == 0 || elapsed_time == 0
  @processed_records / elapsed_time
end

#resetObject



115
116
117
118
119
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 115

def reset
  @processed_records = 0
  @model_progress = {}
  @start_time = nil
end

#startObject



18
19
20
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 18

def start
  @start_time = Time.now
end

#start_extraction(total_count) ⇒ Object



22
23
24
25
26
27
28
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 22

def start_extraction(total_count)
  return unless @enabled

  @total_records = total_count
  @start_time = Time.now
  log_info("🚀 Starting extraction of #{format_number(total_count)} records...")
end

#start_import(total_count) ⇒ Object



48
49
50
51
52
53
54
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 48

def start_import(total_count)
  return unless @enabled

  @total_records = total_count
  @start_time = Time.now
  log_info("🚀 Starting import of #{format_number(total_count)} records...")
end

#to_json(*args) ⇒ Object



125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 125

def to_json(*args)
  {
    total_records: @total_records,
    processed_records: @processed_records,
    progress_percentage: progress_percentage,
    elapsed_time: elapsed_time,
    estimated_time_remaining: estimated_time_remaining,
    records_per_second: records_per_second,
    model_progress: @model_progress,
    complete: complete?
  }.to_json(*args)
end

#to_sObject



121
122
123
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 121

def to_s
  "Progress: #{@processed_records}/#{@total_records} (#{progress_percentage}%)"
end

#update_progress(current_count, message = nil) ⇒ Object



30
31
32
33
34
35
36
37
38
39
# File 'lib/activerecord_graph_extractor/progress_tracker.rb', line 30

def update_progress(current_count, message = nil)
  return unless @enabled

  percentage = @total_records > 0 ? (current_count * 100.0 / @total_records).round(1) : 0

  status = "📊 Progress: #{format_number(current_count)}/#{format_number(@total_records)} (#{percentage}%)"
  status += " - #{message}" if message

  log_info(status)
end