flydata 0.6.14 → 0.7.0

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