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 +4 -4
- data/VERSION +1 -1
- data/flydata-core/lib/flydata-core/table_def/redshift_table_def.rb +3 -0
- data/flydata-core/spec/table_def/redshift_table_def_spec.rb +19 -0
- data/flydata.gemspec +0 -0
- data/lib/flydata/command/sync.rb +63 -55
- data/lib/flydata/fluent-plugins/in_postgresql_query_based_flydata.rb +1 -0
- data/lib/flydata/helper/action/repair.rb +13 -0
- data/lib/flydata/helper/action_ownership.rb +1 -0
- data/lib/flydata/plugin_support/context.rb +1 -0
- data/lib/flydata/query_based_sync/client.rb +3 -0
- data/spec/flydata/helper/action/repair_spec.rb +21 -0
- data/spec/flydata/helper/action_ownership_spec.rb +1 -1
- data/spec/flydata/query_based_sync/query_based_sync_context.rb +3 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aafcbf0332b985cd94a8fa83302bbccdb5ef86f1
|
4
|
+
data.tar.gz: f6842935284bacbd7cc5046f640c65c376b28bfb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8f6ef145d7f026237e35dd351f306b815a901e654a3fa67bc1ddd251fcad5fbc003c5780e2b93260f670f3692efcf78160c8ea688466f70eea91ebe12a3ade8d
|
7
|
+
data.tar.gz: 268449b51660a61f40aa8a731107630c2876c41b656ef4063b2eb41b925162d942c2963017d15a83d91dd78366cacc698d3c8c51d43bc6e2af5fe55b7865d0e4
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.7.
|
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
|
data/lib/flydata/command/sync.rb
CHANGED
@@ -341,7 +341,7 @@ EOS
|
|
341
341
|
message += "\n"
|
342
342
|
end
|
343
343
|
if pos_mismatch_tables
|
344
|
-
message += " - Incorrect table position
|
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
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
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
|
504
|
+
log_info_stdout <<EOS unless broken_tables.empty?
|
489
505
|
- Sync is broken due to missing data for the following tables
|
490
|
-
#{
|
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
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
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,
|
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
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
|
587
|
-
|
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
|
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(
|
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: {
|
@@ -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
|
@@ -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.
|
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:
|
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.
|
913
|
+
rubygems_version: 2.4.3
|
912
914
|
signing_key:
|
913
915
|
specification_version: 4
|
914
916
|
summary: FlyData Agent
|