Class RR::Replicators::TwoWayReplicator
In: lib/rubyrep/replicators/two_way_replicator.rb
Parent: Object

This replicator implements a two way replication. Options:

  • :left_change_handling, :right_change_handling: Handling of records that were changed only in the named database. Can be any of the following:
    • :ignore: No action.
    • :replicate: Updates other database accordingly. Default Setting
    • Proc object: If a Proc object is given, it is responsible for dealing with the record. Called with the following parameters:
  • :replication_conflict_handling: Handling of conflicting record changes. Can be any of the following:
    • :ignore: No action. Default Setting
    • :left_wins: The right database is updated accordingly.
    • :right_wins: The left database is updated accordingly.
    • :later_wins: The more recent change is replicated. (If both changes have same age: left change is replicated)
    • :earlier_wins: The less recent change is replicated. (If both records have same age: left change is replicated)
    • Proc object: If a Proc object is given, it is responsible for dealing with the record. Called with the following parameters:
  • :logged_replication_events: Specifies which types of replications are logged. Is either a single value or an array of multiple ones. Default: [:ignored_conflicts] Possible values:
    • :ignored_changes: log ignored (but not replicated) non-conflict changes
    • :all_changes: log all non-conflict changes
    • :ignored_conflicts: log ignored (but not replicated) conflicts
    • :all_conflicts: log all conflicts

Example of using a Proc object for custom behaviour:

  lambda do |rep_helper, diff|
    # if specified as replication_conflict_handling option, logs all
    # conflicts to a text file
    File.open('/var/log/rubyrep_conflict_log', 'a') do |f|
      f.puts <<-end_str
        #{Time.now}: conflict
        * in table #{diff.changes[:left].table}
        * for record '#{diff.changes[:left].key}'
        * change type in left db: '#{diff.changes[:left].type}'
        * change type in right db: '#{diff.changes[:right].type}'
      end_str
    end
  end

Methods

Constants

OTHER_SIDE = { :left => :right, :right => :left   Shortcut to calculate the "other" database.
CONFLICT_STATE_MATRIX = { :insert => {:insert => :update, :update => :update, :delete => :insert}, :update => {:insert => :update, :update => :update, :delete => :insert}, :delete => {:insert => :delete, :update => :delete, :delete => :delete}   Specifies how to clear conflicts. The outer hash keys describe the type of the winning change. The inner hash keys describe the type of the loosing change. The inser hash values describe the action to take on the loosing side.
MAX_REPLICATION_ATTEMPTS = 2   How often a replication will be attempted (in case it fails because the record in question was removed from the source or inserted into the target database after the ReplicationDifference was loaded

Attributes

rep_helper  [RW]  The current ReplicationHelper object

Public Class methods

Provides default option for the replicator. Optional. Returns a hash with key => value pairs.

Initializes the TwoWayReplicator Raises an ArgumentError if any of the replication options is invalid.

Parameters:

  • rep_helper: The ReplicationHelper object providing information and utility functions.

Public Instance methods

Helper for execution of insert / update / delete attempts. Wraps those attempts into savepoints and handles exceptions.

Note: Savepoints have to be used for PostgreSQL (as a failed SQL statement will otherwise invalidate the complete transaction.)

  • action: short description of change (e. g.: "update" or "delete")
  • source_db: either :left or :right - source database of replication
  • target_db: either :left or :right - target database of replication
  • diff: the current ReplicationDifference instance
  • remaining_attempts: the number of remaining replication attempts for this difference

Attempts to delete the source record from the target database.

  1. g. if +source_db is :left, then the record is deleted in database

:right.

  • source_db: either :left or :right - source database of replication
  • diff: the current ReplicationDifference instance
  • remaining_attempts: the number of remaining replication attempts for this difference
  • target_key: a column_name => value hash identifying the source record

Attempts to read the specified record from the source database and insert it into the target database. Retries if insert fails due to missing source or suddenly existing target record.

  • source_db: either :left or :right - source database of replication
  • diff: the current ReplicationDifference instance
  • remaining_attempts: the number of remaining replication attempts for this difference
  • source_key: a column_name => value hash identifying the source record

Attempts to read the specified record from the source database and update the specified record in the target database. Retries if update fails due to missing source

  • source_db: either :left or :right - source database of replication
  • diff: the current ReplicationDifference instance
  • remaining_attempts: the number of remaining replication attempts for this difference
  • source_key: a column_name => value hash identifying the source record
  • target_key: a column_name => value hash identifying the source record

Helper function that clears a conflict by taking the change from the specified winning database and updating the other database accordingly.

  • source_db: the winning database (either :left or :right)
  • diff: the ReplicationDifference instance
  • remaining_attempts: the number of remaining replication attempts for this difference

Logs replication of the specified difference as per configured :replication_conflict_logging / :left_change_logging / :right_change_logging options.

  • winner: Either the winner database (:left or :right) or :ignore
  • diff: the ReplicationDifference instance

Called to replicate the specified difference.

  • :diff: ReplicationDifference instance
  • :remaining_attempts: how many more times a replication will be attempted
  • :previous_failure_description: why the previous replication attempt failed

Verifies if the :left_change_handling / :right_change_handling options are valid. Raises an ArgumentError if an option is invalid

Verifies if the given :replication_conflict_handling options are valid. Raises an ArgumentError if an option is invalid.

Verifies if the given :replication_logging option /options is / are valid. Raises an ArgumentError if invalid

Checks if an option is configured correctly. Raises an ArgumentError if not.

  • table_spec: the table specification to which the option belongs. May be nil.
  • valid_option_values: array of valid option values
  • option_key: the key of the option that is to be checked
  • option_value: the value of the option that is to be checked

[Validate]