flydata 0.5.10 → 0.5.11

Sign up to get free protection for your applications and to get access to all the features.
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