flydata 0.5.10 → 0.5.11

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9ae9067dda053aa56404eb3260e3518679d787cd
4
- data.tar.gz: f4af787def23a4860a8bbe5ed4619e61bb8abb7e
3
+ metadata.gz: 48cf9129bf088b6ab52c5b1933c344f772cc208d
4
+ data.tar.gz: 577ead8b2fd3962be51b610542ae52030ecd88d0
5
5
  SHA512:
6
- metadata.gz: e6160a696088969741b7fb49cc44c1a7e28cf8af0d839a8fec431b8549ec9ebfc5e54cb4845bfb3ccb789585e5fd9953e75d0fc16136d443c0b251f269aa7af4
7
- data.tar.gz: 6df8c0c9a3bd151d157ba2ac01e1c74757abfb1abc86cc23774b33ddebcc06331f4f7af798a49432af9a6cf0bf750363dc039d8f40f119494cdc0da102eb17ac
6
+ metadata.gz: e6ed2e5faf4aab3e8347b5d56ce7c5fc08e9213e16629fbdd5ab46084ec6a213f1a3917ae308b46d58701c10b2be926d32268416a4a38341198f014700f61349
7
+ data.tar.gz: 38e9f620d6b617cb3461918de1159adfb7a2084f6a3667bb2d7f8f68533d159d13be0ff85b2d08016fe8ef4bbcdb925b212c9ae122b3efd400c1bd6350ea52f8
data/Gemfile.lock CHANGED
@@ -21,7 +21,7 @@ GEM
21
21
  arel (4.0.2)
22
22
  builder (3.1.4)
23
23
  coderay (1.1.0)
24
- cool.io (1.2.4)
24
+ cool.io (1.4.1)
25
25
  diff-lcs (1.2.5)
26
26
  faraday (0.8.9)
27
27
  multipart-post (~> 1.2.0)
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.10
1
+ 0.5.11
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.10 ruby lib
5
+ # stub: flydata 0.5.11 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "flydata"
9
- s.version = "0.5.10"
9
+ s.version = "0.5.11"
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-10-04"
14
+ s.date = "2015-10-06"
15
15
  s.description = "FlyData Agent"
16
16
  s.email = "sysadmin@flydata.com"
17
17
  s.executables = ["fdmysqldump", "flydata", "serverinfo"]
@@ -140,6 +140,7 @@ Gem::Specification.new do |s|
140
140
  "lib/flydata/fluent-plugins/mysql/context.rb",
141
141
  "lib/flydata/fluent-plugins/mysql/ddl_query_handler.rb",
142
142
  "lib/flydata/fluent-plugins/mysql/dml_record_handler.rb",
143
+ "lib/flydata/fluent-plugins/mysql/drop_database_query_handler.rb",
143
144
  "lib/flydata/fluent-plugins/mysql/table_meta.rb",
144
145
  "lib/flydata/fluent-plugins/mysql/truncate_table_query_handler.rb",
145
146
  "lib/flydata/fluent-plugins/out_forward_ssl.rb",
@@ -205,6 +206,7 @@ Gem::Specification.new do |s|
205
206
  "spec/flydata/fluent-plugins/mysql/binlog_query_dispatcher_spec.rb",
206
207
  "spec/flydata/fluent-plugins/mysql/ddl_query_handler_spec.rb",
207
208
  "spec/flydata/fluent-plugins/mysql/dml_record_handler_spec.rb",
209
+ "spec/flydata/fluent-plugins/mysql/drop_database_query_handler_spec.rb",
208
210
  "spec/flydata/fluent-plugins/mysql/shared_query_handler_context.rb",
209
211
  "spec/flydata/fluent-plugins/mysql/table_meta_spec.rb",
210
212
  "spec/flydata/fluent-plugins/mysql/truncate_query_handler_spec.rb",
@@ -236,7 +238,7 @@ Gem::Specification.new do |s|
236
238
  ]
237
239
  s.homepage = "http://flydata.com/"
238
240
  s.licenses = ["All right reserved."]
239
- s.rubygems_version = "2.4.3"
241
+ s.rubygems_version = "2.4.6"
240
242
  s.summary = "FlyData Agent"
241
243
 
242
244
  if s.respond_to? :specification_version then
@@ -1348,7 +1348,8 @@ Thank you for using FlyData!
1348
1348
  # from 'table.binlog.pos.init' file.
1349
1349
  def populate_initial_binlog_positions(table_status_hash, sync_fm)
1350
1350
  table_status_hash.keys.each do |table|
1351
- if table_status_hash[table]["src_pos"] == "-"
1351
+ src_pos = table_status_hash[table]["src_pos"]
1352
+ if src_pos.nil? || src_pos == "-"
1352
1353
  init_binlog_pos = sync_fm.get_table_binlog_pos_init(table)
1353
1354
  unless init_binlog_pos
1354
1355
  raise "File `#{table}.binlog.pos.init` is missing"
@@ -281,12 +281,16 @@ EOS
281
281
  @idle_event_detector.stop
282
282
  if @thread and @thread.alive?
283
283
  $log.info "Requesting stop Kodama"
284
- @kodama_client.stop_request
285
- if wait_till_safe_to_stop
286
- $log.info "Killing Kodama client"
287
- Thread.kill(@thread)
288
- else
289
- $log.error "Unable to stop Kodama"
284
+ begin
285
+ @kodama_client.stop_request
286
+ if wait_till_safe_to_stop
287
+ $log.info "Killing Kodama client"
288
+ Thread.kill(@thread)
289
+ else
290
+ $log.error "Unable to stop Kodama"
291
+ end
292
+ rescue => e
293
+ $log.warn "an error occurred during Kodama shutdown. error:'#{e.to_s}'\n#{e.backtrace.join("\n")}"
290
294
  end
291
295
  end
292
296
  @sync_fm.close
@@ -1,5 +1,6 @@
1
1
  require 'flydata/fluent-plugins/mysql/alter_table_query_handler'
2
2
  require 'flydata/fluent-plugins/mysql/truncate_table_query_handler'
3
+ require 'flydata/fluent-plugins/mysql/drop_database_query_handler'
3
4
 
4
5
  module Mysql
5
6
  class BinlogQueryDispatcher
@@ -58,6 +59,7 @@ module Mysql
58
59
  @handlers = [
59
60
  AlterTableQueryHandler.new(context),
60
61
  TruncateTableQueryHandler.new(context),
62
+ DropDatabaseQueryHandler.new(context),
61
63
  ]
62
64
  end
63
65
  end
@@ -4,14 +4,8 @@ require 'flydata/mysql/binlog_position'
4
4
  require 'flydata-core/record/record'
5
5
 
6
6
  module Mysql
7
+
7
8
  class BinlogRecordHandler
8
- TABLE_NAME = :table_name # A Flydata JSON tag to specify a table name
9
- TYPE = :type
10
- SEQ = :seq
11
- RESPECT_ORDER = :respect_order
12
- SRC_POS = :src_pos
13
- TABLE_REV = :table_rev
14
- V = :v # FlyData record format version
15
9
 
16
10
  def initialize(context)
17
11
  @context = context
@@ -59,7 +53,7 @@ module Mysql
59
53
 
60
54
  def emit_record(type, record)
61
55
  return unless acceptable_db?(record)
62
- return unless record["table_name"].nil? or acceptable_table?(record, record["table_name"])
56
+ return if record["table_name"] and not acceptable_table?(record, record["table_name"])
63
57
 
64
58
  check_empty_binlog
65
59
 
@@ -68,47 +62,135 @@ module Mysql
68
62
  return if records.nil? # skip
69
63
  records = [records] unless records.kind_of?(Array)
70
64
 
71
- table = records.first[TABLE_NAME] || record['table_name']
72
- raise "Missing table name. #{record}" if table.to_s.empty?
73
- return unless acceptable_table?(record, table) && acceptable_event?(type, table)
65
+ FlydataJsonHandlerFactory.create(records, record, @context, type, opt[:increment_table_rev])
66
+ end
74
67
 
75
- table_rev = @context.table_revs[table]
76
- position = record['next_position'] - record['event_length']
68
+ def check_empty_binlog
69
+ #Log one warning per consecutive records that have empty binlog filename
70
+ if @context.current_binlog_file.to_s.empty?
71
+ if @first_empty_binlog
72
+ $log.warn "Binlog file name is empty. Rotate event not received!"
73
+ @first_empty_binlog = false
74
+ end
75
+ else
76
+ @first_empty_binlog = true
77
+ end
78
+ end
79
+ end
80
+ class FlydataJsonHandlerFactory
81
+
82
+ def self.create(records, record, context, type, increment_table_rev)
83
+ table = records.first[:table_name] || record['table_name']
84
+ database = records.first[:db_name] || record['db_name']
85
+
86
+ case table
87
+ when nil
88
+ DatabaseFlydataJsonHandler.new(records, record, context, type)
89
+ else
90
+ TableFlydataJsonHandler.new(records, record, context, type, increment_table_rev)
91
+ end
92
+ end
77
93
 
78
- # Add common information to each record
79
- records.each do |r|
80
- if opt[:increment_table_rev]
81
- table_rev = @context.sync_fm.increment_table_rev(table, table_rev)
82
- @context.table_revs[table] = table_rev
94
+ class FlydataJsonHandler
95
+ TABLE_NAME = :table_name # A Flydata JSON tag to specify a table name
96
+ TYPE = :type
97
+ SEQ = :seq
98
+ RESPECT_ORDER = :respect_order
99
+ SRC_POS = :src_pos
100
+ TABLE_REV = :table_rev
101
+ V = :v # FlyData record format version
102
+ DB_NAME = :db_name
103
+
104
+ def initialize(records, record, context, type, increment_table_rev=nil)
105
+ @context = context
106
+ end
107
+
108
+ def emit(timestamp, row)
109
+ end
110
+ end
111
+
112
+ class TableFlydataJsonHandler < FlydataJsonHandler
113
+ def initialize(records, record, context, type, increment_table_rev=nil)
114
+ super
115
+ table = records.first[TABLE_NAME] || record['table_name']
116
+ raise "Missing table name. #{record}" if table.to_s.empty?
117
+
118
+ return unless acceptable_event?(type, table)
119
+
120
+ table_rev = @context.table_revs[table]
121
+ position = record['next_position'] - record['event_length']
122
+
123
+ # Add common information to each record
124
+ records.each do |r|
125
+ if increment_table_rev
126
+ table_rev = @context.sync_fm.increment_table_rev(table, table_rev)
127
+ @context.table_revs[table] = table_rev
128
+ end
129
+ r[TYPE] = type
130
+ r[RESPECT_ORDER] = true
131
+ r[TABLE_NAME] = table
132
+ r[SRC_POS] = "#{@context.current_binlog_file}\t#{position}"
133
+ r[TABLE_REV] = table_rev
134
+ r[V] = FlydataCore::Record::V2
135
+ end
136
+
137
+ # Use binlog's timestamp
138
+ timestamp = record["timestamp"].to_i
139
+ records.each do |row|
140
+ emit(timestamp, row)
83
141
  end
84
- r[TYPE] = type
85
- r[RESPECT_ORDER] = true
86
- r[TABLE_NAME] = table
87
- r[SRC_POS] = "#{@context.current_binlog_file}\t#{position}"
88
- r[TABLE_REV] = table_rev
89
- r[V] = FlydataCore::Record::V2
90
142
  end
91
143
 
92
- # Use binlog's timestamp
93
- timestamp = record["timestamp"].to_i
94
- records.each do |row|
144
+ def emit(timestamp, row)
95
145
  @context.sync_fm.increment_and_save_table_position(row[TABLE_NAME]) do |seq|
96
146
  row[SEQ] = seq
97
147
  Fluent::Engine.emit(@context.tag, timestamp, row)
98
148
  end
99
149
  end
150
+
151
+ private
152
+ def acceptable_event?(type, table)
153
+ @context.omit_events[table].nil? || !@context.omit_events[table].include?(type)
154
+ end
155
+
100
156
  end
101
157
 
102
- def check_empty_binlog
103
- #Log one warning per consecutive records that have empty binlog filename
104
- if @context.current_binlog_file.to_s.empty?
105
- if @first_empty_binlog
106
- $log.warn "Binlog file name is empty. Rotate event not received!"
107
- @first_empty_binlog = false
158
+ class DatabaseFlydataJsonHandler < FlydataJsonHandler
159
+ def initialize(records, record, context, type, increment_table_rev=nil)
160
+ super
161
+ database = records.first[DB_NAME] || record['db_name']
162
+
163
+ return unless acceptable_event?(type)
164
+
165
+ position = record['next_position'] - record['event_length']
166
+
167
+ # Add common information to each record
168
+ records.each do |r|
169
+ r[TYPE] = type
170
+ r[RESPECT_ORDER] = true
171
+ r[SRC_POS] = "#{@context.current_binlog_file}\t#{position}"
172
+ r[V] = FlydataCore::Record::V2
108
173
  end
109
- else
110
- @first_empty_binlog = true
174
+
175
+ # Use binlog's timestamp
176
+ timestamp = record["timestamp"].to_i
177
+ records.each do |row|
178
+ emit(timestamp, row)
179
+ end
180
+ end
181
+
182
+ def emit(timestamp, row)
183
+ Fluent::Engine.emit(@context.tag, timestamp, row)
184
+ end
185
+
186
+ private
187
+ #TODO: No support on DS for database records currently so no record should be emitted
188
+ def acceptable_event?(type)
189
+ false
111
190
  end
191
+
112
192
  end
193
+
113
194
  end
195
+
114
196
  end
@@ -0,0 +1,22 @@
1
+ require 'flydata/parser_provider'
2
+ require 'flydata/fluent-plugins/mysql/ddl_query_handler'
3
+
4
+ module Mysql
5
+ class DropDatabaseQueryHandler < DdlQueryHandler
6
+ # For MySQL, database and schema are exchangable
7
+ PATTERN = /^DROP DATABASE|SCHEMA/i
8
+
9
+ def initialize(context)
10
+ super
11
+ end
12
+
13
+ def pattern
14
+ PATTERN
15
+ end
16
+
17
+ def process(record)
18
+ $log.warn("DROP DATABASE detected. A full re-sync is required to provide sync consistency")
19
+ #NOTE: No emit_record here because this record should not be sent to data servers for now
20
+ end
21
+ end
22
+ end
@@ -6,9 +6,14 @@ module Flydata
6
6
  module Helper
7
7
  module Action
8
8
  class CheckRemoteActions < BaseAction
9
+ include FlydataCore::Logger
10
+
11
+ MAX_ERROR_RETRY = 20
12
+
9
13
  def initialize(config)
10
14
  super
11
15
  @api_client = ApiClient.instance
16
+ @retry_count = 0
12
17
  end
13
18
 
14
19
  def execute(opts = {})
@@ -16,7 +21,20 @@ module Flydata
16
21
 
17
22
  # Get actions from flydata web server
18
23
  last_id = action_position.load
19
- actions = @api_client.agent.actions(last_id)
24
+ actions = nil
25
+ begin
26
+ actions = @api_client.agent.actions(last_id)
27
+ @retry_count = 0
28
+ rescue => e
29
+ if @retry_count >= MAX_ERROR_RETRY
30
+ @retry_count = 0
31
+ raise
32
+ else
33
+ @retry_count += 1
34
+ log_warn "Failed to get actions with error '#{e.to_s}'. Wait for the next turn."
35
+ actions = {'actions' => []}
36
+ end
37
+ end
20
38
 
21
39
  actions['actions'].each do |action|
22
40
  action_name = action['name']
@@ -59,6 +59,11 @@ EOT
59
59
  allow(r).to receive(:pattern).and_return(Mysql::TruncateTableQueryHandler::PATTERN)
60
60
  r
61
61
  end
62
+ let(:drop_database_query_handler) do
63
+ r = double('drop_database_query_handler')
64
+ allow(r).to receive(:pattern).and_return(Mysql::DropDatabaseQueryHandler::PATTERN)
65
+ r
66
+ end
62
67
  let(:context) { double('context') }
63
68
  let(:subject_object) { described_class.new(context) }
64
69
  subject { subject_object }
@@ -73,6 +78,7 @@ EOT
73
78
  before do
74
79
  expect(AlterTableQueryHandler).to receive(:new).with(context).and_return(alter_query_handler)
75
80
  expect(TruncateTableQueryHandler).to receive(:new).with(context).and_return(truncate_query_handler)
81
+ expect(DropDatabaseQueryHandler).to receive(:new).with(context).and_return(drop_database_query_handler)
76
82
  end
77
83
 
78
84
  describe '#dispatch' do
@@ -198,6 +204,30 @@ EOS
198
204
  it_behaves_like "a dispatcher that calls query handler with correct query"
199
205
  end
200
206
  end
207
+ context "drop database queries" do
208
+ let(:correct_query_handler) { drop_database_query_handler }
209
+
210
+ shared_examples "drop database tests" do
211
+ context "drop database query" do
212
+ let(:query) { "DROP DATABASE #{db_name};" }
213
+ let(:normalized_query) { "DROP DATABASE #{db_name};" }
214
+ it_behaves_like "a dispatcher that calls query handler with correct query"
215
+ end
216
+
217
+ context "drop schema query" do
218
+ let(:query) { "DROP SCHEMA #{db_name};" }
219
+ let(:normalized_query) { "DROP SCHEMA #{db_name};" }
220
+ it_behaves_like "a dispatcher that calls query handler with correct query"
221
+ end
222
+ end
223
+
224
+ context "without table key word" do
225
+ let(:db_name) { "foo" }
226
+ include_examples "drop database tests"
227
+ end
228
+
229
+ end
230
+
201
231
  context "truncate table queries" do
202
232
  let(:correct_query_handler) { truncate_query_handler }
203
233
 
@@ -0,0 +1,56 @@
1
+ require 'fluent_plugins_spec_helper'
2
+ require 'flydata/fluent-plugins/mysql/drop_database_query_handler'
3
+ require 'flydata/fluent-plugins/mysql/shared_query_handler_context'
4
+
5
+ module Mysql
6
+ describe DropDatabaseQueryHandler do
7
+ include_context "query handler context"
8
+
9
+ describe '#process' do
10
+ let(:drop_database_query) { "DROP database foo" }
11
+
12
+ before do
13
+ allow(record).to receive(:[]).with("query").and_return(drop_database_query)
14
+ allow(record).to receive(:[]).with("normalized_query").and_return(drop_database_query)
15
+ end
16
+
17
+ shared_examples "process drop database queries correctly" do
18
+ let(:expected_record) do
19
+ {
20
+ query: drop_database_query,
21
+ type: :drop_database,
22
+ respect_order: true,
23
+ src_pos: "#{current_binlog_file}\t#{next_position - event_length}",
24
+ v: flydata_record_version
25
+ }
26
+ end
27
+
28
+ context "for the registered database" do
29
+ it "should call Fluent's emit with appropriate params" do
30
+ # Should mock up the method to return true
31
+ #expect(Fluent::Engine).to receive(:emit).with(tag, timestamp, expected_record)
32
+ expect(Fluent::Engine).to receive(:emit).never
33
+ expect($log).to receive(:warn)
34
+ expect(subject.process(record))
35
+ end
36
+ end
37
+ end
38
+
39
+ shared_examples "skip processing queries" do
40
+ it "should not call Fluent's emit" do
41
+ expect(Fluent::Engine).to receive(:emit).never
42
+ subject.process(record)
43
+ end
44
+ end
45
+
46
+ context "drop database queries with database keyword" do
47
+ let(:drop_database_query) { "DROP DATABASE foo" }
48
+ include_examples "process drop database queries correctly"
49
+ end
50
+ context "drop database queries with schema keyword" do
51
+ let(:drop_database_query) { "DROP SCHEMA foo" }
52
+ include_examples "process drop database queries correctly"
53
+ end
54
+ end
55
+ end
56
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flydata
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.10
4
+ version: 0.5.11
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-10-04 00:00:00.000000000 Z
15
+ date: 2015-10-06 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rest-client
@@ -577,6 +577,7 @@ files:
577
577
  - lib/flydata/fluent-plugins/mysql/context.rb
578
578
  - lib/flydata/fluent-plugins/mysql/ddl_query_handler.rb
579
579
  - lib/flydata/fluent-plugins/mysql/dml_record_handler.rb
580
+ - lib/flydata/fluent-plugins/mysql/drop_database_query_handler.rb
580
581
  - lib/flydata/fluent-plugins/mysql/table_meta.rb
581
582
  - lib/flydata/fluent-plugins/mysql/truncate_table_query_handler.rb
582
583
  - lib/flydata/fluent-plugins/out_forward_ssl.rb
@@ -642,6 +643,7 @@ files:
642
643
  - spec/flydata/fluent-plugins/mysql/binlog_query_dispatcher_spec.rb
643
644
  - spec/flydata/fluent-plugins/mysql/ddl_query_handler_spec.rb
644
645
  - spec/flydata/fluent-plugins/mysql/dml_record_handler_spec.rb
646
+ - spec/flydata/fluent-plugins/mysql/drop_database_query_handler_spec.rb
645
647
  - spec/flydata/fluent-plugins/mysql/shared_query_handler_context.rb
646
648
  - spec/flydata/fluent-plugins/mysql/table_meta_spec.rb
647
649
  - spec/flydata/fluent-plugins/mysql/truncate_query_handler_spec.rb
@@ -690,7 +692,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
690
692
  version: '0'
691
693
  requirements: []
692
694
  rubyforge_project:
693
- rubygems_version: 2.4.3
695
+ rubygems_version: 2.4.6
694
696
  signing_key:
695
697
  specification_version: 4
696
698
  summary: FlyData Agent