Class: Backup::Model

Inherits:
Object
  • Object
show all
Defined in:
lib/backup/model.rb

Defined Under Namespace

Classes: Error, FatalError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(trigger, label, &block) ⇒ Model

Returns a new instance of Model.



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/backup/model.rb', line 113

def initialize(trigger, label, &block)
  @trigger = trigger.to_s
  @label   = label.to_s
  @package = Package.new(self)

  @databases  = []
  @archives   = []
  @storages   = []
  @notifiers  = []
  @syncers    = []

  instance_eval(&self.class.preconfigure) if self.class.preconfigure
  instance_eval(&block) if block_given?

  # trigger all defined databases to generate their #dump_filename
  # so warnings may be logged if `backup perform --check` is used
  databases.each { |db| db.send(:dump_filename) }

  Model.all << self
end

Instance Attribute Details

#archivesObject (readonly)

Array of configured Archive objects.



55
56
57
# File 'lib/backup/model.rb', line 55

def archives
  @archives
end

#compressorObject (readonly)

The configured Compressor, if any.



71
72
73
# File 'lib/backup/model.rb', line 71

def compressor
  @compressor
end

#databasesObject (readonly)

Array of configured Database objects.



51
52
53
# File 'lib/backup/model.rb', line 51

def databases
  @databases
end

#encryptorObject (readonly)

The configured Encryptor, if any.



75
76
77
# File 'lib/backup/model.rb', line 75

def encryptor
  @encryptor
end

#exceptionObject (readonly)

Exception raised by either a before hook or one of the model’s procedures that caused the model to fail. An exception raised by an after hook would not be stored here. Therefore, it is possible for this to be nil even if #exit_status is 2 or 3.



111
112
113
# File 'lib/backup/model.rb', line 111

def exception
  @exception
end

#exit_statusObject (readonly)

Result of this model’s backup process.

0 = Job was successful 1 = Job was successful, but issued warnings 2 = Job failed, additional triggers may be performed 3 = Job failed, additional triggers will not be performed



104
105
106
# File 'lib/backup/model.rb', line 104

def exit_status
  @exit_status
end

#finished_atObject (readonly)

The time when the backup finished (as a Time object)



95
96
97
# File 'lib/backup/model.rb', line 95

def finished_at
  @finished_at
end

#labelObject (readonly)

The label (stored as a String) is used for a more friendly user output



47
48
49
# File 'lib/backup/model.rb', line 47

def label
  @label
end

#notifiersObject (readonly)

Array of configured Notifier objects.



59
60
61
# File 'lib/backup/model.rb', line 59

def notifiers
  @notifiers
end

#packageObject (readonly)

The final backup Package this model will create.



83
84
85
# File 'lib/backup/model.rb', line 83

def package
  @package
end

#splitterObject (readonly)

The configured Splitter, if any.



79
80
81
# File 'lib/backup/model.rb', line 79

def splitter
  @splitter
end

#started_atObject (readonly)

The time when the backup initiated (as a Time object)



91
92
93
# File 'lib/backup/model.rb', line 91

def started_at
  @started_at
end

#storagesObject (readonly)

Array of configured Storage objects.



63
64
65
# File 'lib/backup/model.rb', line 63

def storages
  @storages
end

#syncersObject (readonly)

Array of configured Syncer objects.



67
68
69
# File 'lib/backup/model.rb', line 67

def syncers
  @syncers
end

#timeObject (readonly)

The time when the backup initiated (in format: 2011.02.20.03.29.59)



87
88
89
# File 'lib/backup/model.rb', line 87

def time
  @time
end

#triggerObject (readonly)

The trigger (stored as a String) is used as an identifier for initializing the backup process



43
44
45
# File 'lib/backup/model.rb', line 43

def trigger
  @trigger
end

Class Method Details

.allObject

The Backup::Model.all class method keeps track of all the models that have been instantiated. It returns the @all class variable, which contains an array of all the models



11
12
13
# File 'lib/backup/model.rb', line 11

def all
  @all ||= []
end

.find_by_trigger(trigger) ⇒ Object

Return an Array of Models matching the given trigger.



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

def find_by_trigger(trigger)
  trigger = trigger.to_s
  if trigger.include?("*")
    regex = /^#{ trigger.gsub('*', '(.*)') }$/
    all.select { |model| regex =~ model.trigger }
  else
    all.select { |model| trigger == model.trigger }
  end
end

.preconfigure(&block) ⇒ Object

Allows users to create preconfigured models.



28
29
30
# File 'lib/backup/model.rb', line 28

def preconfigure(&block)
  @preconfigure ||= block
end

Instance Method Details

#after(&block) ⇒ Object

Defines a block of code to run after the model’s procedures.

This code is ensured to run, even if the model failed, unless a before hook raised an exception and aborted the model.

The code block will be passed the model’s current exit_status:

‘0`: Success, no warnings. `1`: Success, but warnings were logged. `2`: Failure, but additional models/triggers will still be processed. `3`: Failure, no additional models/triggers will be processed.

The model’s exit_status may be elevated based on the after hook’s actions, but will never be decreased.

Warnings logged within the after hook may elevate the model’s exit_status to 1 and cause warning notifications to be sent.

Raising an exception may elevate the model’s exit_status and cause failure notifications to be sent. If the exception is a StandardError, the exit_status will be elevated to 2. If the exception is not a StandardError, the exit_status will be elevated to 3.



238
239
240
241
# File 'lib/backup/model.rb', line 238

def after(&block)
  @after = block if block
  @after
end

#archive(name, &block) ⇒ Object

Adds an Archive. Multiple Archives may be added to the model.



136
137
138
# File 'lib/backup/model.rb', line 136

def archive(name, &block)
  @archives << Archive.new(self, name, &block)
end

#before(&block) ⇒ Object

Defines a block of code to run before the model’s procedures.

Warnings logged within the before hook will elevate the model’s exit_status to 1 and cause warning notifications to be sent.

Raising an exception will abort the model and cause failure notifications to be sent. If the exception is a StandardError, exit_status will be 2. If the exception is not a StandardError, exit_status will be 3.

If any exception is raised, any defined after hook will be skipped.



210
211
212
213
# File 'lib/backup/model.rb', line 210

def before(&block)
  @before = block if block
  @before
end

#compress_with(name, &block) ⇒ Object

Adds an Compressor. Only one Compressor may be added to the model. This will be used to compress each individual Archive and Database stored within the final backup package.



177
178
179
# File 'lib/backup/model.rb', line 177

def compress_with(name, &block)
  @compressor = get_class_from_scope(Compressor, name).new(&block)
end

#database(name, database_id = nil, &block) ⇒ Object

Adds an Database. Multiple Databases may be added to the model.



142
143
144
145
# File 'lib/backup/model.rb', line 142

def database(name, database_id = nil, &block)
  @databases << get_class_from_scope(Database, name)
    .new(self, database_id, &block)
end

#durationObject

The duration of the backup process (in format: HH:MM:SS)



290
291
292
293
# File 'lib/backup/model.rb', line 290

def duration
  return unless finished_at
  elapsed_time(started_at, finished_at)
end

#encrypt_with(name, &block) ⇒ Object

Adds an Encryptor. Only one Encryptor may be added to the model. This will be used to encrypt the final backup package.



169
170
171
# File 'lib/backup/model.rb', line 169

def encrypt_with(name, &block)
  @encryptor = get_class_from_scope(Encryptor, name).new(&block)
end

#notify_by(name, &block) ⇒ Object

Adds an Notifier. Multiple Notifiers may be added to the model.



162
163
164
# File 'lib/backup/model.rb', line 162

def notify_by(name, &block)
  @notifiers << get_class_from_scope(Notifier, name).new(self, &block)
end

#perform!Object

Performs the backup process

Once complete, #exit_status will indicate the result of this process.

If any errors occur during the backup process, all temporary files will be left in place. If the error occurs before Packaging, then the temporary folder (tmp_path/trigger) will remain and may contain all or some of the configured Archives and/or Database dumps. If the error occurs after Packaging, but before the Storages complete, then the final packaged files (located in the root of tmp_path) will remain.

*** Important *** If an error occurs and any of the above mentioned temporary files remain, those files *** will be removed *** before the next scheduled backup for the same trigger.



259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# File 'lib/backup/model.rb', line 259

def perform!
  @started_at = Time.now.utc
  @time = package.time = started_at.strftime("%Y.%m.%d.%H.%M.%S")

  log!(:started)
  before_hook

  procedures.each do |procedure|
    procedure.is_a?(Proc) ? procedure.call : procedure.each(&:perform!)
  end

  syncers.each(&:perform!)

rescue Interrupt
  @interrupted = true
  raise

rescue Exception => err
  @exception = err

ensure
  unless @interrupted
    set_exit_status
    @finished_at = Time.now.utc
    log!(:finished)
    after_hook
  end
end

#split_into_chunks_of(chunk_size, suffix_length = 3) ⇒ Object

Adds a Splitter to split the final backup package into multiple files.

chunk_size is specified in MiB and must be given as an Integer. suffix_length controls the number of characters used in the suffix (and the maximum number of chunks possible). ie. 1 (-a, -b), 2 (-aa, -ab), 3 (-aaa, -aab)



188
189
190
191
192
193
194
195
196
197
# File 'lib/backup/model.rb', line 188

def split_into_chunks_of(chunk_size, suffix_length = 3)
  if chunk_size.is_a?(Integer) && suffix_length.is_a?(Integer)
    @splitter = Splitter.new(self, chunk_size, suffix_length)
  else
    raise Error, "      Invalid arguments for #split_into_chunks_of()\n      +chunk_size+ (and optional +suffix_length+) must be Integers.\n    EOS\n  end\nend\n"

#store_with(name, storage_id = nil, &block) ⇒ Object

Adds an Storage. Multiple Storages may be added to the model.



149
150
151
152
# File 'lib/backup/model.rb', line 149

def store_with(name, storage_id = nil, &block)
  @storages << get_class_from_scope(Storage, name)
    .new(self, storage_id, &block)
end

#sync_with(name, syncer_id = nil, &block) ⇒ Object

Adds an Syncer. Multiple Syncers may be added to the model.



156
157
158
# File 'lib/backup/model.rb', line 156

def sync_with(name, syncer_id = nil, &block)
  @syncers << get_class_from_scope(Syncer, name).new(syncer_id, &block)
end