flydata 0.2.30 → 0.3.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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/bin/flydata +6 -1
- data/flydata-core/lib/flydata-core/table_def/mysql_table_def.rb +18 -15
- data/flydata-core/spec/table_def/mysql_table_def_spec.rb +132 -0
- data/flydata.gemspec +5 -4
- data/lib/flydata/cli.rb +5 -3
- data/lib/flydata/command/setup.rb +7 -2
- data/lib/flydata/command/sync.rb +62 -8
- data/lib/flydata/compatibility_check.rb +2 -2
- data/lib/flydata/errors.rb +34 -0
- data/lib/flydata/fluent-plugins/mysql/dml_record_handler.rb +14 -9
- data/lib/flydata/helpers.rb +1 -17
- data/spec/flydata/cli_spec.rb +2 -2
- data/spec/flydata/fluent-plugins/in_mysql_binlog_flydata_spec.rb +25 -9
- data/spec/flydata/parser/mysql/alter_table_parser_spec.rb +2 -2
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 68f311d20207752e80dd5fb47b905b085e840520
|
4
|
+
data.tar.gz: 6bfa38fa63a7db7e1f4b7109324017e99c82c117
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 01469b9c9b268bc8dad0bda81a3dbcc3a98a55901108cac17b50a6688313485f1d7cdd8a01b26ea20cbea0d8fa6f4c096055394f55cea58ee59a949acb2963fe
|
7
|
+
data.tar.gz: cde53114405b00f034e7444fd0b9ba9df9519a2cd3979eade6a99d48e80e326615a1ba16fb0d5c014c51d23272ca5cf2257b2f318135ad6efef858f4d6d4479b
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/bin/flydata
CHANGED
@@ -28,37 +28,37 @@ class MysqlTableDef
|
|
28
28
|
end
|
29
29
|
|
30
30
|
TYPE_MAP_M2F = {
|
31
|
-
'bigint' => {type: 'int8'},
|
32
|
-
'binary' => {type: 'binary', override: PROC_override_varbinary},
|
33
|
-
'bit' => {type: 'bit'},
|
31
|
+
'bigint' => {type: 'int8', def_width: '20'},
|
32
|
+
'binary' => {type: 'binary', def_width: '1', override: PROC_override_varbinary},
|
33
|
+
'bit' => {type: 'bit', def_width: '1'},
|
34
34
|
'blob' => {type: 'varbinary(65535)'},
|
35
|
-
'bool' => {type: 'int1'},
|
36
|
-
'boolean' => {type: 'int1'},
|
37
|
-
'char' => {type: 'varchar', override: PROC_override_varchar},
|
35
|
+
'bool' => {type: 'int1', def_width: '1'},
|
36
|
+
'boolean' => {type: 'int1', def_width: '1'},
|
37
|
+
'char' => {type: 'varchar', def_width: '1', override: PROC_override_varchar},
|
38
38
|
'date' => {type: 'date'},
|
39
39
|
'datetime' => {type: 'datetime'},
|
40
|
-
'dec' => {type: 'numeric'},
|
41
|
-
'decimal' => {type: 'numeric'},
|
40
|
+
'dec' => {type: 'numeric', def_width: '10,0'},
|
41
|
+
'decimal' => {type: 'numeric', def_width: '10,0'},
|
42
42
|
'double' => {type: 'float8'},
|
43
43
|
'double precision' => {type: 'float8'},
|
44
44
|
'enum' => {type: 'enum'},
|
45
|
-
'fixed' => {type: 'numeric'},
|
45
|
+
'fixed' => {type: 'numeric', def_width: '10,0'},
|
46
46
|
'float' => {type: 'float4'},
|
47
|
-
'int' => {type: 'int4'},
|
48
|
-
'integer' => {type: 'int4'},
|
47
|
+
'int' => {type: 'int4', def_width: '11'},
|
48
|
+
'integer' => {type: 'int4', def_width: '11'},
|
49
49
|
'longblob' => {type: 'varbinary(4294967295)'},
|
50
50
|
'longtext' => {type: 'text'},
|
51
51
|
'mediumblob' => {type: 'varbinary(16777215)'},
|
52
|
-
'mediumint' => {type: 'int3'},
|
52
|
+
'mediumint' => {type: 'int3', def_width: '9'},
|
53
53
|
'mediumtext' => {type: 'text'},
|
54
|
-
'numeric' => {type: 'numeric'},
|
54
|
+
'numeric' => {type: 'numeric', def_width: '10,0'},
|
55
55
|
'set' => {type: 'set'},
|
56
|
-
'smallint' => {type: 'int2'},
|
56
|
+
'smallint' => {type: 'int2', def_width: '6'},
|
57
57
|
'text' => {type: 'text'},
|
58
58
|
'time' => {type: 'time'},
|
59
59
|
'timestamp' => {type: 'datetime'},
|
60
60
|
'tinyblob' => {type: 'varbinary(255)'},
|
61
|
-
'tinyint' => {type: 'int1'},
|
61
|
+
'tinyint' => {type: 'int1', def_width: '4'},
|
62
62
|
'tinytext' => {type: 'text'},
|
63
63
|
'varbinary' => {type: 'varbinary', override: PROC_override_varbinary},
|
64
64
|
'varchar' => {type: 'varchar', override: PROC_override_varchar},
|
@@ -69,6 +69,9 @@ class MysqlTableDef
|
|
69
69
|
flydata_type = type_hash[:type]
|
70
70
|
if /^#{mysql_type}\(|^#{mysql_type}$/.match(type)
|
71
71
|
ret_type = type.gsub(/^#{mysql_type}/, flydata_type)
|
72
|
+
if type_hash.has_key?(:def_width) && !/\(.+\)/.match(ret_type)
|
73
|
+
ret_type += "(#{type_hash[:def_width]})"
|
74
|
+
end
|
72
75
|
if type_hash[:override]
|
73
76
|
ret_type = type_hash[:override].call(ret_type, mysql_type, flydata_type)
|
74
77
|
end
|
@@ -199,6 +199,138 @@ describe MysqlTableDef do
|
|
199
199
|
end
|
200
200
|
end
|
201
201
|
end
|
202
|
+
|
203
|
+
describe '.convert_to_flydata_type' do
|
204
|
+
subject { described_class.convert_to_flydata_type(mysql_type) }
|
205
|
+
shared_examples "converting the mysql data type to the expected flydata type" do
|
206
|
+
# Use the context description as the value of "mysql_type"
|
207
|
+
# RSpec.current_example.meatadata[:example_group] => the shared_examples "converting the mysql data type to the expected flydata type"
|
208
|
+
# [:parent_example_group] => the context including the shared examples (e.g. context "bigint")
|
209
|
+
# [:description] => the name of the example group (e.g. "bigint")
|
210
|
+
let(:mysql_type) { RSpec.current_example.metadata[:example_group][:parent_example_group][:description] }
|
211
|
+
it do
|
212
|
+
expect(subject).to eq flydata_type
|
213
|
+
end
|
214
|
+
end
|
215
|
+
context "with no-width mysql data type" do
|
216
|
+
context "bigint" do
|
217
|
+
let(:flydata_type) { 'int8(20)' }
|
218
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
219
|
+
end
|
220
|
+
context "binary" do
|
221
|
+
let(:flydata_type) { 'binary(4)' }
|
222
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
223
|
+
end
|
224
|
+
context "bit" do
|
225
|
+
let(:flydata_type) { 'bit(1)' }
|
226
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
227
|
+
end
|
228
|
+
context "blob" do
|
229
|
+
let(:flydata_type) { 'varbinary(65535)' }
|
230
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
231
|
+
end
|
232
|
+
context "bool" do
|
233
|
+
let(:flydata_type) { 'int1(1)' }
|
234
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
235
|
+
end
|
236
|
+
context "boolean" do
|
237
|
+
let(:flydata_type) { 'int1(1)' }
|
238
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
239
|
+
end
|
240
|
+
context "char" do
|
241
|
+
let(:flydata_type) { 'varchar(3)' }
|
242
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
243
|
+
end
|
244
|
+
context "date" do
|
245
|
+
let(:flydata_type) { 'date' }
|
246
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
247
|
+
end
|
248
|
+
context "datetime" do
|
249
|
+
let(:flydata_type) { 'datetime' }
|
250
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
251
|
+
end
|
252
|
+
context "dec" do
|
253
|
+
let(:flydata_type) { 'numeric(10,0)' }
|
254
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
255
|
+
end
|
256
|
+
context "decimal" do
|
257
|
+
let(:flydata_type) { 'numeric(10,0)' }
|
258
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
259
|
+
end
|
260
|
+
context "double" do
|
261
|
+
let(:flydata_type) { 'float8' }
|
262
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
263
|
+
end
|
264
|
+
context "fixed" do
|
265
|
+
let(:flydata_type) { 'numeric(10,0)' }
|
266
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
267
|
+
end
|
268
|
+
context "float" do
|
269
|
+
let(:flydata_type) { 'float4' }
|
270
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
271
|
+
end
|
272
|
+
context "int" do
|
273
|
+
let(:flydata_type) { 'int4(11)' }
|
274
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
275
|
+
end
|
276
|
+
context "integer" do
|
277
|
+
let(:flydata_type) { 'int4(11)' }
|
278
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
279
|
+
end
|
280
|
+
context "longblob" do
|
281
|
+
let(:flydata_type) { 'varbinary(4294967295)' }
|
282
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
283
|
+
end
|
284
|
+
context "longtext" do
|
285
|
+
let(:flydata_type) { 'text' }
|
286
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
287
|
+
end
|
288
|
+
context "mediumblob" do
|
289
|
+
let(:flydata_type) { 'varbinary(16777215)' }
|
290
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
291
|
+
end
|
292
|
+
context "mediumint" do
|
293
|
+
let(:flydata_type) { 'int3(9)' }
|
294
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
295
|
+
end
|
296
|
+
context "mediumtext" do
|
297
|
+
let(:flydata_type) { 'text' }
|
298
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
299
|
+
end
|
300
|
+
context "numeric" do
|
301
|
+
let(:flydata_type) { 'numeric(10,0)' }
|
302
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
303
|
+
end
|
304
|
+
context "smallint" do
|
305
|
+
let(:flydata_type) { 'int2(6)' }
|
306
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
307
|
+
end
|
308
|
+
context "text" do
|
309
|
+
let(:flydata_type) { 'text' }
|
310
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
311
|
+
end
|
312
|
+
context "time" do
|
313
|
+
let(:flydata_type) { 'time' }
|
314
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
315
|
+
end
|
316
|
+
context "timestamp" do
|
317
|
+
let(:flydata_type) { 'datetime' }
|
318
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
319
|
+
end
|
320
|
+
context "tinyblob" do
|
321
|
+
let(:flydata_type) { 'varbinary(255)' }
|
322
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
323
|
+
end
|
324
|
+
context "tinyint" do
|
325
|
+
let(:flydata_type) { 'int1(4)' }
|
326
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
327
|
+
end
|
328
|
+
context "tinytext" do
|
329
|
+
let(:flydata_type) { 'text' }
|
330
|
+
it_behaves_like "converting the mysql data type to the expected flydata type"
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
202
334
|
end
|
203
335
|
|
204
336
|
end
|
data/flydata.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: flydata 0.
|
5
|
+
# stub: flydata 0.3.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "flydata"
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.3.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Koichi Fujikawa", "Masashi Miyazaki", "Matthew Luu", "Mak Inada", "Sriram NS"]
|
14
|
-
s.date = "2015-
|
14
|
+
s.date = "2015-02-11"
|
15
15
|
s.description = "FlyData Agent"
|
16
16
|
s.email = "sysadmin@flydata.com"
|
17
17
|
s.executables = ["fdmysqldump", "flydata", "serverinfo"]
|
@@ -93,6 +93,7 @@ Gem::Specification.new do |s|
|
|
93
93
|
"lib/flydata/compatibility_check.rb",
|
94
94
|
"lib/flydata/credentials.rb",
|
95
95
|
"lib/flydata/cron.rb",
|
96
|
+
"lib/flydata/errors.rb",
|
96
97
|
"lib/flydata/fluent-plugins/idle_event_detector.rb",
|
97
98
|
"lib/flydata/fluent-plugins/in_mysql_binlog_flydata.rb",
|
98
99
|
"lib/flydata/fluent-plugins/mysql/alter_table_query_handler.rb",
|
@@ -149,7 +150,7 @@ Gem::Specification.new do |s|
|
|
149
150
|
]
|
150
151
|
s.homepage = "http://flydata.com/"
|
151
152
|
s.licenses = ["All right reserved."]
|
152
|
-
s.rubygems_version = "2.
|
153
|
+
s.rubygems_version = "2.4.3"
|
153
154
|
s.summary = "FlyData Agent"
|
154
155
|
|
155
156
|
if s.respond_to? :specification_version then
|
data/lib/flydata/cli.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'slop'
|
2
2
|
require_relative 'command_logger'
|
3
|
+
require_relative 'errors'
|
3
4
|
|
4
5
|
module Flydata
|
5
6
|
class Cli
|
@@ -42,15 +43,16 @@ module Flydata
|
|
42
43
|
cmd_obj = cmd_cls.new(options)
|
43
44
|
sub_cmd ? cmd_obj.send(sub_cmd,*@args) : cmd_obj.run(*@args)
|
44
45
|
else
|
45
|
-
$stderr.puts usage_text
|
46
|
+
$stderr.puts usage_text
|
46
47
|
return
|
47
48
|
end
|
48
49
|
rescue => e
|
49
50
|
#raise e
|
50
|
-
$stderr.puts "! #{e.to_s}"
|
51
51
|
$stderr.puts
|
52
52
|
$stderr.puts
|
53
|
-
$stderr.puts
|
53
|
+
$stderr.puts "!! #{e.to_s}"
|
54
|
+
$stderr.puts
|
55
|
+
$stderr.puts e.respond_to?(:description) ? e.description : AgentError.description
|
54
56
|
log_error_with_backtrace('Error occured during command.', {error: e, args: @args})
|
55
57
|
raise e if FLYDATA_DEBUG
|
56
58
|
exit 1
|
@@ -93,8 +93,13 @@ What's next?
|
|
93
93
|
elsif has_registered_redshift_mysql_data_entries?
|
94
94
|
de = retrieve_data_entries.first
|
95
95
|
if File.exists?(Flydata::FileUtil::SyncFileManager.new(de).binlog_path)
|
96
|
-
Flydata::Command::Sender.new
|
97
|
-
|
96
|
+
sender = Flydata::Command::Sender.new
|
97
|
+
if sender.process_exist?
|
98
|
+
sender.stop(quiet: true)
|
99
|
+
true
|
100
|
+
else
|
101
|
+
false
|
102
|
+
end
|
98
103
|
else
|
99
104
|
last_message = INITIAL_SYNC_MESSAGE_TEMPLATE
|
100
105
|
false
|
data/lib/flydata/command/sync.rb
CHANGED
@@ -13,9 +13,11 @@ require 'flydata-core/table_def'
|
|
13
13
|
|
14
14
|
module Flydata
|
15
15
|
module Command
|
16
|
+
|
16
17
|
class Sync < Base
|
17
18
|
include Helpers
|
18
19
|
INSERT_PROGRESS_INTERVAL = 1000
|
20
|
+
SERVER_DATA_PROCESSING_TIMEOUT = 600 # seconds
|
19
21
|
|
20
22
|
# for dump.pos file
|
21
23
|
STATUS_PARSING = 'PARSING'
|
@@ -102,8 +104,21 @@ module Flydata
|
|
102
104
|
de = retrieve_sync_data_entry unless de
|
103
105
|
de = load_sync_info(de,tables)
|
104
106
|
validate_initial_sync_status(de, tables)
|
105
|
-
|
106
|
-
|
107
|
+
begin
|
108
|
+
flush_buffer_and_stop unless @initial_sync
|
109
|
+
sync_mysql_to_redshift(de)
|
110
|
+
rescue ServerDataProcessingTimeout => e
|
111
|
+
ee = ServerDataProcessingTimeout.new("Delayed Data Processing")
|
112
|
+
ee.description = <<EOS
|
113
|
+
Data processing is taking more than expected. Please contact support@flydata.com to check the system status.
|
114
|
+
Once checked, you can resume sync with the following command.
|
115
|
+
|
116
|
+
flydata start
|
117
|
+
|
118
|
+
EOS
|
119
|
+
ee.set_backtrace e.backtrace
|
120
|
+
raise ee
|
121
|
+
end
|
107
122
|
complete
|
108
123
|
end
|
109
124
|
|
@@ -114,7 +129,17 @@ module Flydata
|
|
114
129
|
end
|
115
130
|
|
116
131
|
def flush
|
117
|
-
|
132
|
+
begin
|
133
|
+
flush_buffer_and_stop
|
134
|
+
rescue ServerDataProcessingTimeout => e
|
135
|
+
ee = ServerDataProcessingTimeout.new("Delayed Data Processing")
|
136
|
+
ee.description = <<EOS
|
137
|
+
Data processing is taking more than expected. Please contact support@flydata.com to check the system status.
|
138
|
+
|
139
|
+
EOS
|
140
|
+
ee.set_backtrace e.backtrace
|
141
|
+
raise ee
|
142
|
+
end
|
118
143
|
log_info_stdout("Buffers have been flushed and the sender process has been stopped.")
|
119
144
|
end
|
120
145
|
|
@@ -136,7 +161,20 @@ module Flydata
|
|
136
161
|
all_tables = de['mysql_data_entry_preference']['tables']
|
137
162
|
verify_input_tables(tables, all_tables)
|
138
163
|
|
139
|
-
|
164
|
+
begin
|
165
|
+
wait_for_server_buffer(SERVER_DATA_PROCESSING_TIMEOUT)
|
166
|
+
rescue ServerDataProcessingTimeout => e
|
167
|
+
ee = ServerDataProcessingTimeout.new("Delayed Data Processing")
|
168
|
+
ee.description = <<EOS
|
169
|
+
Data processing is taking more than expected. Please contact support@flydata.com to check the system status.
|
170
|
+
Once checked, you can continue sync reset with the following command
|
171
|
+
|
172
|
+
flydata sync:reset #{tables.empty? ? '' : tables.join(" ")}
|
173
|
+
|
174
|
+
EOS
|
175
|
+
ee.set_backtrace e.backtrace
|
176
|
+
raise ee
|
177
|
+
end
|
140
178
|
cleanup_sync_server(de, tables) unless opts.client?
|
141
179
|
sync_fm = Flydata::FileUtil::SyncFileManager.new(de)
|
142
180
|
delete_files = [
|
@@ -158,25 +196,41 @@ module Flydata
|
|
158
196
|
log_info_stdout("Reset completed successfully.")
|
159
197
|
end
|
160
198
|
|
161
|
-
def wait_for_server_buffer
|
199
|
+
def wait_for_server_buffer(timeout = 0)
|
200
|
+
start_time = Time.now
|
162
201
|
log_info_stdout("Waiting for the server buffer to get empty.")
|
202
|
+
prev_message =nil
|
163
203
|
while (status = check) && (status['state'] == 'processing')
|
204
|
+
prev_message = status['message']
|
205
|
+
if timeout > 0 && Time.now - start_time > timeout
|
206
|
+
raise ServerDataProcessingTimeout.new
|
207
|
+
end
|
164
208
|
print_progress(status)
|
165
209
|
sleep 10
|
166
210
|
end
|
167
211
|
end
|
168
212
|
|
169
|
-
def wait_for_server_data_processing
|
213
|
+
def wait_for_server_data_processing(timeout = 0)
|
170
214
|
state = :PROCESS
|
215
|
+
start_time = Time.now
|
171
216
|
log_info_stdout("Uploading data to Redshift...")
|
172
217
|
sleep 10
|
173
218
|
status = nil
|
219
|
+
prev_message =nil
|
174
220
|
while (status = check)
|
175
221
|
if state == :PROCESS && status['state'] == 'uploading'
|
176
222
|
log_info_stdout(" -> Done")
|
177
223
|
state = :UPLOAD
|
178
224
|
log_info_stdout("Finishing data upload...")
|
179
225
|
end
|
226
|
+
if status['message'] != prev_message
|
227
|
+
# making some progress. Reset timer
|
228
|
+
start_time = Time.now
|
229
|
+
end
|
230
|
+
prev_message = status['message']
|
231
|
+
if timeout > 0 && Time.now - start_time > timeout
|
232
|
+
raise ServerDataProcessingTimeout.new
|
233
|
+
end
|
180
234
|
print_progress(status)
|
181
235
|
sleep 10
|
182
236
|
end
|
@@ -606,7 +660,7 @@ EOM
|
|
606
660
|
return unless dump_pos_info[:status] == STATUS_WAITING
|
607
661
|
binlog_pos = dump_pos_info[:binlog_pos]
|
608
662
|
|
609
|
-
wait_for_server_data_processing
|
663
|
+
wait_for_server_data_processing(SERVER_DATA_PROCESSING_TIMEOUT)
|
610
664
|
tables = de['mysql_data_entry_preference']['tables']
|
611
665
|
sync_fm.save_table_binlog_pos(tables, binlog_pos)
|
612
666
|
sync_fm.save_dump_pos(STATUS_COMPLETE, '', -1, binlog_pos)
|
@@ -670,7 +724,7 @@ Thank you for using FlyData!
|
|
670
724
|
def flush_buffer_and_stop
|
671
725
|
sender = Flydata::Command::Sender.new
|
672
726
|
sender.flush_client_buffer
|
673
|
-
wait_for_server_data_processing
|
727
|
+
wait_for_server_data_processing(SERVER_DATA_PROCESSING_TIMEOUT)
|
674
728
|
sender.stop(quiet: true)
|
675
729
|
end
|
676
730
|
end
|
@@ -137,8 +137,8 @@ module Flydata
|
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
|
-
def
|
141
|
-
sys_var_to_check = {'@@binlog_format'=>'ROW', '@@binlog_checksum'=>'NONE', '@@log_bin_use_v1_row_events'=>1}
|
140
|
+
def check_mysql_parameters_compat
|
141
|
+
sys_var_to_check = {'@@binlog_format'=>'ROW', '@@binlog_checksum'=>'NONE', '@@log_bin_use_v1_row_events'=>1, '@@log_slave_updates'=>1}
|
142
142
|
errors={}
|
143
143
|
|
144
144
|
client = Mysql2::Client.new(@db_opts)
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Flydata
|
2
|
+
|
3
|
+
class AgentError < StandardError
|
4
|
+
def self.description
|
5
|
+
text = <<-EOM
|
6
|
+
Fix the issue and try again. If the problem continues, please contact support@flydata.com
|
7
|
+
|
8
|
+
EOM
|
9
|
+
|
10
|
+
flydata_log = File.join(FLYDATA_HOME, 'flydata.log')
|
11
|
+
if File.exists?(flydata_log)
|
12
|
+
text += <<-EOM
|
13
|
+
Also check the Agent log.
|
14
|
+
Log path: #{flydata_log}
|
15
|
+
EOM
|
16
|
+
end
|
17
|
+
text
|
18
|
+
end
|
19
|
+
|
20
|
+
def description
|
21
|
+
if instance_variable_defined?(:@description) && @description
|
22
|
+
@description
|
23
|
+
else
|
24
|
+
self.class.description
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_writer :description
|
29
|
+
end
|
30
|
+
|
31
|
+
class ServerDataProcessingTimeout < AgentError
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -3,6 +3,7 @@ require_relative 'binlog_record_handler'
|
|
3
3
|
module Mysql
|
4
4
|
class DmlRecordHandler < BinlogRecordHandler
|
5
5
|
ROW = :row
|
6
|
+
OLD = :old
|
6
7
|
INTEGER_TYPES = {'TINY' => 1,
|
7
8
|
'SHORT' => 2,
|
8
9
|
'INT24' => 3,
|
@@ -36,7 +37,8 @@ module Mysql
|
|
36
37
|
|
37
38
|
def emit_update(record)
|
38
39
|
emit_rows(:update, record) do |row|
|
39
|
-
|
40
|
+
# For update, row has two arrays (old and new values)
|
41
|
+
{ OLD => row.first, ROW => row.last }
|
40
42
|
end
|
41
43
|
end
|
42
44
|
|
@@ -44,10 +46,13 @@ module Mysql
|
|
44
46
|
emit_record(type, record) do |opt|
|
45
47
|
table_name = record['table_name']
|
46
48
|
records = record["rows"].collect do |row|
|
47
|
-
|
48
|
-
|
49
|
+
row_values = { ROW => row }
|
50
|
+
row_values = yield(row) if block_given? # Give the caller a chance to generate the correct row values
|
51
|
+
row_types = row_values.keys
|
52
|
+
row_kinds = row_types.inject({}) {|m, k| m[k] = convert_to_flydata_row_format(table_name, row_values[k]); m}
|
53
|
+
encode_signless_integer(row_kinds, record["columns"], row_types)
|
54
|
+
row_kinds
|
49
55
|
end
|
50
|
-
encode_signless_integer(records, record["columns"])
|
51
56
|
records
|
52
57
|
end
|
53
58
|
end
|
@@ -70,19 +75,19 @@ module Mysql
|
|
70
75
|
end
|
71
76
|
end
|
72
77
|
|
73
|
-
def encode_signless_integer(
|
74
|
-
|
75
|
-
record[
|
78
|
+
def encode_signless_integer(record, column_types, row_types)
|
79
|
+
row_types.each do |row_type|
|
80
|
+
record[row_type].keys.each do |position|
|
76
81
|
index = position.to_i - 1
|
77
82
|
column_type = column_types[index]
|
78
83
|
if INTEGER_TYPES.keys.include?(column_type)
|
79
84
|
# It's a signless integer.
|
80
|
-
intval = record[
|
85
|
+
intval = record[row_type][position]
|
81
86
|
next unless (intval.kind_of?(Numeric) || intval =~ /^-?[\d]+$/)
|
82
87
|
width = INTEGER_TYPES[column_type] * 2 # * 2 because a single byte requires two characters (e.g. ff)
|
83
88
|
signless_val = SIGNLESS_INTEGER_PREFIX
|
84
89
|
signless_val += sprintf("%0#{width}x", intval).gsub(/\.\.f/, 'f' * width).slice(-width..-1)
|
85
|
-
record[
|
90
|
+
record[row_type][position] = signless_val
|
86
91
|
end
|
87
92
|
end
|
88
93
|
end
|
data/lib/flydata/helpers.rb
CHANGED
@@ -12,25 +12,9 @@ module Flydata
|
|
12
12
|
[klass, method]
|
13
13
|
end
|
14
14
|
|
15
|
-
def usage_text
|
15
|
+
def usage_text
|
16
16
|
text = ""
|
17
17
|
|
18
|
-
if err
|
19
|
-
text += <<-EOM
|
20
|
-
Fix the issue and try again. If the problem continues, please contact support@flydata.com
|
21
|
-
|
22
|
-
EOM
|
23
|
-
|
24
|
-
flydata_log = File.join(FLYDATA_HOME, 'flydata.log')
|
25
|
-
if File.exists?(flydata_log)
|
26
|
-
text += <<-EOM
|
27
|
-
Also check the Agent log.
|
28
|
-
Log path: #{flydata_log}
|
29
|
-
EOM
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
text += ""
|
34
18
|
text += '-' * 64
|
35
19
|
text += "\n"
|
36
20
|
text += <<-EOM
|
data/spec/flydata/cli_spec.rb
CHANGED
@@ -27,7 +27,7 @@ module Flydata
|
|
27
27
|
context 'with options' do
|
28
28
|
let(:options) { %w(-a --host-name localhost) }
|
29
29
|
it 'returns with an error' do
|
30
|
-
expect($stderr).to receive(:puts).with('
|
30
|
+
expect($stderr).to receive(:puts).with('!! Unknown options -a, --host-name').once
|
31
31
|
allow($stderr).to receive(:puts)
|
32
32
|
|
33
33
|
expect{ subject.run }.to terminate.with_code(1)
|
@@ -62,7 +62,7 @@ module Flydata
|
|
62
62
|
context 'with optionss' do
|
63
63
|
let(:options) { %w(-a --host-name localhost) }
|
64
64
|
it 'returns an error' do
|
65
|
-
expect($stderr).to receive(:puts).with('
|
65
|
+
expect($stderr).to receive(:puts).with('!! Unknown options -a, --host-name').once
|
66
66
|
allow($stderr).to receive(:puts)
|
67
67
|
|
68
68
|
expect{ subject.run }.to terminate.with_code(1)
|
@@ -164,9 +164,10 @@ EOT
|
|
164
164
|
rows = [rows] unless rows.kind_of?(Array)
|
165
165
|
@seq ||= TEST_SEQUENCE_NUM
|
166
166
|
records = rows.collect do |row|
|
167
|
+
record = row.kind_of?(Hash) && row.keys.include?(:row) ? row : { row: row }
|
167
168
|
@seq += 1
|
168
|
-
{ :type=>type, :table_name=>table, :respect_order=>true,
|
169
|
-
:src_pos=>"#{binlog_file}\t#{position}", :table_rev=>1
|
169
|
+
record.merge({ :type=>type, :table_name=>table, :respect_order=>true,
|
170
|
+
:seq=>@seq, :src_pos=>"#{binlog_file}\t#{position}", :table_rev=>1 })
|
170
171
|
end
|
171
172
|
expect_emitted_records(event, records)
|
172
173
|
end
|
@@ -289,21 +290,30 @@ EOT
|
|
289
290
|
context 'when received update event' do
|
290
291
|
it do
|
291
292
|
expect_emitted_records_with_rows(update_event, :update, TEST_TABLE, 2528, "mysql-bin.000048",
|
292
|
-
[{"1"=>"0SL00000001", "2"=>"
|
293
|
+
[{old:{"1"=>"0SL00000001", "2"=>"foo"},
|
294
|
+
row:{"1"=>"0SL00000001", "2"=>"wow"}},
|
295
|
+
{old:{"1"=>"0SL00000003", "2"=>"hoge"},
|
296
|
+
row:{"1"=>"0SL00000003", "2"=>"fuga"}}])
|
293
297
|
end
|
294
298
|
end
|
295
299
|
|
296
300
|
context 'when received update event with two byte utf8 chars' do
|
297
301
|
it do
|
298
302
|
expect_emitted_records_with_rows(update_two_byte_event, :update, TEST_TABLE, 2528, "mysql-bin.000048",
|
299
|
-
[{"1"=>"0SL00000001", "2"=>"
|
303
|
+
[{old:{"1"=>"0SL00000001", "2"=>"føø"},
|
304
|
+
row:{"1"=>"0SL00000001", "2"=>"∑ø∑"}},
|
305
|
+
{old:{"1"=>"0SL00000003", "2"=>"høgé"},
|
306
|
+
row:{"1"=>"0SL00000003", "2"=>"fügå"}}])
|
300
307
|
end
|
301
308
|
end
|
302
309
|
|
303
310
|
context 'when received update event with three byte utf8 chars' do
|
304
311
|
it do
|
305
312
|
expect_emitted_records_with_rows(update_three_byte_event, :update, TEST_TABLE, 2528, "mysql-bin.000048",
|
306
|
-
[{"1"=>"0SL00000001", "2"=>"
|
313
|
+
[{old:{"1"=>"0SL00000001", "2"=>"富无无"},
|
314
|
+
row:{"1"=>"0SL00000001", "2"=>"很兴奋"}},
|
315
|
+
{old:{"1"=>"0SL00000003", "2"=>"切实切实"},
|
316
|
+
row:{"1"=>"0SL00000003", "2"=>"興奮虎"}}])
|
307
317
|
end
|
308
318
|
end
|
309
319
|
|
@@ -317,7 +327,7 @@ EOT
|
|
317
327
|
table_rev: 2, # increment revision
|
318
328
|
seq: 2,
|
319
329
|
actions: [{
|
320
|
-
action: :add_column, column: "sum", :type=>'int4', :query=>'add column sum integer'}],
|
330
|
+
action: :add_column, column: "sum", :type=>'int4(11)', :query=>'add column sum integer'}],
|
321
331
|
})
|
322
332
|
end
|
323
333
|
end
|
@@ -395,7 +405,10 @@ EOT
|
|
395
405
|
it 'logs a warning and emits FET with a blank binlog file name, when it receives an update event' do
|
396
406
|
expect($log).to receive(:warn).with("Binlog file name is empty. Rotate event not received!").once
|
397
407
|
expect_emitted_records_with_rows(update_event, :update, TEST_TABLE, 2528, "",
|
398
|
-
[{"1"=>"0SL00000001", "2"=>"
|
408
|
+
[{old:{"1"=>"0SL00000001", "2"=>"foo"},
|
409
|
+
row:{"1"=>"0SL00000001", "2"=>"wow"}},
|
410
|
+
{old:{"1"=>"0SL00000003", "2"=>"hoge"},
|
411
|
+
row:{"1"=>"0SL00000003", "2"=>"fuga"}}])
|
399
412
|
end
|
400
413
|
|
401
414
|
it 'logs a warning emits FET with a blank binlog file name, when it receives a delete event' do
|
@@ -409,7 +422,10 @@ EOT
|
|
409
422
|
expect_emitted_records_with_rows(insert_event, :insert, TEST_TABLE, 628, "",
|
410
423
|
[{"1"=>"0SL00000001", "2"=>"foo"}, {"1"=>"0SL00000002", "2"=>"var"}, {"1"=>"0SL00000003", "2"=>"hoge"}])
|
411
424
|
expect_emitted_records_with_rows(update_event, :update, TEST_TABLE, 2528, "",
|
412
|
-
[{"1"=>"0SL00000001", "2"=>"
|
425
|
+
[{old:{"1"=>"0SL00000001", "2"=>"foo"},
|
426
|
+
row:{"1"=>"0SL00000001", "2"=>"wow"}},
|
427
|
+
{old:{"1"=>"0SL00000003", "2"=>"hoge"},
|
428
|
+
row:{"1"=>"0SL00000003", "2"=>"fuga"}}])
|
413
429
|
expect_emitted_records_with_rows(insert_event, :insert, TEST_TABLE, 628, "",
|
414
430
|
[{"1"=>"0SL00000001", "2"=>"foo"}, {"1"=>"0SL00000002", "2"=>"var"}, {"1"=>"0SL00000003", "2"=>"hoge"}])
|
415
431
|
expect_emitted_records_with_rows(delete_event, :delete, TEST_TABLE, 5324, "",
|
@@ -475,7 +491,7 @@ EOT
|
|
475
491
|
event = update_event
|
476
492
|
event['table_name'] = TEST_TABLE_APPEND_ONLY
|
477
493
|
expect_emitted_records_with_rows(event, :update, TEST_TABLE_APPEND_ONLY, 2528, "mysql-bin.000048",
|
478
|
-
[{"1"=>"0SL00000001", "2"=>"wow"}, {"1"=>"0SL00000003", "2"=>"fuga"}])
|
494
|
+
[{old:{"1"=>"0SL00000001", "2"=>"foo"}, row:{"1"=>"0SL00000001", "2"=>"wow"}}, {old:{"1"=>"0SL00000003", "2"=>"hoge"}, row:{"1"=>"0SL00000003", "2"=>"fuga"}}])
|
479
495
|
end
|
480
496
|
|
481
497
|
it 'emits a record when it receives a delete event for non-append only table' do
|
@@ -136,7 +136,7 @@ describe 'MysqlAlterTableParser' do
|
|
136
136
|
},{
|
137
137
|
action: :add_column,
|
138
138
|
column: "value2",
|
139
|
-
type: "int4",
|
139
|
+
type: "int4(11)",
|
140
140
|
auto_increment: true,
|
141
141
|
query: "add (value1 varchar(26) not null default 'flydata', value2 int auto_increment)"
|
142
142
|
}]
|
@@ -160,7 +160,7 @@ describe 'MysqlAlterTableParser' do
|
|
160
160
|
},{
|
161
161
|
action: :add_column,
|
162
162
|
column: "value2",
|
163
|
-
type: "int4",
|
163
|
+
type: "int4(11)",
|
164
164
|
auto_increment: true,
|
165
165
|
query: "add (`value1` varchar(26) not null default 'flydata', `value2` int auto_increment)"
|
166
166
|
}]
|
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.
|
4
|
+
version: 0.3.0
|
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: 2015-
|
15
|
+
date: 2015-02-11 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: rest-client
|
@@ -496,6 +496,7 @@ files:
|
|
496
496
|
- lib/flydata/compatibility_check.rb
|
497
497
|
- lib/flydata/credentials.rb
|
498
498
|
- lib/flydata/cron.rb
|
499
|
+
- lib/flydata/errors.rb
|
499
500
|
- lib/flydata/fluent-plugins/idle_event_detector.rb
|
500
501
|
- lib/flydata/fluent-plugins/in_mysql_binlog_flydata.rb
|
501
502
|
- lib/flydata/fluent-plugins/mysql/alter_table_query_handler.rb
|
@@ -569,7 +570,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
569
570
|
version: '0'
|
570
571
|
requirements: []
|
571
572
|
rubyforge_project:
|
572
|
-
rubygems_version: 2.
|
573
|
+
rubygems_version: 2.4.3
|
573
574
|
signing_key:
|
574
575
|
specification_version: 4
|
575
576
|
summary: FlyData Agent
|