flydata 0.6.14 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/flydata-core/Gemfile +1 -0
  4. data/flydata-core/Gemfile.lock +5 -0
  5. data/flydata-core/lib/flydata-core/errors.rb +4 -2
  6. data/flydata-core/lib/flydata-core/mysql/binlog_pos.rb +4 -0
  7. data/flydata-core/lib/flydata-core/postgresql/compatibility_checker.rb +119 -0
  8. data/flydata-core/lib/flydata-core/postgresql/config.rb +58 -0
  9. data/flydata-core/lib/flydata-core/postgresql/pg_client.rb +170 -0
  10. data/flydata-core/lib/flydata-core/postgresql/snapshot.rb +49 -0
  11. data/flydata-core/lib/flydata-core/postgresql/source_pos.rb +71 -10
  12. data/flydata-core/lib/flydata-core/table_def/mysql_table_def.rb +1 -1
  13. data/flydata-core/lib/flydata-core/table_def/postgresql_table_def.rb +76 -17
  14. data/flydata-core/lib/flydata-core/table_def/redshift_table_def.rb +59 -10
  15. data/flydata-core/spec/mysql/binlog_pos_spec.rb +10 -2
  16. data/flydata-core/spec/postgresql/compatibility_checker_spec.rb +148 -0
  17. data/flydata-core/spec/postgresql/config_spec.rb +85 -0
  18. data/flydata-core/spec/postgresql/pg_client_spec.rb +195 -0
  19. data/flydata-core/spec/postgresql/snapshot_spec.rb +55 -0
  20. data/flydata-core/spec/postgresql/source_pos_spec.rb +70 -8
  21. data/flydata-core/spec/table_def/postgresql_table_def_spec.rb +80 -19
  22. data/flydata-core/spec/table_def/redshift_table_def_spec.rb +211 -14
  23. data/flydata.gemspec +0 -0
  24. data/lib/flydata.rb +1 -0
  25. data/lib/flydata/command/sender.rb +10 -7
  26. data/lib/flydata/command/sync.rb +4 -1
  27. data/lib/flydata/fluent-plugins/flydata_plugin_ext/base.rb +1 -0
  28. data/lib/flydata/fluent-plugins/flydata_plugin_ext/fluent_log_ext.rb +73 -0
  29. data/lib/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync.rb +35 -10
  30. data/lib/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_diff_based.rb +29 -0
  31. data/lib/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_query_based.rb +26 -0
  32. data/lib/flydata/fluent-plugins/flydata_plugin_ext/preference.rb +29 -13
  33. data/lib/flydata/fluent-plugins/in_mysql_binlog_flydata.rb +10 -18
  34. data/lib/flydata/fluent-plugins/in_postgresql_query_based_flydata.rb +64 -0
  35. data/lib/flydata/helpers.rb +1 -3
  36. data/lib/flydata/plugin_support/context.rb +14 -2
  37. data/lib/flydata/plugin_support/source_position_file.rb +35 -0
  38. data/lib/flydata/plugin_support/sync_record_emittable.rb +2 -1
  39. data/lib/flydata/query_based_sync/client.rb +101 -0
  40. data/lib/flydata/query_based_sync/record_size_estimator.rb +39 -0
  41. data/lib/flydata/query_based_sync/resource_requester.rb +70 -0
  42. data/lib/flydata/query_based_sync/response.rb +122 -0
  43. data/lib/flydata/query_based_sync/response_handler.rb +30 -0
  44. data/lib/flydata/source/sync_generate_table_ddl.rb +1 -1
  45. data/lib/flydata/source_mysql/plugin_support/binlog_record_dispatcher.rb +2 -2
  46. data/lib/flydata/source_mysql/plugin_support/binlog_record_handler.rb +3 -9
  47. data/lib/flydata/source_mysql/plugin_support/context.rb +26 -2
  48. data/lib/flydata/source_mysql/plugin_support/source_position_file.rb +14 -0
  49. data/lib/flydata/source_mysql/table_ddl.rb +3 -3
  50. data/lib/flydata/source_mysql/{plugin_support/table_meta.rb → table_meta.rb} +3 -10
  51. data/lib/flydata/source_postgresql/generate_source_dump.rb +44 -63
  52. data/lib/flydata/source_postgresql/parse_dump_and_send.rb +2 -0
  53. data/lib/flydata/source_postgresql/plugin_support/context.rb +13 -0
  54. data/lib/flydata/source_postgresql/plugin_support/source_position_file.rb +14 -0
  55. data/lib/flydata/source_postgresql/query_based_sync/client.rb +16 -0
  56. data/lib/flydata/source_postgresql/query_based_sync/diff_query_generator.rb +135 -0
  57. data/lib/flydata/source_postgresql/query_based_sync/resource_requester.rb +86 -0
  58. data/lib/flydata/source_postgresql/query_based_sync/response.rb +12 -0
  59. data/lib/flydata/source_postgresql/query_based_sync/response_handler.rb +12 -0
  60. data/lib/flydata/source_postgresql/sync_generate_table_ddl.rb +25 -79
  61. data/lib/flydata/source_postgresql/table_meta.rb +168 -0
  62. data/lib/flydata/sync_file_manager.rb +5 -5
  63. data/lib/flydata/table_meta.rb +19 -0
  64. data/spec/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_context.rb +85 -0
  65. data/spec/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_diff_based_shared_examples.rb +36 -0
  66. data/spec/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_query_based_shared_examples.rb +37 -0
  67. data/spec/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_shared_examples.rb +67 -0
  68. data/spec/flydata/fluent-plugins/in_mysql_binlog_flydata_spec.rb +119 -96
  69. data/spec/flydata/fluent-plugins/in_postgresql_query_based_flydata_spec.rb +82 -0
  70. data/spec/flydata/fluent-plugins/sync_source_plugin_context.rb +29 -0
  71. data/spec/flydata/plugin_support/context_spec.rb +37 -3
  72. data/spec/flydata/query_based_sync/client_spec.rb +79 -0
  73. data/spec/flydata/query_based_sync/query_based_sync_context.rb +116 -0
  74. data/spec/flydata/query_based_sync/record_size_estimator_spec.rb +54 -0
  75. data/spec/flydata/query_based_sync/resource_requester_spec.rb +58 -0
  76. data/spec/flydata/query_based_sync/response_handler_spec.rb +36 -0
  77. data/spec/flydata/query_based_sync/response_spec.rb +157 -0
  78. data/spec/flydata/source_mysql/plugin_support/context_spec.rb +7 -1
  79. data/spec/flydata/source_mysql/plugin_support/dml_record_handler_spec.rb +2 -15
  80. data/spec/flydata/source_mysql/plugin_support/drop_database_query_handler_spec.rb +1 -1
  81. data/spec/flydata/source_mysql/plugin_support/shared_query_handler_context.rb +12 -11
  82. data/spec/flydata/source_mysql/plugin_support/source_position_file_spec.rb +53 -0
  83. data/spec/flydata/source_mysql/plugin_support/truncate_query_handler_spec.rb +1 -1
  84. data/spec/flydata/source_mysql/table_ddl_spec.rb +5 -5
  85. data/spec/flydata/source_mysql/{plugin_support/table_meta_spec.rb → table_meta_spec.rb} +6 -7
  86. data/spec/flydata/source_postgresql/generate_source_dump_spec.rb +165 -77
  87. data/spec/flydata/source_postgresql/query_based_sync/diff_query_generator_spec.rb +213 -0
  88. data/spec/flydata/source_postgresql/query_based_sync/query_based_sync_postgresql_context.rb +76 -0
  89. data/spec/flydata/source_postgresql/query_based_sync/resource_requester_spec.rb +70 -0
  90. data/spec/flydata/source_postgresql/table_meta_spec.rb +77 -0
  91. metadata +49 -6
  92. data/lib/flydata/source_mysql/plugin_support/binlog_position_file.rb +0 -23
  93. 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
- let(:subject_object) { described_class.new(params) }
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: 'test_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('test_sync_fm') }
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