def replicate_difference(diff, remaining_attempts = MAX_REPLICATION_ATTEMPTS, previous_failure_description = nil)
raise Exception, previous_failure_description || "max replication attempts exceeded" if remaining_attempts == 0
options = rep_helper.options_for_table(diff.changes[:left].table)
if diff.type == :left or diff.type == :right
key = diff.type == :left ? :left_change_handling : :right_change_handling
option = options[key]
if option == :ignore
log_replication_outcome :ignore, diff
elsif option == :replicate
source_db = diff.type
change = diff.changes[source_db]
case change.type
when :insert
attempt_insert source_db, diff, remaining_attempts, change.key
when :update
attempt_update source_db, diff, remaining_attempts, change.new_key, change.key
when :delete
attempt_delete source_db, diff, remaining_attempts, change.key
end
else
option.call rep_helper, diff
end
elsif diff.type == :conflict
option = options[:replication_conflict_handling]
if option == :ignore
log_replication_outcome :ignore, diff
elsif option == :left_wins
clear_conflict :left, diff, remaining_attempts
elsif option == :right_wins
clear_conflict :right, diff, remaining_attempts
elsif option == :later_wins
winner_db = diff.changes[:left].last_changed_at >= diff.changes[:right].last_changed_at ? :left : :right
clear_conflict winner_db, diff, remaining_attempts
elsif option == :earlier_wins
winner_db = diff.changes[:left].last_changed_at <= diff.changes[:right].last_changed_at ? :left : :right
clear_conflict winner_db, diff, remaining_attempts
else
option.call rep_helper, diff
end
end
end