Class: RailsRedshiftReplicator::Replicable

Inherits:
Object
  • Object
show all
Includes:
HairTrigger::Base
Defined in:
lib/rails_redshift_replicator/replicable.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(replication_type, options = {}) ⇒ Replicable

Returns a new instance of Replicable.

Parameters:

  • replication_type (String, Symbol)
  • options (Hash) (defaults to: {})

    Replication options

Options Hash (options):

  • :source_table (String, Symbol)

    name of the source table to replicate

  • :target_table (String, Symbol)

    name of the target table on redshift

  • :replication_field (String, Symbol)

    name of the replication field



13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/rails_redshift_replicator/replicable.rb', line 13

def initialize(replication_type, options = {})
  @replication_type = replication_type
  @options = options
  @source_table = options[:source_table].to_s
  @target_table = (options[:target_table] || source_table).to_s
  replication_field = options[:replication_field] || exporter_class.replication_field
  @replication_field = replication_field && replication_field.to_s
  @tracking_deleted = delete_tracking_enabled?
  if tracking_deleted
    trigger.after(:delete) do
      "INSERT INTO rails_redshift_replicator_deleted_ids(source_table, object_id) VALUES('#{source_table}', OLD.id);"
    end
  end
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options.



4
5
6
# File 'lib/rails_redshift_replicator/replicable.rb', line 4

def options
  @options
end

#replication_fieldObject (readonly)

Returns the value of attribute replication_field.



4
5
6
# File 'lib/rails_redshift_replicator/replicable.rb', line 4

def replication_field
  @replication_field
end

#replication_typeObject (readonly)

Returns the value of attribute replication_type.



4
5
6
# File 'lib/rails_redshift_replicator/replicable.rb', line 4

def replication_type
  @replication_type
end

#source_tableObject (readonly) Also known as: table_name

Returns the value of attribute source_table.



4
5
6
# File 'lib/rails_redshift_replicator/replicable.rb', line 4

def source_table
  @source_table
end

#target_tableObject (readonly)

Returns the value of attribute target_table.



4
5
6
# File 'lib/rails_redshift_replicator/replicable.rb', line 4

def target_table
  @target_table
end

#tracking_deletedObject (readonly)

Returns the value of attribute tracking_deleted.



4
5
6
# File 'lib/rails_redshift_replicator/replicable.rb', line 4

def tracking_deleted
  @tracking_deleted
end

Instance Method Details

#analyzeObject



119
120
121
# File 'lib/rails_redshift_replicator/replicable.rb', line 119

def analyze
  RailsRedshiftReplicator.analyze(target_table)
end

#delete_tracking_enabled?Boolean

Returns:

  • (Boolean)


33
34
35
36
37
# File 'lib/rails_redshift_replicator/replicable.rb', line 33

def delete_tracking_enabled?
  RailsRedshiftReplicator.enable_delete_tracking &&
  (options[:enable_delete_tracking].blank? || options[:enable_delete_tracking]) &&
  table_supports_tracking?
end

#deleterObject



123
124
125
# File 'lib/rails_redshift_replicator/replicable.rb', line 123

def deleter
  RailsRedshiftReplicator::Deleter.new(self)
end

#exportObject



65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/rails_redshift_replicator/replicable.rb', line 65

def export
  @last_replication = nil
  if last_replication.blank? || (last_replication && last_replication.imported?)
    perform_export
  else
    if max_retries_reached?
      last_replication.cancel!
      perform_export
    else
      resume_replication
    end
  end
end

#exporter_classObject



127
128
129
130
131
132
133
# File 'lib/rails_redshift_replicator/replicable.rb', line 127

def exporter_class
  @exporter_class ||= begin
    "RailsRedshiftReplicator::Exporters::#{replication_type.to_s.classify}".constantize
  rescue
    raise StandardError.new I18n.t(:missing_replicator_type, scope: :rails_redshift_replicator)
  end
end

#importObject



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/rails_redshift_replicator/replicable.rb', line 48

def import
  @last_replication = nil
  if last_replication.present?
    if last_replication.uploaded?
      perform_import
    elsif last_replication.imported?
      RailsRedshiftReplicator.logger.info I18n.t(:nothing_to_import, table_name: source_table, scope: :rails_redshift_replicator)
    elsif max_retries_reached?
      last_replication.cancel!
    else
      resume_replication
    end
  else
    RailsRedshiftReplicator.logger.info I18n.t(:nothing_to_import, table_name: source_table, scope: :rails_redshift_replicator)
  end
end

#importer_classObject



135
136
137
138
139
140
141
# File 'lib/rails_redshift_replicator/replicable.rb', line 135

def importer_class
  @importer_class ||= begin
    "RailsRedshiftReplicator::Importers::#{replication_type.to_s.classify}".constantize
  rescue
    raise StandardError.new I18n.t(:missing_replicator_type, scope: :rails_redshift_replicator)
  end
end

#last_replicationObject



96
97
98
# File 'lib/rails_redshift_replicator/replicable.rb', line 96

def last_replication
  @last_replication ||= RailsRedshiftReplicator::Replication.from_table(source_table).last
end

#log_resuming(action) ⇒ Object



111
112
113
# File 'lib/rails_redshift_replicator/replicable.rb', line 111

def log_resuming(action)
  RailsRedshiftReplicator.logger.info I18n.t(:resuming_replication, table_name: source_table, action: action, state: last_replication.state, scope: :rails_redshift_replicator)
end

#max_retries_reached?Boolean

Returns:

  • (Boolean)


87
88
89
90
91
92
93
94
# File 'lib/rails_redshift_replicator/replicable.rb', line 87

def max_retries_reached?
  if RailsRedshiftReplicator.max_retries && (RailsRedshiftReplicator.max_retries == last_replication.retries)
    RailsRedshiftReplicator.logger.warn I18n.t(:max_retries_reached, id: last_replication, table_name: source_table, scope: :rails_redshift_replicator)
    return true
  else
    false
  end
end

#perform_export(replication = nil) ⇒ Object



79
80
81
# File 'lib/rails_redshift_replicator/replicable.rb', line 79

def perform_export(replication = nil)
  exporter_class.new(self, replication).export_and_upload
end

#perform_importObject



83
84
85
# File 'lib/rails_redshift_replicator/replicable.rb', line 83

def perform_import
  importer_class.new(last_replication).import
end

#replicateObject



43
44
45
46
# File 'lib/rails_redshift_replicator/replicable.rb', line 43

def replicate
  export
  import
end

#reset_last_recordObject



28
29
30
31
# File 'lib/rails_redshift_replicator/replicable.rb', line 28

def reset_last_record
  last_imported_replication = RailsRedshiftReplicator::Replication.from_table(source_table).with_state(:imported).last
  last_imported_replication && last_imported_replication.update_attribute(:last_record, nil)
end

#resume_replicationObject



100
101
102
103
104
105
106
107
108
109
# File 'lib/rails_redshift_replicator/replicable.rb', line 100

def resume_replication
  last_replication.increment! :retries, 1
  if last_replication.state.in? %w(enqueued exporting exported uploading)
    log_resuming('export')
    perform_export(last_replication)
  else
    log_resuming('import')
    perform_import
  end
end

#table_supports_tracking?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/rails_redshift_replicator/replicable.rb', line 39

def table_supports_tracking?
  ActiveRecord::Base.connection.columns(source_table).map(&:name).include? "id"
end

#vacuumObject



115
116
117
# File 'lib/rails_redshift_replicator/replicable.rb', line 115

def vacuum
  RailsRedshiftReplicator.vacuum(target_table)
end