Class: Mxrb::Semantic::BatchPlan
- Inherits:
-
Object
- Object
- Mxrb::Semantic::BatchPlan
- Defined in:
- lib/mxrb/semantic/batch_plan.rb
Overview
Wraps multiple plans into a single atomic operation with rollback on failure.
Before applying, a backup of the MPR is taken using SQLite's VACUUM INTO. If any plan raises, the backup is restored and the project state is reset as if the batch never ran.
Usage:
plan1 = project.plan_rename("M.OldName", to: "M.NewName")
plan2 = project.plan_add_attribute("M.NewName", name: :Slug, type: :string)
project.batch_plan([plan1, plan2]).apply!
Instance Attribute Summary collapse
-
#changes ⇒ Object
readonly
Returns the value of attribute changes.
-
#plans ⇒ Object
readonly
Returns the value of attribute plans.
Instance Method Summary collapse
- #applied? ⇒ Boolean
- #apply! ⇒ Object
- #empty? ⇒ Boolean
-
#initialize(project:, plans:) ⇒ BatchPlan
constructor
A new instance of BatchPlan.
Constructor Details
#initialize(project:, plans:) ⇒ BatchPlan
Returns a new instance of BatchPlan.
20 21 22 23 24 25 |
# File 'lib/mxrb/semantic/batch_plan.rb', line 20 def initialize(project:, plans:) @project = project @plans = plans.freeze @applied = false @changes = @plans.flat_map { |p| p.respond_to?(:changes) ? Array(p.changes) : [] }.freeze end |
Instance Attribute Details
#changes ⇒ Object (readonly)
Returns the value of attribute changes.
18 19 20 |
# File 'lib/mxrb/semantic/batch_plan.rb', line 18 def changes @changes end |
#plans ⇒ Object (readonly)
Returns the value of attribute plans.
18 19 20 |
# File 'lib/mxrb/semantic/batch_plan.rb', line 18 def plans @plans end |
Instance Method Details
#applied? ⇒ Boolean
28 |
# File 'lib/mxrb/semantic/batch_plan.rb', line 28 def applied? = @applied |
#apply! ⇒ Object
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/mxrb/semantic/batch_plan.rb', line 30 def apply! raise ArgumentError, "batch plan was already applied" if @applied return self if @plans.empty? backup_path = "#{@project.mpr.path}.mxrb_batch_backup" @project.mpr.backup!(backup_path) begin @plans.each(&:apply!) @applied = true rescue => error idx = @plans.index { !_1.applied? }.to_i + 1 rollback_errors = rollback_applied_plans @project.mpr.restore_from!(backup_path) @project.refresh! detail = rollback_errors.empty? ? "" : "; rollback failed: #{rollback_errors.join(', ')}" raise BatchError, "batch failed at plan #{idx} of #{@plans.size}: #{error.}#{detail}" ensure FileUtils.rm_f(backup_path) rescue nil end self end |
#empty? ⇒ Boolean
27 |
# File 'lib/mxrb/semantic/batch_plan.rb', line 27 def empty? = @plans.empty? |