rubyrep 1.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +18 -0
  5. data/Gemfile.lock +84 -0
  6. data/History.txt +6 -0
  7. data/README.txt +1 -1
  8. data/Rakefile +6 -27
  9. data/bin/rubyrep +1 -1
  10. data/config/mysql_config.rb +2 -2
  11. data/config/postgres_config.rb +5 -3
  12. data/lib/rubyrep/command_runner.rb +1 -1
  13. data/lib/rubyrep/connection_extenders/connection_extenders.rb +30 -44
  14. data/lib/rubyrep/connection_extenders/mysql_extender.rb +23 -1
  15. data/lib/rubyrep/connection_extenders/postgresql_extender.rb +31 -168
  16. data/lib/rubyrep/generate_runner.rb +1 -1
  17. data/lib/rubyrep/logged_change.rb +1 -1
  18. data/lib/rubyrep/proxy_connection.rb +22 -12
  19. data/lib/rubyrep/replication_difference.rb +1 -1
  20. data/lib/rubyrep/replication_extenders/mysql_replication.rb +1 -1
  21. data/lib/rubyrep/replication_helper.rb +1 -1
  22. data/lib/rubyrep/replication_runner.rb +10 -0
  23. data/lib/rubyrep/scan_report_printers/scan_detail_reporter.rb +1 -1
  24. data/lib/rubyrep/table_spec_resolver.rb +1 -1
  25. data/lib/rubyrep/type_casting_cursor.rb +8 -4
  26. data/lib/rubyrep/version.rb +1 -7
  27. data/lib/rubyrep.rb +4 -3
  28. data/rubyrep +4 -0
  29. data/rubyrep.bat +5 -0
  30. data/rubyrep.gemspec +29 -0
  31. data/sims/performance/big_rep_spec.rb +34 -17
  32. data/sims/performance/performance.rake +11 -31
  33. data/tasks/database.rake +14 -14
  34. data/tasks/java.rake +18 -5
  35. data/tasks/rspec.rake +14 -34
  36. data/tasks/stats.rake +1 -16
  37. metadata +99 -162
  38. data/.gemtest +0 -0
  39. data/config/requirements.rb +0 -32
  40. data/lib/rubyrep/connection_extenders/jdbc_extender.rb +0 -65
  41. data/spec/base_runner_spec.rb +0 -218
  42. data/spec/buffered_committer_spec.rb +0 -274
  43. data/spec/command_runner_spec.rb +0 -145
  44. data/spec/committers_spec.rb +0 -178
  45. data/spec/configuration_spec.rb +0 -203
  46. data/spec/connection_extender_interface_spec.rb +0 -141
  47. data/spec/connection_extenders_registration_spec.rb +0 -164
  48. data/spec/database_proxy_spec.rb +0 -48
  49. data/spec/database_rake_spec.rb +0 -40
  50. data/spec/db_specific_connection_extenders_spec.rb +0 -34
  51. data/spec/db_specific_replication_extenders_spec.rb +0 -38
  52. data/spec/direct_table_scan_spec.rb +0 -61
  53. data/spec/dolphins.jpg +0 -0
  54. data/spec/generate_runner_spec.rb +0 -84
  55. data/spec/initializer_spec.rb +0 -46
  56. data/spec/log_helper_spec.rb +0 -39
  57. data/spec/logged_change_loader_spec.rb +0 -68
  58. data/spec/logged_change_spec.rb +0 -470
  59. data/spec/noisy_connection_spec.rb +0 -78
  60. data/spec/postgresql_replication_spec.rb +0 -48
  61. data/spec/postgresql_schema_support_spec.rb +0 -212
  62. data/spec/postgresql_support_spec.rb +0 -63
  63. data/spec/progress_bar_spec.rb +0 -77
  64. data/spec/proxied_table_scan_spec.rb +0 -151
  65. data/spec/proxy_block_cursor_spec.rb +0 -197
  66. data/spec/proxy_connection_spec.rb +0 -423
  67. data/spec/proxy_cursor_spec.rb +0 -56
  68. data/spec/proxy_row_cursor_spec.rb +0 -66
  69. data/spec/proxy_runner_spec.rb +0 -70
  70. data/spec/replication_difference_spec.rb +0 -161
  71. data/spec/replication_extender_interface_spec.rb +0 -367
  72. data/spec/replication_extenders_spec.rb +0 -32
  73. data/spec/replication_helper_spec.rb +0 -178
  74. data/spec/replication_initializer_spec.rb +0 -509
  75. data/spec/replication_run_spec.rb +0 -443
  76. data/spec/replication_runner_spec.rb +0 -254
  77. data/spec/replicators_spec.rb +0 -36
  78. data/spec/rubyrep_spec.rb +0 -8
  79. data/spec/scan_detail_reporter_spec.rb +0 -119
  80. data/spec/scan_progress_printers_spec.rb +0 -68
  81. data/spec/scan_report_printers_spec.rb +0 -67
  82. data/spec/scan_runner_spec.rb +0 -50
  83. data/spec/scan_summary_reporter_spec.rb +0 -61
  84. data/spec/session_spec.rb +0 -253
  85. data/spec/spec.opts +0 -1
  86. data/spec/spec_helper.rb +0 -305
  87. data/spec/strange_name_support_spec.rb +0 -135
  88. data/spec/sync_helper_spec.rb +0 -169
  89. data/spec/sync_runner_spec.rb +0 -78
  90. data/spec/syncers_spec.rb +0 -171
  91. data/spec/table_scan_helper_spec.rb +0 -36
  92. data/spec/table_scan_spec.rb +0 -49
  93. data/spec/table_sorter_spec.rb +0 -30
  94. data/spec/table_spec_resolver_spec.rb +0 -111
  95. data/spec/table_sync_spec.rb +0 -140
  96. data/spec/task_sweeper_spec.rb +0 -47
  97. data/spec/trigger_mode_switcher_spec.rb +0 -83
  98. data/spec/two_way_replicator_spec.rb +0 -721
  99. data/spec/two_way_syncer_spec.rb +0 -256
  100. data/spec/type_casting_cursor_spec.rb +0 -50
  101. data/spec/uninstall_runner_spec.rb +0 -93
  102. data/tasks/rubyrep.tailor +0 -18
  103. data/tasks/website.rake +0 -19
@@ -1,721 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper.rb'
2
-
3
- include RR
4
-
5
- describe Replicators::TwoWayReplicator do
6
- before(:each) do
7
- Initializer.configuration = deep_copy(standard_config)
8
- Initializer.configuration.options = {:replicator => :two_way}
9
- end
10
-
11
- it "should register itself" do
12
- Replicators::replicators[:two_way].should == Replicators::TwoWayReplicator
13
- end
14
-
15
- it "initialize should store the replication helper" do
16
- rep_run = ReplicationRun.new(Session.new, TaskSweeper.new(1))
17
- helper = ReplicationHelper.new(rep_run)
18
- replicator = Replicators::TwoWayReplicator.new(helper)
19
- replicator.rep_helper.should == helper
20
- end
21
-
22
- it "verify_option should raise descriptive errors" do
23
- rep_run = ReplicationRun.new(Session.new, TaskSweeper.new(1))
24
- helper = ReplicationHelper.new(rep_run)
25
- replicator = Replicators::TwoWayReplicator.new(helper)
26
- lambda {replicator.verify_option(nil, [:valid_value], :my_key, :my_value)}.
27
- should raise_error(ArgumentError, ':my_value not a valid :my_key option')
28
- lambda {replicator.verify_option(/my_spec/, [:valid_value], :my_key, :my_value)}.
29
- should raise_error(ArgumentError, '/my_spec/: :my_value not a valid :my_key option')
30
- end
31
-
32
- it "initialize should throw an error if options are invalid" do
33
- rep_run = ReplicationRun.new(Session.new, TaskSweeper.new(1))
34
- helper = ReplicationHelper.new(rep_run)
35
- base_options = {
36
- :replicator => :two_way,
37
- :left_change_handling => :ignore,
38
- :right_change_handling => :ignore,
39
- :replication_conflict_handling => :ignore,
40
- :logged_replication_events => [:ignored_conflicts]
41
- }
42
-
43
- # Verify that correct options don't raise errors.
44
- helper.stub!(:options).and_return(base_options)
45
- lambda {Replicators::TwoWayReplicator.new(helper)}.should_not raise_error
46
-
47
- # Also lambda options should not raise errors.
48
- l = lambda {}
49
- helper.stub!(:options).and_return(base_options.merge(
50
- {
51
- :left_change_handling => l,
52
- :right_change_handling => l,
53
- :repliction_conflict_handling => l
54
- })
55
- )
56
- lambda {Replicators::TwoWayReplicator.new(helper)}.should_not raise_error
57
-
58
- # Invalid options should raise errors
59
- invalid_options = [
60
- {:left_change_handling => :invalid_left_option},
61
- {:right_change_handling => :invalid_right_option},
62
- {:replication_conflict_handling => :invalid_conflict_option},
63
- {:logged_replication_events => :invalid_logging_option},
64
- ]
65
- invalid_options.each do |options|
66
- helper.session.configuration.stub!(:options).and_return(base_options.merge(options))
67
- lambda {Replicators::TwoWayReplicator.new(helper)}.should raise_error(ArgumentError)
68
- end
69
- end
70
-
71
- it "clear_conflicts should update the correct database with the correct action" do
72
- Initializer.configuration.include_tables 'left_table, right_table'
73
- session = Session.new
74
- session.left.begin_db_transaction
75
- session.right.begin_db_transaction
76
- begin
77
- rep_run = ReplicationRun.new(session, TaskSweeper.new(1))
78
- helper = ReplicationHelper.new(rep_run)
79
- replicator = Replicators::TwoWayReplicator.new(helper)
80
-
81
- loaders = LoggedChangeLoaders.new(session)
82
-
83
- left_change = LoggedChange.new loaders[:left]
84
- left_change.table = 'left_table'
85
- left_change.key = {'id' => '1'}
86
- right_change = LoggedChange.new loaders[:right]
87
- right_change.table = 'right_table'
88
- right_change.key = {'id' => '1'}
89
-
90
- diff = ReplicationDifference.new(loaders)
91
- diff.changes[:left] = left_change
92
- diff.changes[:right] = right_change
93
-
94
-
95
- # verify that an insert is dealt correctly with
96
- left_change.type = :insert
97
- right_change.type = :insert
98
-
99
- helper.should_receive(:load_record).ordered.
100
- with(:left, 'left_table', {'id' => '1'}).
101
- and_return(:dummy_values)
102
- helper.should_receive(:update_record).ordered.
103
- with(:right, 'right_table', :dummy_values, {'id' => '1'})
104
- replicator.clear_conflict :left, diff, 1
105
-
106
- # verify that an update is dealt correctly with
107
- left_change.type = :delete
108
- right_change.type = :update
109
- right_change.new_key = {'id' => '2'}
110
-
111
-
112
- helper.should_receive(:load_record).ordered.
113
- with(:right, 'right_table', {'id' => '2'}).
114
- and_return(:dummy_values)
115
- helper.should_receive(:insert_record).ordered.
116
- with(:left, 'left_table', :dummy_values)
117
- replicator.clear_conflict :right, diff, 1
118
-
119
-
120
- # verify that a delete is dealt correctly with
121
- left_change.type = :delete
122
- right_change.type = :update
123
-
124
- helper.should_receive(:delete_record).ordered.
125
- with(:right, 'right_table', {'id' => '2'})
126
- replicator.clear_conflict :left, diff, 1
127
- ensure
128
- session.left.rollback_db_transaction
129
- session.right.rollback_db_transaction
130
- end
131
- end
132
-
133
- it "log_replication_outcome should log conflicts correctly" do
134
- session = Session.new
135
- rep_run = ReplicationRun.new(session, TaskSweeper.new(1))
136
-
137
- loaders = LoggedChangeLoaders.new(session)
138
-
139
- diff = ReplicationDifference.new loaders
140
- diff.type = :conflict
141
- diff.changes[:left] = LoggedChange.new loaders[:left]
142
- diff.changes[:left].table = 'scanner_records'
143
-
144
- # should only log events if so configured
145
- helper = ReplicationHelper.new(rep_run)
146
- replicator = Replicators::TwoWayReplicator.new(helper)
147
- helper.should_not_receive(:log_replication_outcome)
148
- helper.stub!(:options_for_table).and_return({:logged_replication_events => []})
149
- replicator.log_replication_outcome :ignore, diff
150
- helper.stub!(:options_for_table).and_return({:logged_replication_events => [:ignored_conflicts]})
151
- replicator.log_replication_outcome :left, diff
152
-
153
- # should log ignored conflicts correctly
154
- helper = ReplicationHelper.new(rep_run)
155
- replicator = Replicators::TwoWayReplicator.new(helper)
156
- helper.should_receive(:log_replication_outcome).with(diff, 'ignored')
157
- helper.stub!(:options_for_table).and_return({:logged_replication_events => [:ignored_conflicts]})
158
- replicator.log_replication_outcome :ignore, diff
159
-
160
- # should log conflicts correctly
161
- helper = ReplicationHelper.new(rep_run)
162
- replicator = Replicators::TwoWayReplicator.new(helper)
163
- helper.should_receive(:log_replication_outcome).with(diff, 'left_won')
164
- helper.stub!(:options_for_table).and_return({:logged_replication_events => [:all_conflicts]})
165
- replicator.log_replication_outcome :left, diff
166
- end
167
-
168
- it "log_replication_outcome should log changes correctly" do
169
- session = Session.new
170
- rep_run = ReplicationRun.new(session, TaskSweeper.new(1))
171
-
172
- loaders = LoggedChangeLoaders.new(session)
173
-
174
- diff = ReplicationDifference.new loaders
175
- diff.type = :left
176
- diff.changes[:left] = LoggedChange.new loaders[:left]
177
- diff.changes[:left].table = 'scanner_records'
178
-
179
- # should only log events if so configured
180
- helper = ReplicationHelper.new(rep_run)
181
- replicator = Replicators::TwoWayReplicator.new(helper)
182
- helper.should_not_receive(:log_replication_outcome)
183
- helper.stub!(:options_for_table).and_return({:logged_replication_events => []})
184
- replicator.log_replication_outcome :ignore, diff
185
- helper.stub!(:options_for_table).and_return({:logged_replication_events => [:ignored_changes]})
186
- replicator.log_replication_outcome :left, diff
187
-
188
- # should log changes correctly
189
- helper = ReplicationHelper.new(rep_run)
190
- replicator = Replicators::TwoWayReplicator.new(helper)
191
- helper.should_receive(:log_replication_outcome).with(diff, 'replicated')
192
- helper.stub!(:options_for_table).and_return({:logged_replication_events => [:all_changes]})
193
- replicator.log_replication_outcome :right, diff
194
-
195
- # should log changes correctly
196
- helper = ReplicationHelper.new(rep_run)
197
- replicator = Replicators::TwoWayReplicator.new(helper)
198
- helper.should_receive(:log_replication_outcome).with(diff, 'ignored')
199
- helper.stub!(:options_for_table).and_return({:logged_replication_events => [:ignored_changes]})
200
- replicator.log_replication_outcome :ignore, diff
201
- end
202
-
203
- it "replicate_difference should not do anything if ignore option is given" do
204
- session = Session.new
205
- rep_run = ReplicationRun.new(session, TaskSweeper.new(1))
206
- helper = ReplicationHelper.new(rep_run)
207
- replicator = Replicators::TwoWayReplicator.new(helper)
208
- helper.stub!(:options_for_table).and_return(
209
- {
210
- :left_change_handling => :ignore,
211
- :right_change_handling => :ignore,
212
- :replication_conflict_handling => :ignore,
213
- :logged_replication_events => [:ignored_changes, :ignored_conflicts]
214
- }
215
- )
216
-
217
- loaders = LoggedChangeLoaders.new(session)
218
-
219
- diff = ReplicationDifference.new(loaders)
220
- diff.changes[:left] = LoggedChange.new loaders[:left]
221
- diff.changes[:left].table = 'scanner_records'
222
-
223
- # but logging should still happen
224
- replicator.should_receive(:log_replication_outcome).
225
- with(:ignore, diff).
226
- exactly(3).times
227
-
228
- helper.should_not_receive :insert_record
229
- helper.should_not_receive :update_record
230
- helper.should_not_receive :delete_record
231
-
232
- diff.type = :conflict
233
- replicator.replicate_difference diff
234
- diff.type = :left
235
- replicator.replicate_difference diff
236
- diff.type = :right
237
- replicator.replicate_difference diff
238
- end
239
-
240
- it "replicate_difference should call the provided Proc objects" do
241
- session = Session.new
242
- rep_run = ReplicationRun.new(session, TaskSweeper.new(1))
243
- helper = ReplicationHelper.new(rep_run)
244
-
245
- lambda_parameters = []
246
- l = lambda do |rep_helper, diff|
247
- lambda_parameters << [rep_helper, diff]
248
- end
249
- replicator = Replicators::TwoWayReplicator.new(helper)
250
- helper.stub!(:options_for_table).and_return(
251
- {
252
- :left_change_handling => l,
253
- :right_change_handling => l,
254
- :replication_conflict_handling => l
255
- }
256
- )
257
-
258
- loaders = LoggedChangeLoaders.new(session)
259
-
260
- change = LoggedChange.new loaders[:left]
261
- change.table = 'scanner_records'
262
-
263
- d1 = ReplicationDifference.new(loaders)
264
- d1.type = :conflict
265
- d1.changes[:left] = change
266
- replicator.replicate_difference d1
267
-
268
- d2 = ReplicationDifference.new(loaders)
269
- d2.type = :left
270
- d2.changes[:left] = change
271
- replicator.replicate_difference d2
272
-
273
- d3 = ReplicationDifference.new(loaders)
274
- d3.type = :right
275
- d3.changes[:left] = change
276
- replicator.replicate_difference d3
277
-
278
- lambda_parameters.should == [
279
- [helper, d1],
280
- [helper, d2],
281
- [helper, d3],
282
- ]
283
- end
284
-
285
- it "replicate_difference should clear conflicts as per provided options" do
286
- session = Session.new
287
- rep_run = ReplicationRun.new(session, TaskSweeper.new(1))
288
- helper = ReplicationHelper.new(rep_run)
289
-
290
- left_change = LoggedChange.new LoggedChangeLoader.new(session, :left)
291
- left_change.table = 'scanner_records'
292
- right_change = LoggedChange.new LoggedChangeLoader.new(session, :right)
293
- right_change.table = 'scanner_records'
294
- diff = ReplicationDifference.new(session)
295
- diff.type = :conflict
296
- diff.changes[:left] = left_change
297
- diff.changes[:right] = right_change
298
-
299
- replicator = Replicators::TwoWayReplicator.new(helper)
300
- helper.stub!(:options_for_table).and_return({:replication_conflict_handling => :left_wins})
301
- replicator.should_receive(:clear_conflict).with(:left, diff, 1)
302
- replicator.replicate_difference diff, 1
303
-
304
- replicator = Replicators::TwoWayReplicator.new(helper)
305
- helper.stub!(:options_for_table).and_return({:replication_conflict_handling => :right_wins})
306
- replicator.should_receive(:clear_conflict).with(:right, diff, 1)
307
- replicator.replicate_difference diff, 1
308
-
309
- replicator = Replicators::TwoWayReplicator.new(helper)
310
- helper.stub!(:options_for_table).and_return({:replication_conflict_handling => :later_wins})
311
- replicator.should_receive(:clear_conflict).with(:left, diff, 1).twice
312
- left_change.last_changed_at = 5.seconds.from_now
313
- right_change.last_changed_at = Time.now
314
- replicator.replicate_difference diff, 1
315
- left_change.last_changed_at = right_change.last_changed_at = Time.now
316
- replicator.replicate_difference diff, 1
317
- replicator.should_receive(:clear_conflict).with(:right, diff, 1)
318
- right_change.last_changed_at = 5.seconds.from_now
319
- replicator.replicate_difference diff, 1
320
-
321
- replicator = Replicators::TwoWayReplicator.new(helper)
322
- helper.stub!(:options_for_table).and_return({:replication_conflict_handling => :earlier_wins})
323
- replicator.should_receive(:clear_conflict).with(:left, diff, 1).twice
324
- left_change.last_changed_at = 5.seconds.ago
325
- right_change.last_changed_at = Time.now
326
- replicator.replicate_difference diff, 1
327
- left_change.last_changed_at = right_change.last_changed_at = Time.now
328
- replicator.replicate_difference diff, 1
329
- replicator.should_receive(:clear_conflict).with(:right, diff, 1)
330
- right_change.last_changed_at = 5.seconds.ago
331
- replicator.replicate_difference diff, 1
332
- end
333
-
334
- it "replicate_difference should replicate :left / :right changes correctly" do
335
- Initializer.configuration.include_tables 'left_table, right_table'
336
- session = Session.new
337
- session.left.begin_db_transaction
338
- session.right.begin_db_transaction
339
- begin
340
- rep_run = ReplicationRun.new(session, TaskSweeper.new(1))
341
-
342
- left_change = LoggedChange.new LoggedChangeLoader.new(session, :left)
343
- left_change.table = 'left_table'
344
- left_change.key = {'id' => '1'}
345
- right_change = LoggedChange.new LoggedChangeLoader.new(session, :right)
346
- right_change.table = 'right_table'
347
- right_change.key = {'id' => '1'}
348
-
349
- diff = ReplicationDifference.new(session)
350
-
351
- # verify insert behaviour
352
- left_change.type = :insert
353
- diff.type = :left
354
- diff.changes[:left] = left_change
355
- diff.changes[:right] = nil
356
-
357
- helper = ReplicationHelper.new(rep_run)
358
- replicator = Replicators::TwoWayReplicator.new(helper)
359
- replicator.should_receive(:log_replication_outcome).with(:left, diff)
360
- helper.should_receive(:load_record).with(:left, 'left_table', {'id' => '1'}).
361
- and_return(:dummy_values)
362
- helper.should_receive(:insert_record).with(:right, 'right_table', :dummy_values)
363
- replicator.replicate_difference diff
364
-
365
- # verify update behaviour
366
- right_change.type = :update
367
- right_change.new_key = {'id' => '2'}
368
- diff.type = :right
369
- diff.changes[:right] = right_change
370
-
371
- helper = ReplicationHelper.new(rep_run)
372
- replicator = Replicators::TwoWayReplicator.new(helper)
373
- replicator.should_receive(:log_replication_outcome).with(:right, diff)
374
- helper.should_receive(:load_record).with(:right, 'right_table', {'id' => '2'}).
375
- and_return(:dummy_values)
376
- helper.should_receive(:update_record).with(:left, 'left_table', :dummy_values, {'id' => '1'})
377
- replicator.replicate_difference diff
378
-
379
- # verify delete behaviour
380
- right_change.type = :delete
381
-
382
- helper = ReplicationHelper.new(rep_run)
383
- replicator = Replicators::TwoWayReplicator.new(helper)
384
- replicator.should_receive(:log_replication_outcome).with(:right, diff)
385
- helper.should_receive(:delete_record).with(:left, 'left_table', {'id' => '1'})
386
- replicator.replicate_difference diff
387
- ensure
388
- session.left.rollback_db_transaction
389
- session.right.rollback_db_transaction
390
- end
391
- end
392
-
393
- it "replicate_difference should handle inserts failing due duplicate records getting created after the original diff was loaded" do
394
- begin
395
- config = deep_copy(standard_config)
396
- config.options[:committer] = :never_commit
397
- config.options[:replication_conflict_handling] = :right_wins
398
-
399
- session = Session.new(config)
400
-
401
- session.left.insert_record 'extender_no_record', {
402
- 'id' => '1',
403
- 'name' => 'bla'
404
- }
405
- session.left.insert_record 'rr_pending_changes', {
406
- 'change_table' => 'extender_no_record',
407
- 'change_key' => 'id|1',
408
- 'change_type' => 'I',
409
- 'change_time' => Time.now
410
- }
411
-
412
-
413
- rep_run = ReplicationRun.new session, TaskSweeper.new(1)
414
- helper = ReplicationHelper.new(rep_run)
415
- replicator = Replicators::TwoWayReplicator.new(helper)
416
-
417
- diff = ReplicationDifference.new LoggedChangeLoaders.new(session)
418
- diff.load
419
-
420
- session.right.insert_record 'extender_no_record', {
421
- 'id' => '1',
422
- 'name' => 'blub'
423
- }
424
- session.right.insert_record 'rr_pending_changes', {
425
- 'change_table' => 'extender_no_record',
426
- 'change_key' => 'id|1',
427
- 'change_type' => 'I',
428
- 'change_time' => Time.now
429
- }
430
- replicator.replicate_difference diff, 2
431
-
432
- session.left.select_record(:table => "extender_no_record").should == {
433
- 'id' => 1,
434
- 'name' => 'blub'
435
- }
436
- ensure
437
- Committers::NeverCommitter.rollback_current_session
438
- if session
439
- session.left.execute "delete from extender_no_record"
440
- session.right.execute "delete from extender_no_record"
441
- session.left.execute "delete from rr_pending_changes"
442
- end
443
- end
444
- end
445
-
446
- it "replicate_difference should handle inserts failing due the new record being deleted after the original diff was loaded" do
447
- begin
448
- config = deep_copy(standard_config)
449
- config.options[:committer] = :never_commit
450
-
451
- session = Session.new(config)
452
-
453
- session.left.insert_record 'rr_pending_changes', {
454
- 'change_table' => 'extender_no_record',
455
- 'change_key' => 'id|1',
456
- 'change_type' => 'I',
457
- 'change_time' => Time.now
458
- }
459
-
460
- rep_run = ReplicationRun.new session, TaskSweeper.new(1)
461
- helper = ReplicationHelper.new(rep_run)
462
- replicator = Replicators::TwoWayReplicator.new(helper)
463
-
464
- diff = ReplicationDifference.new LoggedChangeLoaders.new(session)
465
- diff.load
466
-
467
- session.left.insert_record 'rr_pending_changes', {
468
- 'change_table' => 'extender_no_record',
469
- 'change_key' => 'id|1',
470
- 'change_type' => 'D',
471
- 'change_time' => Time.now
472
- }
473
- replicator.replicate_difference diff, 2
474
-
475
- # no rspec expectation: success is when we get till here without exception
476
- ensure
477
- Committers::NeverCommitter.rollback_current_session
478
- session.left.execute "delete from rr_pending_changes" if session
479
- end
480
- end
481
-
482
- it "replicate_difference should raise Exception if all replication attempts have been exceeded" do
483
- rep_run = ReplicationRun.new Session.new, TaskSweeper.new(1)
484
- helper = ReplicationHelper.new(rep_run)
485
- replicator = Replicators::TwoWayReplicator.new(helper)
486
- lambda {replicator.replicate_difference :dummy_diff, 0}.
487
- should raise_error(Exception, "max replication attempts exceeded")
488
- end
489
-
490
- it "replicate_difference should handle updates rejected by the database" do
491
- begin
492
- config = deep_copy(standard_config)
493
- config.options[:committer] = :never_commit
494
- config.options[:replication_conflict_handling] = :left_wins
495
-
496
- session = Session.new(config)
497
- session.left.execute "delete from rr_logged_events"
498
-
499
- session.left.insert_record 'rr_pending_changes', {
500
- 'change_table' => 'scanner_records',
501
- 'change_key' => 'id|1',
502
- 'change_new_key' => 'id|2',
503
- 'change_type' => 'U',
504
- 'change_time' => Time.now
505
- }
506
-
507
- rep_run = ReplicationRun.new session, TaskSweeper.new(1)
508
- helper = ReplicationHelper.new(rep_run)
509
- replicator = Replicators::TwoWayReplicator.new(helper)
510
-
511
- diff = ReplicationDifference.new LoggedChangeLoaders.new(session)
512
- diff.load
513
-
514
- lambda {replicator.replicate_difference diff, 1}.should raise_error(/duplicate/i)
515
-
516
- # Verify that the transaction has not become invalid
517
- helper.log_replication_outcome diff, "bla", "blub"
518
-
519
- row = session.left.select_one("select * from rr_logged_events")
520
- row['change_table'].should == 'scanner_records'
521
- row['change_key'].should == '1'
522
- row['description'].should == 'bla'
523
-
524
- ensure
525
- Committers::NeverCommitter.rollback_current_session
526
- if session
527
- session.left.execute "delete from rr_pending_changes"
528
- session.left.execute "delete from rr_logged_events"
529
- end
530
- end
531
- end
532
-
533
- it "replicate_difference should handle deletes rejected by the database" do
534
- begin
535
- config = deep_copy(standard_config)
536
- config.options[:committer] = :never_commit
537
- config.options[:replication_conflict_handling] = :left_wins
538
-
539
- session = Session.new(config)
540
-
541
- session.left.select_all("select * from rr_logged_events").should == []
542
-
543
- session.left.insert_record 'rr_pending_changes', {
544
- 'change_table' => 'referenced_table',
545
- 'change_key' => 'first_id|1|second_id|2',
546
- 'change_new_key' => nil,
547
- 'change_type' => 'D',
548
- 'change_time' => Time.now
549
- }
550
-
551
- rep_run = ReplicationRun.new session, TaskSweeper.new(1)
552
- helper = ReplicationHelper.new(rep_run)
553
- replicator = Replicators::TwoWayReplicator.new(helper)
554
-
555
- diff = ReplicationDifference.new LoggedChangeLoaders.new(session)
556
- diff.load
557
-
558
- lambda {replicator.replicate_difference diff, 1}.should raise_error(/referencing_table_fkey/)
559
-
560
- # Verify that the transaction has not become invalid
561
- helper.log_replication_outcome diff, "bla", "blub"
562
-
563
- row = session.left.select_one("select * from rr_logged_events")
564
- row['change_table'].should == 'referenced_table'
565
- row['change_key'].should =~ /first_id.*1.*second_id.*2/
566
- row['description'].should == 'bla'
567
-
568
- ensure
569
- Committers::NeverCommitter.rollback_current_session
570
- if session
571
- session.left.execute "delete from rr_pending_changes"
572
- session.left.execute "delete from rr_logged_events"
573
- end
574
- end
575
- end
576
-
577
- it "replicate_difference should handle deletes failing due to the target record vanishing" do
578
- begin
579
- config = deep_copy(standard_config)
580
- config.options[:committer] = :never_commit
581
- config.options[:replication_conflict_handling] = :left_wins
582
-
583
- session = Session.new(config)
584
-
585
- session.left.insert_record 'rr_pending_changes', {
586
- 'change_table' => 'scanner_records',
587
- 'change_key' => 'id|3',
588
- 'change_new_key' => nil,
589
- 'change_type' => 'D',
590
- 'change_time' => Time.now
591
- }
592
-
593
- rep_run = ReplicationRun.new session, TaskSweeper.new(1)
594
- helper = ReplicationHelper.new(rep_run)
595
- replicator = Replicators::TwoWayReplicator.new(helper)
596
-
597
- diff = ReplicationDifference.new LoggedChangeLoaders.new(session)
598
- diff.load
599
-
600
- session.right.insert_record 'rr_pending_changes', {
601
- 'change_table' => 'scanner_records',
602
- 'change_key' => 'id|3',
603
- 'change_new_key' => 'id|4',
604
- 'change_type' => 'U',
605
- 'change_time' => Time.now
606
- }
607
-
608
- replicator.replicate_difference diff, 2
609
-
610
- session.right.select_one("select * from scanner_records where id = 4").
611
- should be_nil
612
- ensure
613
- Committers::NeverCommitter.rollback_current_session
614
- if session
615
- session.left.execute "delete from rr_pending_changes"
616
- session.left.execute "delete from rr_logged_events"
617
- end
618
- end
619
- end
620
-
621
- it "replicate_difference should handle updates failing due to the source record being deleted after the original diff was loaded" do
622
- begin
623
- config = deep_copy(standard_config)
624
- config.options[:committer] = :never_commit
625
- config.options[:replication_conflict_handling] = :left_wins
626
-
627
- session = Session.new(config)
628
-
629
- session.left.insert_record 'extender_no_record', {
630
- 'id' => '2',
631
- 'name' => 'bla'
632
- }
633
- session.right.insert_record 'extender_no_record', {
634
- 'id' => '2',
635
- 'name' => 'blub'
636
- }
637
- session.left.insert_record 'rr_pending_changes', {
638
- 'change_table' => 'extender_no_record',
639
- 'change_key' => 'id|1',
640
- 'change_new_key' => 'id|2',
641
- 'change_type' => 'U',
642
- 'change_time' => Time.now
643
- }
644
-
645
- rep_run = ReplicationRun.new session, TaskSweeper.new(1)
646
- helper = ReplicationHelper.new(rep_run)
647
- replicator = Replicators::TwoWayReplicator.new(helper)
648
-
649
- diff = ReplicationDifference.new LoggedChangeLoaders.new(session)
650
- diff.load
651
-
652
- session.left.delete_record 'extender_no_record', {'id' => '2'}
653
-
654
- session.left.insert_record 'rr_pending_changes', {
655
- 'change_table' => 'extender_no_record',
656
- 'change_key' => 'id|2',
657
- 'change_type' => 'D',
658
- 'change_time' => Time.now
659
- }
660
- replicator.replicate_difference diff, 2
661
-
662
- session.right.select_one("select * from extender_no_record").should be_nil
663
- ensure
664
- Committers::NeverCommitter.rollback_current_session
665
- if session
666
- session.left.execute "delete from extender_no_record"
667
- session.right.execute "delete from extender_no_record"
668
- session.left.execute "delete from rr_pending_changes"
669
- end
670
- end
671
- end
672
-
673
- it "replicate_difference should handle updates failing due to the target record being deleted after the original diff was loaded" do
674
- begin
675
- config = deep_copy(standard_config)
676
- config.options[:committer] = :never_commit
677
- config.options[:replication_conflict_handling] = :left_wins
678
-
679
- session = Session.new(config)
680
-
681
- session.left.insert_record 'extender_no_record', {
682
- 'id' => '2',
683
- 'name' => 'bla'
684
- }
685
- session.left.insert_record 'rr_pending_changes', {
686
- 'change_table' => 'extender_no_record',
687
- 'change_key' => 'id|1',
688
- 'change_new_key' => 'id|2',
689
- 'change_type' => 'U',
690
- 'change_time' => Time.now
691
- }
692
-
693
- rep_run = ReplicationRun.new session, TaskSweeper.new(1)
694
- helper = ReplicationHelper.new(rep_run)
695
- replicator = Replicators::TwoWayReplicator.new(helper)
696
-
697
- diff = ReplicationDifference.new LoggedChangeLoaders.new(session)
698
- diff.load
699
-
700
- session.right.insert_record 'rr_pending_changes', {
701
- 'change_table' => 'extender_no_record',
702
- 'change_key' => 'id|1',
703
- 'change_type' => 'D',
704
- 'change_time' => Time.now
705
- }
706
- replicator.replicate_difference diff, 2
707
-
708
- session.right.select_record(:table => "extender_no_record").should == {
709
- 'id' => 2,
710
- 'name' => 'bla'
711
- }
712
- ensure
713
- Committers::NeverCommitter.rollback_current_session
714
- if session
715
- session.left.execute "delete from extender_no_record"
716
- session.right.execute "delete from extender_no_record"
717
- session.left.execute "delete from rr_pending_changes"
718
- end
719
- end
720
- end
721
- end