flydata 0.6.14 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/flydata-core/Gemfile +1 -0
- data/flydata-core/Gemfile.lock +5 -0
- data/flydata-core/lib/flydata-core/errors.rb +4 -2
- data/flydata-core/lib/flydata-core/mysql/binlog_pos.rb +4 -0
- data/flydata-core/lib/flydata-core/postgresql/compatibility_checker.rb +119 -0
- data/flydata-core/lib/flydata-core/postgresql/config.rb +58 -0
- data/flydata-core/lib/flydata-core/postgresql/pg_client.rb +170 -0
- data/flydata-core/lib/flydata-core/postgresql/snapshot.rb +49 -0
- data/flydata-core/lib/flydata-core/postgresql/source_pos.rb +71 -10
- data/flydata-core/lib/flydata-core/table_def/mysql_table_def.rb +1 -1
- data/flydata-core/lib/flydata-core/table_def/postgresql_table_def.rb +76 -17
- data/flydata-core/lib/flydata-core/table_def/redshift_table_def.rb +59 -10
- data/flydata-core/spec/mysql/binlog_pos_spec.rb +10 -2
- data/flydata-core/spec/postgresql/compatibility_checker_spec.rb +148 -0
- data/flydata-core/spec/postgresql/config_spec.rb +85 -0
- data/flydata-core/spec/postgresql/pg_client_spec.rb +195 -0
- data/flydata-core/spec/postgresql/snapshot_spec.rb +55 -0
- data/flydata-core/spec/postgresql/source_pos_spec.rb +70 -8
- data/flydata-core/spec/table_def/postgresql_table_def_spec.rb +80 -19
- data/flydata-core/spec/table_def/redshift_table_def_spec.rb +211 -14
- data/flydata.gemspec +0 -0
- data/lib/flydata.rb +1 -0
- data/lib/flydata/command/sender.rb +10 -7
- data/lib/flydata/command/sync.rb +4 -1
- data/lib/flydata/fluent-plugins/flydata_plugin_ext/base.rb +1 -0
- data/lib/flydata/fluent-plugins/flydata_plugin_ext/fluent_log_ext.rb +73 -0
- data/lib/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync.rb +35 -10
- data/lib/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_diff_based.rb +29 -0
- data/lib/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_query_based.rb +26 -0
- data/lib/flydata/fluent-plugins/flydata_plugin_ext/preference.rb +29 -13
- data/lib/flydata/fluent-plugins/in_mysql_binlog_flydata.rb +10 -18
- data/lib/flydata/fluent-plugins/in_postgresql_query_based_flydata.rb +64 -0
- data/lib/flydata/helpers.rb +1 -3
- data/lib/flydata/plugin_support/context.rb +14 -2
- data/lib/flydata/plugin_support/source_position_file.rb +35 -0
- data/lib/flydata/plugin_support/sync_record_emittable.rb +2 -1
- data/lib/flydata/query_based_sync/client.rb +101 -0
- data/lib/flydata/query_based_sync/record_size_estimator.rb +39 -0
- data/lib/flydata/query_based_sync/resource_requester.rb +70 -0
- data/lib/flydata/query_based_sync/response.rb +122 -0
- data/lib/flydata/query_based_sync/response_handler.rb +30 -0
- data/lib/flydata/source/sync_generate_table_ddl.rb +1 -1
- data/lib/flydata/source_mysql/plugin_support/binlog_record_dispatcher.rb +2 -2
- data/lib/flydata/source_mysql/plugin_support/binlog_record_handler.rb +3 -9
- data/lib/flydata/source_mysql/plugin_support/context.rb +26 -2
- data/lib/flydata/source_mysql/plugin_support/source_position_file.rb +14 -0
- data/lib/flydata/source_mysql/table_ddl.rb +3 -3
- data/lib/flydata/source_mysql/{plugin_support/table_meta.rb → table_meta.rb} +3 -10
- data/lib/flydata/source_postgresql/generate_source_dump.rb +44 -63
- data/lib/flydata/source_postgresql/parse_dump_and_send.rb +2 -0
- data/lib/flydata/source_postgresql/plugin_support/context.rb +13 -0
- data/lib/flydata/source_postgresql/plugin_support/source_position_file.rb +14 -0
- data/lib/flydata/source_postgresql/query_based_sync/client.rb +16 -0
- data/lib/flydata/source_postgresql/query_based_sync/diff_query_generator.rb +135 -0
- data/lib/flydata/source_postgresql/query_based_sync/resource_requester.rb +86 -0
- data/lib/flydata/source_postgresql/query_based_sync/response.rb +12 -0
- data/lib/flydata/source_postgresql/query_based_sync/response_handler.rb +12 -0
- data/lib/flydata/source_postgresql/sync_generate_table_ddl.rb +25 -79
- data/lib/flydata/source_postgresql/table_meta.rb +168 -0
- data/lib/flydata/sync_file_manager.rb +5 -5
- data/lib/flydata/table_meta.rb +19 -0
- data/spec/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_context.rb +85 -0
- data/spec/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_diff_based_shared_examples.rb +36 -0
- data/spec/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_query_based_shared_examples.rb +37 -0
- data/spec/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_shared_examples.rb +67 -0
- data/spec/flydata/fluent-plugins/in_mysql_binlog_flydata_spec.rb +119 -96
- data/spec/flydata/fluent-plugins/in_postgresql_query_based_flydata_spec.rb +82 -0
- data/spec/flydata/fluent-plugins/sync_source_plugin_context.rb +29 -0
- data/spec/flydata/plugin_support/context_spec.rb +37 -3
- data/spec/flydata/query_based_sync/client_spec.rb +79 -0
- data/spec/flydata/query_based_sync/query_based_sync_context.rb +116 -0
- data/spec/flydata/query_based_sync/record_size_estimator_spec.rb +54 -0
- data/spec/flydata/query_based_sync/resource_requester_spec.rb +58 -0
- data/spec/flydata/query_based_sync/response_handler_spec.rb +36 -0
- data/spec/flydata/query_based_sync/response_spec.rb +157 -0
- data/spec/flydata/source_mysql/plugin_support/context_spec.rb +7 -1
- data/spec/flydata/source_mysql/plugin_support/dml_record_handler_spec.rb +2 -15
- data/spec/flydata/source_mysql/plugin_support/drop_database_query_handler_spec.rb +1 -1
- data/spec/flydata/source_mysql/plugin_support/shared_query_handler_context.rb +12 -11
- data/spec/flydata/source_mysql/plugin_support/source_position_file_spec.rb +53 -0
- data/spec/flydata/source_mysql/plugin_support/truncate_query_handler_spec.rb +1 -1
- data/spec/flydata/source_mysql/table_ddl_spec.rb +5 -5
- data/spec/flydata/source_mysql/{plugin_support/table_meta_spec.rb → table_meta_spec.rb} +6 -7
- data/spec/flydata/source_postgresql/generate_source_dump_spec.rb +165 -77
- data/spec/flydata/source_postgresql/query_based_sync/diff_query_generator_spec.rb +213 -0
- data/spec/flydata/source_postgresql/query_based_sync/query_based_sync_postgresql_context.rb +76 -0
- data/spec/flydata/source_postgresql/query_based_sync/resource_requester_spec.rb +70 -0
- data/spec/flydata/source_postgresql/table_meta_spec.rb +77 -0
- metadata +49 -6
- data/lib/flydata/source_mysql/plugin_support/binlog_position_file.rb +0 -23
- data/lib/flydata/source_postgresql/pg_client.rb +0 -43
@@ -0,0 +1,82 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'fluent_plugins_spec_helper'
|
4
|
+
require 'in_postgresql_query_based_flydata'
|
5
|
+
require 'flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_query_based_shared_examples'
|
6
|
+
|
7
|
+
module Fluent
|
8
|
+
|
9
|
+
describe PostgresqlQueryBasedFlydataInput do
|
10
|
+
let(:plugin) { PostgresqlQueryBasedFlydataInput.new }
|
11
|
+
let(:default_config) { <<EOT
|
12
|
+
data_entry_name test_name
|
13
|
+
data_entry_type RedshiftMysqlDataEntry
|
14
|
+
tag #{TEST_TAG}
|
15
|
+
database #{TEST_DB}
|
16
|
+
tables test_table,test_table_1,test_table_2
|
17
|
+
tables_append_only test_table_3
|
18
|
+
position_file #{TEST_POSITION_FILE}
|
19
|
+
host localhost
|
20
|
+
port 3306
|
21
|
+
username test_admin
|
22
|
+
password test_password
|
23
|
+
database test_db
|
24
|
+
schema test_schema
|
25
|
+
emit_chunk_limit 64m
|
26
|
+
fetch_interval 2m
|
27
|
+
EOT
|
28
|
+
}
|
29
|
+
include_examples 'flydata sync query based shared examples'
|
30
|
+
|
31
|
+
describe '#configure' do
|
32
|
+
let(:config) { default_config }
|
33
|
+
subject { Test.configure_plugin(plugin, config) }
|
34
|
+
|
35
|
+
before do
|
36
|
+
create_file(TEST_POSITION_FILE, "1001:1001:\t\t")
|
37
|
+
create_table_pos_file('test_table', '0')
|
38
|
+
subject
|
39
|
+
end
|
40
|
+
after do
|
41
|
+
delete_file(TEST_POSITION_FILE)
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'sets data entry object' do
|
45
|
+
expect(plugin.instance_variable_get(:@data_entry)).to eq(
|
46
|
+
'name' => 'test_name',
|
47
|
+
'type' => 'RedshiftMysqlDataEntry',
|
48
|
+
'postgresql_data_entry_preference' => {
|
49
|
+
'database' => 'test_db',
|
50
|
+
'tables' => 'test_table,test_table_1,test_table_2',
|
51
|
+
'tables_append_only' => 'test_table_3',
|
52
|
+
'host' => 'localhost',
|
53
|
+
'username' => 'test_admin',
|
54
|
+
'password' => 'test_password',
|
55
|
+
'schema' => 'test_schema',
|
56
|
+
}
|
57
|
+
)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'sets data tables as array' do
|
61
|
+
expect(plugin.instance_variable_get(:@tables)).to eq(%w(test_table))
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'sets sync_fm' do
|
65
|
+
expect(plugin.instance_variable_get(:@sync_fm)).to be_kind_of(Flydata::SyncFileManager)
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'sets omit_events' do
|
69
|
+
expect(plugin.instance_variable_get(:@omit_events)).to eq({'test_table_3' => [:delete, :truncate_table]})
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'sets context' do
|
73
|
+
expect(plugin.instance_variable_get(:@context)).to be_kind_of(Flydata::SourcePostgresql::PluginSupport::Context)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'sets client' do
|
77
|
+
expect(plugin.instance_variable_get(:@client)).to be_kind_of(Flydata::SourcePostgresql::QueryBasedSync::Client)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'timecop'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Fluent
|
5
|
+
FLYDATA_HOME = Flydata::FLYDATA_HOME
|
6
|
+
TEST_TAG = "test_tag"
|
7
|
+
TEST_DB = "test_db"
|
8
|
+
TEST_TABLE = "test_table"
|
9
|
+
TEST_SEQUENCE_FILE = File.join(FLYDATA_HOME, "positions/#{TEST_TABLE}.pos")
|
10
|
+
TEST_SEQUENCE_NUM = 1
|
11
|
+
TEST_TABLE_BINLOG_POS = File.join(FLYDATA_HOME, "positions/#{TEST_TABLE}.binlog.pos")
|
12
|
+
TEST_TABLES = "#{TEST_TABLE},test_table_1,test_table_2,test_table_3"
|
13
|
+
TEST_POSITION_FILE = "test_position.binlog.pos"
|
14
|
+
TEST_SENT_POSITION_FILE = "test_position.binlog.sent.pos"
|
15
|
+
TEST_REVISION_FILE = File.join(FLYDATA_HOME, "positions/#{TEST_TABLE}.rev")
|
16
|
+
TEST_TIMESTAMP = 1389214083
|
17
|
+
TEST_TABLE_APPEND_ONLY = "test_table_4"
|
18
|
+
TEST_SEQUENCE_FILE_1 = File.join(FLYDATA_HOME, "positions/#{TEST_TABLE_APPEND_ONLY}.pos")
|
19
|
+
|
20
|
+
shared_context 'sync source plugin context' do
|
21
|
+
def create_file(file_path, content)
|
22
|
+
File.open(file_path, 'w') {|f| f.write(content)}
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete_file(file_path)
|
26
|
+
FileUtils.rm(file_path) if File.exists?(file_path)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -2,16 +2,38 @@ require 'fluent_plugins_spec_helper'
|
|
2
2
|
require 'flydata/plugin_support/context'
|
3
3
|
|
4
4
|
describe ::Flydata::PluginSupport::Context do
|
5
|
-
|
5
|
+
|
6
|
+
class DummySourcePos
|
7
|
+
def initialize(str)
|
8
|
+
@str = str
|
9
|
+
end
|
10
|
+
def self.load(str)
|
11
|
+
self.new(str)
|
12
|
+
end
|
13
|
+
attr_reader :str
|
14
|
+
end
|
15
|
+
|
16
|
+
class TestContext < described_class
|
17
|
+
SOURCE_POS_CLASS = DummySourcePos
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:subject_object) { TestContext.new(params) }
|
21
|
+
let(:sync_fm) { double('sync_fm') }
|
6
22
|
|
7
23
|
describe '#initialize' do
|
8
24
|
subject { subject_object }
|
9
25
|
|
26
|
+
before do
|
27
|
+
allow(sync_fm).to receive(:get_table_source_raw_pos) do |tbl|
|
28
|
+
"#{tbl}_binlog_pos"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
10
32
|
context 'when no missing params' do
|
11
33
|
let(:params) { {
|
12
34
|
tables: %w(table_a table_b table_c),
|
13
35
|
tag: 'test_tag',
|
14
|
-
sync_fm:
|
36
|
+
sync_fm: sync_fm,
|
15
37
|
omit_events: {'table_c' => %i(delete truncate_table)},
|
16
38
|
table_revs: {'table_a' => 1, 'table_b' => 2, 'table_c' => 3},
|
17
39
|
} }
|
@@ -19,9 +41,21 @@ describe ::Flydata::PluginSupport::Context do
|
|
19
41
|
it { expect{subject}.not_to raise_error }
|
20
42
|
it { expect(subject.tables).to eq(%w(table_a table_b table_c)) }
|
21
43
|
it { expect(subject.tag).to eq('test_tag') }
|
22
|
-
it { expect(subject.sync_fm).to eq(
|
44
|
+
it { expect(subject.sync_fm).to eq(sync_fm) }
|
23
45
|
it { expect(subject.omit_events).to eq({'table_c' => %i(delete truncate_table)}) }
|
24
46
|
it { expect(subject.table_revs).to eq({'table_a' => 1, 'table_b' => 2, 'table_c' => 3}) }
|
47
|
+
=begin
|
48
|
+
it do
|
49
|
+
binlog_pos = subject.table_binlog_pos
|
50
|
+
expect(binlog_pos.keys.size).to eq(3)
|
51
|
+
expect(binlog_pos['table_a']).to be_kind_of(DummySourcePos)
|
52
|
+
expect(binlog_pos['table_a'].str).to eq('table_a_binlog_pos')
|
53
|
+
expect(binlog_pos['table_b']).to be_kind_of(DummySourcePos)
|
54
|
+
expect(binlog_pos['table_b'].str).to eq('table_b_binlog_pos')
|
55
|
+
expect(binlog_pos['table_c']).to be_kind_of(DummySourcePos)
|
56
|
+
expect(binlog_pos['table_c'].str).to eq('table_c_binlog_pos')
|
57
|
+
end
|
58
|
+
=end
|
25
59
|
end
|
26
60
|
end
|
27
61
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'flydata/query_based_sync/query_based_sync_context'
|
3
|
+
|
4
|
+
|
5
|
+
module Flydata
|
6
|
+
module QueryBasedSync
|
7
|
+
|
8
|
+
describe Client do
|
9
|
+
include_context 'query based sync context'
|
10
|
+
|
11
|
+
let(:subject_object) { DummyClient.new(context) }
|
12
|
+
|
13
|
+
describe '#initialize' do
|
14
|
+
subject { subject_object }
|
15
|
+
|
16
|
+
before do
|
17
|
+
subject
|
18
|
+
end
|
19
|
+
|
20
|
+
it { expect(subject.context).to eq(context) }
|
21
|
+
it { expect(subject.resource_requester).to be_kind_of(DummyResourceRequester) }
|
22
|
+
it { expect(subject.response_handler).to be_kind_of(DummyResponseHandler) }
|
23
|
+
it { expect(subject.instance_variable_get(:@fetch_interval)).to eq(10) }
|
24
|
+
it { expect(subject.instance_variable_get(:@retry_interval)).to eq(5) }
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#start' do
|
28
|
+
def start_client(wait = 0.0)
|
29
|
+
@thread = Thread.new(&method(:run_client))
|
30
|
+
sleep wait
|
31
|
+
expect(@thread.alive?).to be(true)
|
32
|
+
end
|
33
|
+
|
34
|
+
def run_client
|
35
|
+
subject_object.start
|
36
|
+
rescue Exception => e
|
37
|
+
$stderr.puts "Caught an exception during running client - error:#{e}\n #{e.backtrace.join("\n ")}"
|
38
|
+
raise e
|
39
|
+
end
|
40
|
+
|
41
|
+
def stop_client
|
42
|
+
if @thread and @thread.alive?
|
43
|
+
subject_object.stop_request
|
44
|
+
@thread.join
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
before do
|
49
|
+
allow_any_instance_of(DummyResourceRequester).to receive(:start) do |my_instance, &block|
|
50
|
+
block.call(my_instance)
|
51
|
+
end
|
52
|
+
allow_any_instance_of(DummyResourceRequester).to receive(:each_response).and_yield(response)
|
53
|
+
allow_any_instance_of(DummyResponseHandler).to receive(:handle)
|
54
|
+
end
|
55
|
+
|
56
|
+
after do
|
57
|
+
stop_client
|
58
|
+
expect(subject_object.stop_requested?).to eq(true)
|
59
|
+
expect(@thread.alive?).to eq(false)
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'starts and stops client' do
|
63
|
+
expect_any_instance_of(DummyResponseHandler).to receive(:handle).with(response)
|
64
|
+
start_client(0.2)
|
65
|
+
stop_client
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when calls start two times' do
|
69
|
+
it 'gets an error for the second try' do
|
70
|
+
start_client(0.2)
|
71
|
+
expect{subject_object.start}.to raise_error(/Already started/)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'flydata/plugin_support/context'
|
3
|
+
require 'flydata/query_based_sync/client'
|
4
|
+
require 'flydata/query_based_sync/resource_requester'
|
5
|
+
require 'flydata/query_based_sync/response_handler'
|
6
|
+
require 'flydata/query_based_sync/response'
|
7
|
+
require 'flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_context'
|
8
|
+
|
9
|
+
|
10
|
+
module Flydata
|
11
|
+
module QueryBasedSync
|
12
|
+
|
13
|
+
class DummyResourceRequester < ResourceRequester
|
14
|
+
end
|
15
|
+
|
16
|
+
class DummyResponseHandler < ResponseHandler
|
17
|
+
end
|
18
|
+
|
19
|
+
class DummyResponse < Response
|
20
|
+
end
|
21
|
+
|
22
|
+
class DummyClient < Client
|
23
|
+
RESOURCE_REQUESTER_CLASS = DummyResourceRequester
|
24
|
+
RESPONSE_HANDLER_CLASS = DummyResponseHandler
|
25
|
+
end
|
26
|
+
|
27
|
+
class DummySourcePos
|
28
|
+
include Comparable
|
29
|
+
|
30
|
+
def initialize(*args)
|
31
|
+
@snapshot = args.first
|
32
|
+
@args = args
|
33
|
+
end
|
34
|
+
|
35
|
+
attr_reader :snapshot
|
36
|
+
attr_reader :args
|
37
|
+
|
38
|
+
def <=>(other)
|
39
|
+
snapshot <=> other.snapshot
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
shared_context 'query based sync context' do
|
44
|
+
include_context 'flydata sync context'
|
45
|
+
|
46
|
+
def create_response(context, table_name, records, query_cond = {})
|
47
|
+
DummyResponse.new(context, table_name, records, query_cond)
|
48
|
+
end
|
49
|
+
|
50
|
+
let(:resource_client) { double('client') }
|
51
|
+
let(:records) { [
|
52
|
+
{'1'=>1, '2'=>'a'},
|
53
|
+
{'1'=>2, '2'=>'b'},
|
54
|
+
{'1'=>3, '2'=>'c'},
|
55
|
+
] }
|
56
|
+
let(:query_cond) { {from_sid: previous_snapshot, to_sid: current_snapshot} }
|
57
|
+
let(:response) { create_response(context, 'table_1', records, query_cond) }
|
58
|
+
|
59
|
+
let(:sync_fm) { double('sync_fm') }
|
60
|
+
let(:table_meta) { double('table_meta') }
|
61
|
+
let(:table_meta_1) { {
|
62
|
+
table_name: 'table_1',
|
63
|
+
table_schema: nil,
|
64
|
+
pk_positions: [1],
|
65
|
+
primary_keys: ['id'],
|
66
|
+
columns: [
|
67
|
+
{ column: 'id', type: 'int4' },
|
68
|
+
{ column: 'value', type: 'varchar(24)' },
|
69
|
+
]
|
70
|
+
} }
|
71
|
+
let(:cur_src_pos_file) { double('cur_src_pos_file') }
|
72
|
+
let(:table_1_src_pos_file) { double('table_1_src_pos_file') }
|
73
|
+
let(:table_2_src_pos_file) { double('table_2_src_pos_file') }
|
74
|
+
let(:table_3_src_pos_file) { double('table_3_src_pos_file') }
|
75
|
+
let(:context) {
|
76
|
+
Flydata::PluginSupport::Context.new(
|
77
|
+
cur_src_pos_file: cur_src_pos_file,
|
78
|
+
tables: %w(table_1 table_2 table_3),
|
79
|
+
tag: 'test_tag',
|
80
|
+
sync_fm: sync_fm,
|
81
|
+
|
82
|
+
omit_events: { 'table_3' => [:delete, :truncate] },
|
83
|
+
table_revs: { 'table_1' => 1, 'table_2' => 1, 'table_3' => 1 },
|
84
|
+
table_meta: table_meta,
|
85
|
+
table_src_pos_files: {
|
86
|
+
table_1: table_1_src_pos_file,
|
87
|
+
table_2: table_2_src_pos_file,
|
88
|
+
table_3: table_3_src_pos_file,
|
89
|
+
},
|
90
|
+
params: {
|
91
|
+
fetch_interval: 10,
|
92
|
+
retry_interval: 5,
|
93
|
+
}
|
94
|
+
)
|
95
|
+
}
|
96
|
+
let(:previous_snapshot) { double('previous_snapshot') }
|
97
|
+
let(:current_snapshot) { double('current_snapshot') }
|
98
|
+
|
99
|
+
def setup_dummy_objects
|
100
|
+
allow_any_instance_of(DummyResourceRequester).to receive(:create_resource_client).and_return(resource_client)
|
101
|
+
allow_any_instance_of(DummyResourceRequester).to receive(:close)
|
102
|
+
allow(context).to receive(:source_pos_class).and_return(DummySourcePos)
|
103
|
+
response.instance_variable_set(:@new_source_pos, DummySourcePos.new(current_snapshot))
|
104
|
+
end
|
105
|
+
|
106
|
+
before do
|
107
|
+
allow(table_meta).to receive(:[]).with(:table_1).and_return(table_meta_1)
|
108
|
+
allow(table_meta).to receive(:current_snapshot).and_return(current_snapshot)
|
109
|
+
allow(cur_src_pos_file).to receive(:save).with(current_snapshot)
|
110
|
+
setup_dummy_objects
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'flydata/query_based_sync/record_size_estimator'
|
3
|
+
|
4
|
+
module Flydata
|
5
|
+
module QueryBasedSync
|
6
|
+
|
7
|
+
describe RecordSizeEstimator do
|
8
|
+
def actual_record_size(table_name, record)
|
9
|
+
j = {
|
10
|
+
row: record,
|
11
|
+
type: :update,
|
12
|
+
respect_order: true,
|
13
|
+
src_pos: "10051:10051:\t10520:10052:\t{\"id\":\"1000000000\"}",
|
14
|
+
v: 2,
|
15
|
+
seq: 1000000000,
|
16
|
+
table_name: table_name,
|
17
|
+
table_rev: 1,
|
18
|
+
}.to_json.size
|
19
|
+
end
|
20
|
+
|
21
|
+
let(:table_name) { 'table_1' }
|
22
|
+
let(:num_columns) { 2 }
|
23
|
+
let(:subject_object) { described_class.new(table_name, num_columns) }
|
24
|
+
|
25
|
+
describe '#calc_record_size' do
|
26
|
+
|
27
|
+
def create_record(num_records = 10)
|
28
|
+
1.upto(num_records).inject({}){|h, i| h[i.to_s]=i.to_s ;h}
|
29
|
+
end
|
30
|
+
|
31
|
+
let(:num_columns) { record.values.count }
|
32
|
+
subject { subject_object.calc_record_size(record) }
|
33
|
+
let(:actual_size) { actual_record_size(table_name, record) }
|
34
|
+
|
35
|
+
context 'when number of columns is small' do
|
36
|
+
let(:record) { create_record(2) }
|
37
|
+
it { is_expected.to eq(actual_size) }
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when number of columns is medium' do
|
41
|
+
let(:record) { create_record(12) }
|
42
|
+
it { is_expected.to eq(actual_size) }
|
43
|
+
end
|
44
|
+
|
45
|
+
context 'when number of columns is big' do
|
46
|
+
let(:record) { create_record(102) }
|
47
|
+
it { is_expected.to eq(actual_size) }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'flydata/query_based_sync/query_based_sync_context'
|
3
|
+
|
4
|
+
|
5
|
+
module Flydata
|
6
|
+
module QueryBasedSync
|
7
|
+
|
8
|
+
describe ResourceRequester do
|
9
|
+
include_context 'query based sync context'
|
10
|
+
|
11
|
+
let(:subject_object) { DummyResourceRequester.new(context) }
|
12
|
+
|
13
|
+
describe '#initialize' do
|
14
|
+
subject { subject_object }
|
15
|
+
|
16
|
+
before do
|
17
|
+
subject
|
18
|
+
end
|
19
|
+
|
20
|
+
it { expect(subject.context).to eq(context) }
|
21
|
+
it { expect(subject.instance_variable_get(:@resource_client)).to eq(resource_client) }
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#start' do
|
25
|
+
it do
|
26
|
+
expect(table_meta).to receive(:reload).with(resource_client)
|
27
|
+
expect(resource_client).to receive(:close).once
|
28
|
+
expect{|b| subject_object.start(&b)}.to yield_with_args(subject_object)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#each_response' do
|
33
|
+
let(:table_name) { 'table_1' }
|
34
|
+
let(:returned_responses) { nil }
|
35
|
+
|
36
|
+
before do
|
37
|
+
allow(subject_object).to receive(:fetch_responses_once).and_return(returned_responses)
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when no response' do
|
41
|
+
let(:returned_responses) { [] }
|
42
|
+
it do
|
43
|
+
expect(subject_object.each_response(table_name)).to be_nil
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when returning a response' do
|
48
|
+
let(:returned_responses) { [response] }
|
49
|
+
it do
|
50
|
+
expect{|b| subject_object.each_response(table_name, 0.1, &b)}.
|
51
|
+
to yield_with_args(response)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|