flydata 0.7.15 → 0.7.16

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.
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