flydata 0.6.0 → 0.6.1

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: 6afa928a6d8e0ee05f33e9a14d81be9659164e8f
4
- data.tar.gz: d6323ad8aa4f7d04cee5263b92e19b3208c8c651
3
+ metadata.gz: 4ab029d2a33bb77838fe20cf625de7f473efdb30
4
+ data.tar.gz: 8313b3c85c3f98201194fd33b68b60cab15c9417
5
5
  SHA512:
6
- metadata.gz: c273cafd862d6eab962afe5594b7b7b3f72c5536a39b6e6825c98418ee3589e61005a42b4aa77503f3fcbd3d0011ddf550072550f60ba91c6f34c5e9d18bc52d
7
- data.tar.gz: 951b50b74c206488fba05241722c09f7bb5f531b8e2097e2cf810bd6cdd863fb1f83471289287f347d1679e4d8ab4f96d27870f535031ea2e4375c3014b7d9ed
6
+ metadata.gz: 0b2b0a184db03ca9d157ee044b349cdf7ab1c94e5338d536ad51c3be474c8cc6363809646c48406578363901917ac9bb453f0426e461f143b7685d51c95edbde
7
+ data.tar.gz: b7adf39c00e853819265dfc598b4873aef9e469afadd457dc729fce00f682fe1924321f1bd2a361707db7099a96c040300df9b31d2f4ae2a04840151681ed579
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.6.0
1
+ 0.6.1
@@ -247,23 +247,24 @@ static VALUE rb_json_generate_kv_pairs(VALUE self, VALUE key_ary, VALUE value_ar
247
247
  rb_raise(rb_eArgError, "length of arrays must match");
248
248
  }
249
249
 
250
- std::stringstream ss;
250
+ std::stringstream* ss = new std::stringstream();
251
251
 
252
- ss << "{";
252
+ *ss << "{";
253
253
 
254
254
  for (long i = 0; i < key_len; i++)
255
255
  {
256
- if (i > 0) { ss << ","; }
256
+ if (i > 0) { *ss << ","; }
257
257
 
258
258
  VALUE key = rb_ary_entry(key_ary, i);
259
259
  VALUE value = rb_ary_entry(value_ary, i);
260
260
 
261
- add_kv_pair(key, value, ss);
261
+ add_kv_pair(key, value, *ss);
262
262
  }
263
- ss << "}";
263
+ *ss << "}";
264
264
 
265
- const std::string& str = ss.str();
265
+ const std::string& str = ss->str();
266
266
  VALUE json = rb_str_new(str.data(), str.size());
267
+ delete ss; ss = 0;
267
268
  int enc = rb_enc_find_index("UTF-8");
268
269
  rb_enc_associate_index(json, enc);
269
270
 
@@ -0,0 +1,10 @@
1
+ module FlydataCore
2
+ module Event
3
+ #Nouns
4
+ INIT_SYNC = "init_sync"
5
+
6
+ #Verbs
7
+ STARTED = "started"
8
+ FINISHED = "finished"
9
+ end
10
+ end
@@ -11,6 +11,7 @@ module FlydataCore
11
11
  end
12
12
 
13
13
  protected
14
+
14
15
  def self.register_handler(opts)
15
16
  @noun = opts[:noun]
16
17
  @verb = opts[:verb] || EVENT_VERB_ANY
@@ -21,6 +22,7 @@ module FlydataCore
21
22
  end
22
23
 
23
24
  private
25
+
24
26
  def self.handlers(noun, verb)
25
27
  handlers = (@@handlers_hash[key(noun, verb)] || []).clone
26
28
 
@@ -6,23 +6,44 @@ module FlydataCore
6
6
  class FlydataEvent
7
7
  attr_accessor :noun
8
8
  attr_accessor :verb
9
- attr_accessor :data
9
+ attr_accessor :data #recommended that it be a hash
10
10
  attr_accessor :id
11
11
  attr_accessor :created
12
12
  attr_accessor :data_entry_id
13
13
  attr_accessor :data_port_id
14
14
 
15
- def initialize (noun, verb, data=nil, de_id=nil,dp_id=nil, id=nil, timestamp=nil)
15
+ # params:
16
+ # data_port_id: nil,
17
+ # data_entry_id: nil,
18
+ # id: nil,
19
+ # data: nil,
20
+ # timestamp: nil
21
+ def initialize (noun, verb, params = {})
22
+ params ||= {}
23
+
16
24
  @noun = noun
17
25
  @verb = verb
18
- @data_entry_id = de_id
19
- @data_port_id = dp_id
20
- @data = data
21
- @id = id.nil? ? SecureRandom.uuid: id
22
- @created = timestamp.nil? ? Time.now : timestamp
26
+ @data_entry_id = params[:data_entry_id] ? params[:data_entry_id].to_i : nil
27
+ @data_port_id = params[:data_port_id] ? params[:data_port_id].to_i : nil
28
+ @data = params[:data]
29
+ @id = params[:id].nil? ? SecureRandom.uuid : params[:id]
30
+ @created = params[:timestamp].nil? ? Time.now : params[:timestamp]
31
+ end
32
+
33
+ def to_h
34
+ {
35
+ noun: @noun,
36
+ verb: @verb,
37
+ data_entry_id: @data_entry_id,
38
+ data_port_id: @data_port_id,
39
+ id: @id,
40
+ created: @created,
41
+ data: @data,
42
+ }
23
43
  end
44
+
24
45
  def to_json
25
- {:noun => @noun, :verb => @verb, :data_entry_id=>@data_entry_id, :data_port_id=> @data_port_id, id => @id, :created => @created, :data => @data}.to_json
46
+ to_h.to_json
26
47
  end
27
48
  end
28
49
  end
@@ -3,7 +3,6 @@ require 'flydata-core/event/flydata_event_handler_registry'
3
3
  module FlydataCore
4
4
  module Event
5
5
  class FlydataEventProcessor
6
-
7
6
  def self.process(event)
8
7
  handlers = FlydataEventHandlerRegistry.handlers(event.noun, event.verb)
9
8
  if handlers.nil? || handlers.empty?
@@ -14,6 +13,5 @@ module FlydataCore
14
13
  end
15
14
  end
16
15
  end
17
-
18
16
  end
19
17
  end
@@ -4,20 +4,24 @@ module FlydataCore
4
4
  module Event
5
5
 
6
6
  class FlydataEventSender
7
-
8
- def send_event(noun, verb, data=nil, data_entry_id=nil, data_port_id=nil, routing_key="default")
9
- event = FlydataEvent.new(noun, verb, data, data_entry_id, data_port_id)
7
+ def send_event(noun, verb, params = {})
8
+ params ||= {}
9
+ routing_key = params[:routing_key] || 'default'
10
+ event = FlydataEvent.new(noun, verb, params)
10
11
  send(event, routing_key)
11
12
  end
12
13
 
13
14
  protected
15
+
14
16
  def send(event, routing_key)
15
17
  raise "send method not implemented"
16
18
  end
17
19
  end
18
20
 
19
21
  class SimpleEventSender <FlydataEventSender
22
+
20
23
  protected
24
+
21
25
  def send(event, routing_key)
22
26
  FlydataEventProcessor.process(event)
23
27
  end
@@ -109,19 +109,13 @@ module FlydataCore
109
109
  msg = build_log_message(level, message, log_params, options)
110
110
  before_logging(level, message, msg, log_params, options)
111
111
  logger = get_logger(options)
112
- set_mutex(logger)
113
- logger.mutex.synchronize do
114
- original_depth_offset = nil
115
- if logger.instance_variable_defined? :@depth_offset
116
- original_depth_offset = logger.instance_variable_get(:@depth_offset)
117
- depth_offset = 3 # log_common + synchronize + synchronized block
118
- depth_offset += options[:depth_offset] if options.has_key?(:depth_offset)
119
- logger.instance_variable_set(:@depth_offset, original_depth_offset + depth_offset)
120
- end
112
+ # For patched Fluent::Log
113
+ if logger.respond_to? :flydata_patched
114
+ depth_offset = 2 # original_depth_offset + log_common
115
+ depth_offset += options[:depth_offset] if options.has_key?(:depth_offset)
116
+ logger.send(level, msg, depth_offset: depth_offset)
117
+ else
121
118
  logger.send(level, msg)
122
- if original_depth_offset
123
- logger.instance_variable_set(:@depth_offset, original_depth_offset)
124
- end
125
119
  end
126
120
  end
127
121
 
@@ -154,17 +148,6 @@ module FlydataCore
154
148
  options[:logger] || logger || log_context_logger || $log
155
149
  end
156
150
 
157
- # set mutex if logger doesn't have one
158
- def set_mutex(logger)
159
- return if logger.respond_to?(:mutex)
160
-
161
- mtx = Mutex.new
162
- logger.instance_variable_set(:@mutex, mtx)
163
- class << logger
164
- attr_reader :mutex
165
- end
166
- end
167
-
168
151
  def build_log_message(level, raw_message, log_params = {}, options = {})
169
152
  message = raw_message.dup
170
153
  # check keys
@@ -9,7 +9,7 @@ module FlydataCore
9
9
  describe "#process" do
10
10
 
11
11
  context "when event has one verb handler and one any verb handler," do
12
- let(:event) {FlydataEvent.new("test2","testing",nil, 1)}
12
+ let(:event) {FlydataEvent.new("test2", "testing", id: 1)}
13
13
  it "should call both handlers" do
14
14
  expect(AnyHandler).to receive(:handle).with(event)
15
15
  expect(Handler3).to receive(:handle).with(event)
@@ -18,7 +18,7 @@ module FlydataCore
18
18
  end
19
19
 
20
20
  context "when event has two handlers," do
21
- let(:event) {FlydataEvent.new("test","testing",nil, 1)}
21
+ let(:event) {FlydataEvent.new("test","testing", id: 1)}
22
22
  it "should call both handlers" do
23
23
  expect(Handler1).to receive(:handle).with(event)
24
24
  expect(Handler2).to receive(:handle).with(event)
@@ -11,7 +11,7 @@ module FlydataCore
11
11
 
12
12
  context "#send_event" do
13
13
  subject{
14
- send_event("test","testing",nil, 1)
14
+ send_event("test","testing", id: 1)
15
15
  }
16
16
  it "should raise exception" do
17
17
  expect { raise Exception}
@@ -5,34 +5,43 @@ module FlydataCore
5
5
  module Event
6
6
  describe FlydataEvent do
7
7
  describe "#initialize" do
8
- let(:noun){"test"}
9
- let(:verb){"testing"}
10
- let(:data){{test:123}}
8
+ let(:noun) { "test" }
9
+ let(:verb) { "testing" }
10
+ let(:data) { { 'tables' => %w(table_a table_b) } }
11
11
 
12
- context "when noun and verb are passed" do
13
- it {
14
- event = FlydataEvent.new(noun,verb, nil,1)
15
- expect(event.noun).to eql(noun)
16
- expect(event.verb).to eql(verb)
17
- expect(event.data).to be_nil
18
- expect(event.id).not_to be_nil
12
+ context 'when all parameters are given' do
13
+ let(:parameters) do
14
+ { data_entry_id: 1,
15
+ data_port_id: 2,
16
+ data: data,
17
+ id: 12,
18
+ created: Time.now + 60, }
19
+ end
20
+
21
+ it 'sets given data to instance variables' do
22
+ event = FlydataEvent.new(noun, verb, parameters)
23
+ expect(event.noun).to eq(noun)
24
+ expect(event.verb).to eq(verb)
25
+ expect(event.data).to eq(data)
26
+ expect(event.id).to eq(12)
19
27
  expect(event.data_entry_id).to eql(1)
20
- expect(event.created).not_to be_nil
21
- }
28
+ expect(event.data_port_id).to eql(2)
29
+ expect(event.created).to be_kind_of(Time)
30
+ end
22
31
  end
23
32
 
24
- context "when noun, verb and data are passed" do
25
- it {
26
- event = FlydataEvent.new(noun,verb,data,1)
27
- expect(event.noun).to eql(noun)
28
- expect(event.verb).to eql(verb)
29
- expect(event.data).to eql(data)
30
- expect(event.data_entry_id).to eql(1)
33
+ context 'when parameters are empty' do
34
+ it 'sets default or nil to instance variables' do
35
+ event = FlydataEvent.new(noun, verb)
36
+ expect(event.noun).to eq(noun)
37
+ expect(event.verb).to eq(verb)
38
+ expect(event.data).to be_nil
31
39
  expect(event.id).not_to be_nil
40
+ expect(event.data_entry_id).to be_nil
41
+ expect(event.data_port_id).to be_nil
32
42
  expect(event.created).not_to be_nil
33
- }
43
+ end
34
44
  end
35
-
36
45
  end
37
46
  end
38
47
  end
Binary file
@@ -6,13 +6,13 @@ module Flydata
6
6
  module Command
7
7
  class Restart < Base
8
8
  def self.slop
9
- Slop.new do
10
- on 'skip-helper', 'Skip restarting the Helper'
11
- end
9
+ sender_opts = Flydata::Command::Sender.slop_start # Needs options for Sender#start
10
+ sender_opts.on 'skip-helper', 'Skip starting the Helper'
11
+ sender_opts
12
12
  end
13
13
 
14
14
  def run
15
- sender = Flydata::Command::Sender.new
15
+ sender = Flydata::Command::Sender.new(opts)
16
16
  sender.restart
17
17
  unless opts.skip_helper?
18
18
  helper = Flydata::Command::Helper.new
@@ -8,6 +8,7 @@ module Flydata
8
8
  def self.slop_start
9
9
  Slop.new do
10
10
  on 'n', 'no-daemon', 'Start FlyData agent as a regular program'
11
+ on 'e', 'no-email', 'Skip sending init-sync-start notification email'
11
12
  end
12
13
  end
13
14
  def start(options_or_show_final_message = {show_final_message: true}) # For backward compatibility. Use only as options going forward
@@ -58,7 +59,8 @@ module Flydata
58
59
  # surpress messages if fluentd is started in #try_mysql_sync
59
60
  options[:quiet] = true
60
61
  Flydata::Command::Sync.new.try_mysql_sync(
61
- binlog_ready_callback: start_fluentd)
62
+ binlog_ready_callback: start_fluentd,
63
+ no_email: opts.no_email?)
62
64
  options[:quiet] = quiet_option
63
65
  start_fluentd.call unless fluentd_started
64
66
  if options[:show_final_message] && !options[:quiet]
@@ -20,6 +20,7 @@ require 'flydata-core/mysql/binlog_pos'
20
20
  require 'flydata/mysql/table_ddl'
21
21
  require 'flydata-core/mysql/command_generator'
22
22
  require 'flydata/event/api_event_sender'
23
+ require 'flydata-core/event/event_dictionary'
23
24
  require 'sigdump/setup'
24
25
  #require 'ruby-prof' # to enable profiling, also set the class' RUN_PROFILE
25
26
 
@@ -150,7 +151,7 @@ EOS
150
151
  log_info_stdout <<EOS
151
152
  ERROR! You cannot reset tables because the previous initial sync has not been completed. Reset the unfinished initial sync first with the following command:
152
153
 
153
- flyudata sync:reset --init
154
+ flydata sync:reset --init
154
155
  EOS
155
156
  return
156
157
  end
@@ -672,9 +673,14 @@ EOM
672
673
  log_info_stdout("This process can take hours depending on data size and load on your database. Please be patient...")
673
674
  sync_fm.save_sync_info(@full_initial_sync, target_tables)
674
675
  # This notification will be uncommented after init_sync_finish email integration is released
675
- #unless options[:sync_resumed]
676
- # FlydataCore::Event::ApiEventSender.instance.send_event("init_sync", "started", {"tables" => target_tables}, de['id'])
677
- #end
676
+ unless options[:sync_resumed]
677
+ FlydataCore::Event::ApiEventSender.instance.send_event(
678
+ FlydataCore::Event::INIT_SYNC,
679
+ FlydataCore::Event::STARTED,
680
+ data: {"tables" => target_tables, 'no_email' => options[:no_email]},
681
+ data_entry_id: de['id'],
682
+ data_port_id: de['data_port_id'])
683
+ end
678
684
  dump_generator = Flydata::Parser::Mysql::MysqlDumpGeneratorNoMasterData.new(de['mysql_data_entry_preference'].merge('tables' => target_tables))
679
685
  if file_dump
680
686
  binlog_pos = nil
@@ -877,10 +883,10 @@ EOM
877
883
  sync_fm.save_dump_pos(STATUS_PARSING, table_name, last_pos, binlog_pos, state, substate)
878
884
 
879
885
  # send record count for the table
880
- if mysql_table &&
886
+ if table_name.to_s != '' &&
881
887
  state == Flydata::Parser::Mysql::MysqlDumpParser::State::CREATE_TABLE
882
888
  # all records for `mysql_table` have been sent
883
- send_record_counts(de, sync_fm, mysql_table.table_name,
889
+ send_record_counts(de, sync_fm, table_name,
884
890
  send_record_counts_threads)
885
891
  log_info_stdout(" -> Finished sending data for table '#{table_name}'...")
886
892
  end
@@ -29,6 +29,9 @@ module Mysql
29
29
  end
30
30
 
31
31
  private
32
+ def binlog_pos(record)
33
+ "#{@context.current_binlog_file}\t#{record['next_position'] - record['event_length']}"
34
+ end
32
35
 
33
36
  def supported_database
34
37
  @context.database
@@ -42,8 +45,7 @@ module Mysql
42
45
  acceptable = @context.tables.include?(table)
43
46
 
44
47
  if acceptable and @table_binlog_pos[record['table_name']]
45
- if @table_binlog_pos[record['table_name']] >= Flydata::Mysql::BinLogPosition.new(
46
- "#{@context.current_binlog_file}\t#{record['next_position'] - record['event_length']}")
48
+ if @table_binlog_pos[record['table_name']] >= Flydata::Mysql::BinLogPosition.new(binlog_pos(record))
47
49
  acceptable = false
48
50
  else
49
51
  @context.sync_fm.delete_table_binlog_pos(record['table_name'])
@@ -73,7 +75,6 @@ module Mysql
73
75
  return unless acceptable_table?(record, table) && acceptable_event?(type, table)
74
76
 
75
77
  table_rev = @context.table_revs[table]
76
- position = record['next_position'] - record['event_length']
77
78
 
78
79
  # Add common information to each record
79
80
  records.each do |r|
@@ -84,7 +85,7 @@ module Mysql
84
85
  r[TYPE] = type
85
86
  r[RESPECT_ORDER] = true
86
87
  r[TABLE_NAME] = table
87
- r[SRC_POS] = "#{@context.current_binlog_file}\t#{position}"
88
+ r[SRC_POS] = binlog_pos(record)
88
89
  r[TABLE_REV] = table_rev
89
90
  r[V] = FlydataCore::Record::V2
90
91
  end
@@ -51,13 +51,11 @@ class DatabaseDdlQueryHandler < DdlQueryHandler
51
51
 
52
52
  return unless acceptable_event?(type)
53
53
 
54
- position = record['next_position'] - record['event_length']
55
-
56
54
  # Add common information to each record
57
55
  records.each do |r|
58
56
  r[TYPE] = type
59
57
  r[RESPECT_ORDER] = true
60
- r[SRC_POS] = "#{@context.current_binlog_file}\t#{position}"
58
+ r[SRC_POS] = binlog_pos(record)
61
59
  r[V] = FlydataCore::Record::V2
62
60
  end
63
61
 
@@ -15,8 +15,8 @@ module Mysql
15
15
 
16
16
  def process(record)
17
17
  #Issuing warning message only for the current database.
18
- if record["db_name"] == @context.database
19
- $log.warn("DROP DATABASE detected. A full re-sync is required to provide sync consistency. db_name: #{record["db_name"]}")
18
+ if acceptable_db?(record) #record["db_name"] == @context.database
19
+ $log.warn("DROP DATABASE detected. A full re-sync is required to provide sync consistency. - db_name:'#{record["db_name"]}' query:'#{record["query"]}' normalized query:'#{record['normalized_query']}' binlog_pos:'#{binlog_pos(record)}'")
20
20
  end
21
21
  #NOTE: No emit_record here because this record should not be sent to data servers for now
22
22
  end
@@ -108,6 +108,7 @@ module Flydata
108
108
  expect(subject).to receive(:ask_yes_no).and_return(true).at_least(:once)
109
109
  Flydata::Parser::Mysql::DatabaseSizeCheck.any_instance.should_receive(:get_db_bytesize).and_return(db_byte)
110
110
  Flydata::MysqlCompatibilityCheck.any_instance.should_receive(:check)
111
+ expect_any_instance_of(FlydataCore::Event::ApiEventSender).to receive(:send_event).once
111
112
  end
112
113
  context 'with no stream option' do
113
114
  before do
@@ -19,9 +19,11 @@ module Mysql
19
19
  shared_examples "test different dbs" do
20
20
  context "for the target db" do
21
21
  let(:database) { target_database }
22
-
22
+ let(:binlog_pos) { "#{context.current_binlog_file}\t#{record['next_position'] - record['event_length']}" }
23
+
23
24
  it "shows a warning message" do
24
- expect($log).to receive(:warn).with("DROP DATABASE detected. A full re-sync is required to provide sync consistency. db_name: #{record["db_name"]}").once
25
+ expect($log).to receive(:warn).with("DROP DATABASE detected. A full re-sync is required to provide sync consistency. - db_name:'#{record["db_name"]}' query:'#{record["query"]}' normalized query:'#{record["normalized_query"]}' binlog_pos:'#{binlog_pos}'")
26
+
25
27
  subject
26
28
  end
27
29
  end
@@ -65,5 +65,29 @@ describe JSON do
65
65
  it_behaves_like "producing the expected result"
66
66
  end
67
67
  end
68
+
69
+ context 'testing memory' do
70
+ let(:keys) { ['id', 'user_id', 'name', 'timestamp'] }
71
+ let(:values) { ['29388381012', '192938439', 'Muy Fiel y Reconquistadora Ciudad de San Felipe y Santiago de Montevideo', '2015-12-01 12:34:56' ] }
72
+ let(:expected_result) { %Q|{"id":"29388381012","user_id":"192938439","name":"Muy Fiel y Reconquistadora Ciudad de San Felipe y Santiago de Montevideo","timestamp":"2015-12-01 12:34:56"}| }
73
+ xcontext 'when run many many times' do
74
+ thread = nil
75
+ before do
76
+ GC.stress = true
77
+ thread = Thread.new { loop {rand(9).to_s * rand(9)} }
78
+ end
79
+ it do
80
+ 6000.times do
81
+ result = described_class.generate_kv_pairs(keys, values)
82
+ rand(9).to_s * rand(9)
83
+ expect(result).to eq expected_result
84
+ end
85
+ end
86
+ after do
87
+ GC.stress = false
88
+ thread.kill
89
+ end
90
+ end
91
+ end
68
92
  end
69
93
  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.6.0
4
+ version: 0.6.1
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-12-01 00:00:00.000000000 Z
15
+ date: 2015-12-07 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rest-client
@@ -513,6 +513,7 @@ files:
513
513
  - flydata-core/lib/flydata-core/core_ext/object.rb
514
514
  - flydata-core/lib/flydata-core/core_ext/object/prepend.rb
515
515
  - flydata-core/lib/flydata-core/errors.rb
516
+ - flydata-core/lib/flydata-core/event/event_dictionary.rb
516
517
  - flydata-core/lib/flydata-core/event/event_handler_base.rb
517
518
  - flydata-core/lib/flydata-core/event/flydata_event.rb
518
519
  - flydata-core/lib/flydata-core/event/flydata_event_handler_registry.rb
@@ -744,7 +745,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
744
745
  version: '0'
745
746
  requirements: []
746
747
  rubyforge_project:
747
- rubygems_version: 2.4.3
748
+ rubygems_version: 2.0.14.1
748
749
  signing_key:
749
750
  specification_version: 4
750
751
  summary: FlyData Agent