Class: DataShifter::Shift
- Inherits:
-
Object
- Object
- DataShifter::Shift
- Includes:
- Axn
- Defined in:
- lib/data_shifter/shift.rb
Class Method Summary collapse
-
.allow_external_requests(hosts) ⇒ Object
Allow these hosts (or regexes) for HTTP during dry run only.
- .description(text = nil) ⇒ Object
- .progress(enabled = nil) ⇒ Object
- .run! ⇒ Object
-
.suppress_repeated_logs(enabled) ⇒ Object
Enable/disable log deduplication for this shift.
-
.task(label = nil, &block) ⇒ Object
Define a task block to run instead of collection/process_record.
- .task_name(value = nil) ⇒ Object
- .throttle(interval) ⇒ Object
- .transaction(mode) ⇒ Object
Instance Method Summary collapse
-
#call ⇒ Object
— Public API (intentionally exposed to subclasses) —.
- #dry_run? ⇒ Boolean
- #find_exactly!(model, ids) ⇒ Object
- #log(message) ⇒ Object
- #skip!(reason = nil) ⇒ Object
Class Method Details
.allow_external_requests(hosts) ⇒ Object
Allow these hosts (or regexes) for HTTP during dry run only. Combines with DataShifter.config.allow_external_requests. Has no effect in commit mode — HTTP is unrestricted when dry_run is false. Example: allow_external_requests [“api.readonly.example.com”, %rinternal.internal.companyz]
123 124 125 |
# File 'lib/data_shifter/shift.rb', line 123 def allow_external_requests(hosts) self._allow_external_requests = Array(hosts) end |
.description(text = nil) ⇒ Object
79 80 81 82 83 84 85 |
# File 'lib/data_shifter/shift.rb', line 79 def description(text = nil) if text.nil? _description else self._description = text.to_s.presence end end |
.progress(enabled = nil) ⇒ Object
108 109 110 111 112 113 114 |
# File 'lib/data_shifter/shift.rb', line 108 def progress(enabled = nil) if enabled.nil? _progress_enabled else self._progress_enabled = !!enabled end end |
.run! ⇒ Object
148 149 150 151 152 153 |
# File 'lib/data_shifter/shift.rb', line 148 def run! dry_run = Internal::Env.dry_run? result = call(dry_run:) raise result.exception if result.exception raise StandardError, result.error unless result.ok? end |
.suppress_repeated_logs(enabled) ⇒ Object
Enable/disable log deduplication for this shift. Overrides DataShifter.config.suppress_repeated_logs. Example: suppress_repeated_logs false
129 130 131 |
# File 'lib/data_shifter/shift.rb', line 129 def suppress_repeated_logs(enabled) self._suppress_repeated_logs = !!enabled end |
.task(label = nil, &block) ⇒ Object
Define a task block to run instead of collection/process_record. Multiple blocks run in sequence; labels appear in errors and summary. Example:
task "Fix user A" do
User.find(123).update!(...)
end
task "Fix user B" do
User.find(456).update!(...)
end
142 143 144 145 146 |
# File 'lib/data_shifter/shift.rb', line 142 def task(label = nil, &block) raise ArgumentError, "task requires a block" unless block_given? self._task_blocks = (_task_blocks || []).dup + [{ label: label.presence, block: }] end |
.task_name(value = nil) ⇒ Object
87 88 89 90 91 92 93 |
# File 'lib/data_shifter/shift.rb', line 87 def task_name(value = nil) if value.nil? _task_name else self._task_name = value.to_s.presence end end |
.throttle(interval) ⇒ Object
116 117 118 |
# File 'lib/data_shifter/shift.rb', line 116 def throttle(interval) self._throttle_interval = interval end |
.transaction(mode) ⇒ Object
95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/data_shifter/shift.rb', line 95 def transaction(mode) case mode when :per_record self._transaction_mode = :per_record when :none, false self._transaction_mode = :none when :single, true self._transaction_mode = :single else raise ArgumentError, "Invalid transaction mode: #{mode.inspect}. Expected :single, :per_record, :none, true, or false." end end |
Instance Method Details
#call ⇒ Object
— Public API (intentionally exposed to subclasses) —
158 159 160 161 162 163 164 |
# File 'lib/data_shifter/shift.rb', line 158 def call if self.class._task_blocks.any? _run_task_blocks else _for_each_record_in(collection) { |record| process_record(record) } end end |
#dry_run? ⇒ Boolean
177 |
# File 'lib/data_shifter/shift.rb', line 177 def dry_run? = dry_run |
#find_exactly!(model, ids) ⇒ Object
166 167 168 169 170 171 172 173 174 175 |
# File 'lib/data_shifter/shift.rb', line 166 def find_exactly!(model, ids) ids = Array(ids).compact.uniq return model.none if ids.empty? records_by_id = model.where(id: ids).index_by(&:id) missing = ids.reject { |id| records_by_id.key?(id) } raise "Expected #{model.name} with ids #{ids.inspect}, but missing: #{missing.inspect}" if missing.any? ids.map { |id| records_by_id[id] } end |
#log(message) ⇒ Object
186 187 188 |
# File 'lib/data_shifter/shift.rb', line 186 def log() puts Internal::Colors.dim() end |
#skip!(reason = nil) ⇒ Object
179 180 181 182 183 184 |
# File 'lib/data_shifter/shift.rb', line 179 def skip!(reason = nil) @stats[:skipped] += 1 key = reason.to_s.presence || "(no reason given)" @skip_reasons[key] += 1 raise SkipRecord end |