flydata 0.7.15 → 0.7.16

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5435f4af64a22277e8417bbdd7196ee8aabc6c19
4
- data.tar.gz: 7bbbff8d0c4cb13891f35dc8debf891b2aa31953
3
+ metadata.gz: aafcbf0332b985cd94a8fa83302bbccdb5ef86f1
4
+ data.tar.gz: f6842935284bacbd7cc5046f640c65c376b28bfb
5
5
  SHA512:
6
- metadata.gz: 646f5ec5b0f3be8102a80c386291c95b6ad220c3e3401b89acea12ab7b59179b3a806fdfc67c403f9ed44d4a08a7080a49f48528109257faad2c1c3cd9fd84f2
7
- data.tar.gz: 179efaee49c60d6573da9b0f6f57476fc8ae26f43ab70bee591f174fec5ba09b90d5a6c4ea2cf95f91417d73f8144d89ae2a568457b28d2034c9479eb629bc17
6
+ metadata.gz: 8f6ef145d7f026237e35dd351f306b815a901e654a3fa67bc1ddd251fcad5fbc003c5780e2b93260f670f3692efcf78160c8ea688466f70eea91ebe12a3ade8d
7
+ data.tar.gz: 268449b51660a61f40aa8a731107630c2876c41b656ef4063b2eb41b925162d942c2963017d15a83d91dd78366cacc698d3c8c51d43bc6e2af5fe55b7865d0e4
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.7.15
1
+ 0.7.16
@@ -275,6 +275,9 @@ EOS
275
275
  # strip outer single-quotes
276
276
  default_value = $1 if /^'(.*)'$/m.match(default_value)
277
277
  end
278
+ if default_value.kind_of?(String) &&/^NULL$/i.match(default_value)
279
+ return NULL_STR
280
+ end
278
281
  if flydata_type.start_with?('year')
279
282
  value = convert_year_into_date(remove_single_quote(default_value))
280
283
  begin
@@ -420,6 +420,13 @@ EOT
420
420
  let(:default_value_sql) { "'0001-01-01 00:00:00.000000'" }
421
421
  it_behaves_like *examples
422
422
  end
423
+
424
+ context 'when default_value has PostgreSQL-style NULL with cast' do
425
+ let(:default_value) { "NULL::timestamp without time zone" }
426
+ let(:default_value_sql) { "NULL" }
427
+
428
+ it_behaves_like *examples
429
+ end
423
430
  end
424
431
 
425
432
  context 'with datetimetz column def' do
@@ -548,6 +555,18 @@ EOT
548
555
 
549
556
  it_behaves_like *examples
550
557
  end
558
+
559
+ context 'when default_value has PostgreSQL-style NULL with cast' do
560
+ let(:default_value) { "NULL::numeric" }
561
+ let(:default_value_sql) { "NULL" }
562
+ before do
563
+ column[:column] = "value"
564
+ column[:type] = "numeric(28,2)"
565
+ end
566
+ let(:type_sql) { %Q|"value" numeric(28,2)| }
567
+
568
+ it_behaves_like *examples
569
+ end
551
570
  end
552
571
 
553
572
  context 'with bit column def' do
data/flydata.gemspec CHANGED
Binary file
@@ -341,7 +341,7 @@ EOS
341
341
  message += "\n"
342
342
  end
343
343
  if pos_mismatch_tables
344
- message += " - Incorrect table position(s)\n"
344
+ message += " - Incorrect table position. This may not be a real issue, caused by pending upload chunks. Run sync:flush and try again.\n"
345
345
  pos_mismatch_tables.each do |bt|
346
346
  message += " table:#{bt[:table]}, agent position:#{bt[:agent_seq] ? bt[:agent_seq] : '(missing)'}, server position:#{bt[:server_seq]}\n"
347
347
  end
@@ -389,7 +389,8 @@ EOS
389
389
  # to wait, but there *are* cases where active data processing takes
390
390
  # more than 3 minutes between 2 chunk processing if COPY command
391
391
  # takes minutes to process.
392
- flush_buffer_and_stop(@full_tables, force: false, timeout: 180)
392
+ flush_buffer_and_stop(@full_tables, force: false, timeout: 180,
393
+ dont_wait_upload: true)
393
394
  rescue ServerDataProcessingTimeout => e
394
395
  data_stuck_at = e.state
395
396
  end
@@ -468,13 +469,28 @@ EOS
468
469
  return true
469
470
  end
470
471
 
471
- gt = []
472
- pt = []
473
- gt = gap_tables.collect{|bt| bt[:table] } if gap_tables
474
- pt = pos_mismatch_tables.collect{|bt| bt[:table] } if pos_mismatch_tables
475
- # position mismatch can be due to query queue items discarded by the copy handler
476
- # so it also needs to be in the target table list.
477
- tables = gt | pt
472
+ if corrupt_master_pos_files
473
+ # TODO This case can be repaied by implementing the following steps.
474
+ # 1. Flush all pending data (buffer & query queue items) except for
475
+ # ones blocked by a gap.
476
+ # 2. Pick the latest src_pos value from table_status and put as the
477
+ # sent.pos.
478
+ # 3. Rerun sync:repair
479
+ #
480
+ log_info_stdout ""
481
+ log_info_stdout "Master position file(s) is broken. Full sync reset is necessary to solve the issue."
482
+ return false
483
+ end
484
+
485
+ broken_tables = []
486
+ broken_tables = gap_tables.collect{|bt| bt[:table] } if gap_tables
487
+
488
+ if broken_tables.empty? && !corrupt_master_pos_files &&
489
+ !status.include?(:ABNORMAL_SHUTDOWN)
490
+ log_info_stdout ""
491
+ log_info_stdout "Sync is in good condition. Nothing to repair."
492
+ return true
493
+ end
478
494
 
479
495
  # table_status will be created at the end of initial sync.
480
496
  # ignore tables that have no table_status, i.e. tables never got init-synced before.
@@ -485,14 +501,9 @@ EOS
485
501
  The following issues have been found and will be repaired.
486
502
 
487
503
  EOS
488
- log_info_stdout <<EOS unless tables.empty?
504
+ log_info_stdout <<EOS unless broken_tables.empty?
489
505
  - Sync is broken due to missing data for the following tables
490
- #{tables.join("\n ")}
491
-
492
- EOS
493
- log_info_stdout <<EOS if corrupt_master_pos_files
494
- - Sync is broken due to corrupt master position files
495
- #{corrupt_master_pos_files.join("\n ")}
506
+ #{broken_tables.join("\n ")}
496
507
 
497
508
  EOS
498
509
  log_info_stdout <<EOS if status.include? :ABNORMAL_SHUTDOWN
@@ -516,25 +527,12 @@ EOS
516
527
  # the table status has no src_pos (which is rare.) Skip the table
517
528
  next
518
529
  end
519
- if tables.empty?
520
- # Find the latest source pos to which all table data is up to date
521
- if table_status_hash[table]["seq"] == 0
522
- # this table's source pos is from the initial sync. It can't
523
- # be used for determining the latest source pos because it can be
524
- # newer than the correct cont sync source pos.
525
- next
526
- end
527
- if sent_source_pos.nil? || sent_source_pos < table_source_pos
528
- sent_source_pos = table_source_pos
529
- end
530
- else
531
- if tables.include?(table)
532
- if sent_source_pos.nil? || sent_source_pos > table_source_pos
533
- if oldest_source_pos && table_source_pos < oldest_source_pos
534
- unrepairable_tables << table
535
- else
536
- sent_source_pos = table_source_pos
537
- end
530
+ if broken_tables.include?(table)
531
+ if sent_source_pos.nil? || sent_source_pos > table_source_pos
532
+ if oldest_source_pos && table_source_pos < oldest_source_pos
533
+ unrepairable_tables << table
534
+ else
535
+ sent_source_pos = table_source_pos
538
536
  end
539
537
  end
540
538
  end
@@ -561,30 +559,26 @@ EOS
561
559
  end
562
560
  master_source_pos = context.resume_pos(sent_source_pos)
563
561
 
564
- # Delete agent buffer
565
- log_info_stdout "Deleting data in the agent buffer..."
566
- files = Flydata::Agent.new(FLYDATA_HOME).delete_buffer_files
567
- unless files.empty?
568
- $log.debug "Deleted buffer files\n " + files.join("\n ")
569
- end
570
-
571
562
  # Delete query queue items for the tables
572
563
  log_info_stdout "Deleting data stuck in the server buffer..."
573
- cleanup_sync_server(de, tables, queue_only: true) unless tables.empty?
564
+ cleanup_sync_server(de, broken_tables, queue_only: true) unless broken_tables.empty?
574
565
 
575
566
  # Save the positions (source_pos and seq)
576
567
  log_info_stdout "Fixing table positions..."
577
568
  synced_tables.each do |table|
578
- table_source_pos = table_status_hash[table]["source_pos"]
579
- if table_source_pos.nil? || table_source_pos.empty?
580
- # no init sync has happened to the table. No need to set positions.
581
- next
582
- end
583
- pos = table_status_hash[table]["seq"]
584
- old_source_pos, old_pos = save_table_positions(table, table_source_pos, pos, context)
585
- if pos.to_i != old_pos.to_i && !tables.include?(table)
586
- $log.debug "Fixed broken table position. table:#{table} pos:#{old_pos} -> #{pos}"
587
- end
569
+ if broken_tables.include?(table)
570
+ table_source_pos = table_status_hash[table]["source_pos"]
571
+ if table_source_pos.nil? || table_source_pos.empty?
572
+ # no init sync has happened to the table. No need to set positions.
573
+ next
574
+ end
575
+ pos = table_status_hash[table]["seq"]
576
+ else
577
+ # use "default" positions supplied by #save_table_positions
578
+ table_source_pos = nil
579
+ pos = nil
580
+ end
581
+ old_source_pos, old_pos = save_table_positions(table, table_source_pos, pos, context)
588
582
  end
589
583
 
590
584
  log_info_stdout "Fixing the master position files..."
@@ -1070,6 +1064,10 @@ EOM
1070
1064
  break
1071
1065
  end
1072
1066
 
1067
+ if state == :UPLOAD && option[:dont_wait_upload]
1068
+ break
1069
+ end
1070
+
1073
1071
  if status['message'] != prev_message
1074
1072
  # making some progress. Reset timer
1075
1073
  start_time = Time.now
@@ -1081,7 +1079,7 @@ EOM
1081
1079
  print_progress(status)
1082
1080
  sleep 10
1083
1081
  end
1084
- if (state == :PROCESS)
1082
+ if state == :PROCESS && !option[:dont_wait_upload]
1085
1083
  # :UPLOAD state was skipped due to no data
1086
1084
  log_info_stdout(" -> Done")
1087
1085
  log_info_stdout("Finishing data upload...")
@@ -1312,7 +1310,8 @@ Thank you for using FlyData!
1312
1310
 
1313
1311
  timeout = options.has_key?(:timeout) ? options[:timeout]
1314
1312
  : SERVER_DATA_PROCESSING_TIMEOUT
1315
- wait_for_server_data_processing( timeout: timeout, tables: tables)
1313
+ wait_for_server_data_processing(timeout: timeout, tables: tables,
1314
+ dont_wait_upload: options[:dont_wait_upload])
1316
1315
  end
1317
1316
 
1318
1317
  # Utility methods
@@ -1459,8 +1458,17 @@ Thank you for using FlyData!
1459
1458
  def save_table_positions(table, source_pos, pos, context)
1460
1459
  de = data_entry
1461
1460
  sync_fm = create_sync_file_manager(de)
1461
+
1462
+ master_sent_source_pos = sync_fm.load_sent_source_pos
1462
1463
  old_source_pos = sync_fm.get_table_source_pos(table)
1463
1464
  old_pos = sync_fm.get_table_position(table)
1465
+
1466
+ source_pos ||= old_source_pos
1467
+ source_pos ||= master_sent_source_pos
1468
+ raise "master sent source pos is missing" unless source_pos
1469
+ pos ||= old_pos
1470
+ raise "table pos is missing for table '#{table}'" unless pos
1471
+
1464
1472
  if pos.to_i != old_pos.to_i
1465
1473
  sync_fm.save_table_position(table, pos)
1466
1474
  $log.debug "table pos updated. table:#{table} pos:#{old_pos} -> #{pos}"
@@ -32,6 +32,7 @@ class PostgresqlQueryBasedFlydataInput < Input
32
32
  tag: @tag, sync_fm: @sync_fm, omit_events: @omit_events,
33
33
  table_revs: @table_revs, dbconf: @dbconf,
34
34
  cur_src_pos_file: @source_position_file,
35
+ cur_sent_pos_file: @sent_position_file,
35
36
  table_src_pos_files: @table_src_pos_files,
36
37
  table_meta: @table_meta,
37
38
  params: {
@@ -0,0 +1,13 @@
1
+ require 'flydata/helper/action/agent_action'
2
+
3
+ module Flydata
4
+ module Helper
5
+ module Action
6
+ class Repair < AgentAction
7
+ def command
8
+ "sync:repair -y"
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -48,6 +48,7 @@ module Flydata
48
48
  self.new(:stop_agent, true, Action::StopAgent),
49
49
  self.new(:restart_agent, true, Action::RestartAgent),
50
50
  self.new(:update_helper_config, false, Action::UpdateHelperConfig),
51
+ self.new(:repair, true, Action::Repair),
51
52
  ].inject({}) do |h, action|
52
53
  h[action.action_name] = action
53
54
  h
@@ -36,6 +36,7 @@ module PluginSupport
36
36
  :table_meta
37
37
 
38
38
  register_optional_opts :cur_src_pos_file,
39
+ :cur_sent_pos_file,
39
40
  :table_src_pos_files,
40
41
  :params
41
42
 
@@ -101,6 +101,9 @@ module QueryBasedSync
101
101
 
102
102
  # Set the current snapshot to master(resume) binlog.pos file
103
103
  context.cur_src_pos_file.save(context.table_meta.current_snapshot)
104
+ # Also set the same value to the sent.binlog.pos file as the file is
105
+ # required by the agent commands.
106
+ context.cur_sent_pos_file.save(context.table_meta.current_snapshot)
104
107
 
105
108
  log_info("Updated source position -", resume_pos:context.table_meta.current_snapshot)
106
109
  end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+ require_relative '../helper_shared_context'
3
+ require 'flydata/helper/action/repair'
4
+
5
+ module Flydata
6
+ module Helper
7
+ module Action
8
+ describe Repair do
9
+ include_context 'helper context'
10
+
11
+ describe "#execute" do
12
+ subject { described_class.new(config).execute }
13
+ it "executes the repair action" do
14
+ expect(Open3).to receive(:capture3).with({}, "flydata sync:repair -y")
15
+ subject
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -36,13 +36,13 @@ module Flydata
36
36
  describe '.action_ownership_map' do
37
37
  subject { described_class.action_ownership_map }
38
38
  it do
39
- expect(subject.size).to eq(6)
40
39
  expect(subject.include?(:check_remote_actions)).to be(true)
41
40
  expect(subject.include?(:check_abnormal_shutdown)).to be(true)
42
41
  expect(subject.include?(:send_logs)).to be(true)
43
42
  expect(subject.include?(:stop_agent)).to be(true)
44
43
  expect(subject.include?(:restart_agent)).to be(true)
45
44
  expect(subject.include?(:update_helper_config)).to be(true)
45
+ expect(subject.include?(:repair)).to be(true)
46
46
  end
47
47
  end
48
48
  end
@@ -69,12 +69,14 @@ shared_context 'query based sync context' do
69
69
  ]
70
70
  } }
71
71
  let(:cur_src_pos_file) { double('cur_src_pos_file') }
72
+ let(:cur_sent_pos_file) { double('cur_sent_pos_file') }
72
73
  let(:table_1_src_pos_file) { double('table_1_src_pos_file') }
73
74
  let(:table_2_src_pos_file) { double('table_2_src_pos_file') }
74
75
  let(:table_3_src_pos_file) { double('table_3_src_pos_file') }
75
76
  let(:context) {
76
77
  Flydata::PluginSupport::Context.new(
77
78
  cur_src_pos_file: cur_src_pos_file,
79
+ cur_sent_pos_file: cur_sent_pos_file,
78
80
  tables: %w(table_1 table_2 table_3),
79
81
  tag: 'test_tag',
80
82
  sync_fm: sync_fm,
@@ -107,6 +109,7 @@ shared_context 'query based sync context' do
107
109
  allow(table_meta).to receive(:[]).with(:table_1).and_return(table_meta_1)
108
110
  allow(table_meta).to receive(:current_snapshot).and_return(current_snapshot)
109
111
  allow(cur_src_pos_file).to receive(:save).with(current_snapshot)
112
+ allow(cur_sent_pos_file).to receive(:save).with(current_snapshot)
110
113
  setup_dummy_objects
111
114
  end
112
115
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flydata
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.15
4
+ version: 0.7.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Koichi Fujikawa
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2016-12-13 00:00:00.000000000 Z
15
+ date: 2017-01-11 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rest-client
@@ -681,6 +681,7 @@ files:
681
681
  - lib/flydata/helper/action/agent_action.rb
682
682
  - lib/flydata/helper/action/check_abnormal_shutdown.rb
683
683
  - lib/flydata/helper/action/check_remote_actions.rb
684
+ - lib/flydata/helper/action/repair.rb
684
685
  - lib/flydata/helper/action/restart_agent.rb
685
686
  - lib/flydata/helper/action/send_logs.rb
686
687
  - lib/flydata/helper/action/stop_agent.rb
@@ -835,6 +836,7 @@ files:
835
836
  - spec/flydata/fluent-plugins/sync_source_plugin_context.rb
836
837
  - spec/flydata/helper/action/check_abnormal_shutdown_spec.rb
837
838
  - spec/flydata/helper/action/check_remote_actions_spec.rb
839
+ - spec/flydata/helper/action/repair_spec.rb
838
840
  - spec/flydata/helper/action/restart_agent_spec.rb
839
841
  - spec/flydata/helper/action/send_logs_spec.rb
840
842
  - spec/flydata/helper/action/stop_agent_spec.rb
@@ -908,7 +910,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
908
910
  version: '0'
909
911
  requirements: []
910
912
  rubyforge_project:
911
- rubygems_version: 2.0.14.1
913
+ rubygems_version: 2.4.3
912
914
  signing_key:
913
915
  specification_version: 4
914
916
  summary: FlyData Agent