flydata 0.6.11 → 0.6.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +4 -4
  4. data/VERSION +1 -1
  5. data/flydata-core/lib/flydata-core/postgresql/source_pos.rb +34 -0
  6. data/flydata-core/lib/flydata-core/table_def/base.rb +10 -0
  7. data/flydata-core/lib/flydata-core/table_def/postgresql_table_def.rb +20 -4
  8. data/flydata-core/spec/postgresql/source_pos_spec.rb +43 -0
  9. data/flydata-core/spec/table_def/base_spec.rb +51 -0
  10. data/flydata.gemspec +0 -0
  11. data/lib/flydata/command/sender.rb +9 -6
  12. data/lib/flydata/command/setup.rb +6 -12
  13. data/lib/flydata/command/sync.rb +31 -17
  14. data/lib/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync.rb +2 -3
  15. data/lib/flydata/fluent-plugins/in_mysql_binlog_flydata.rb +15 -14
  16. data/lib/flydata/parser/source_table.rb +4 -3
  17. data/lib/flydata/plugin_support/context.rb +46 -0
  18. data/lib/flydata/plugin_support/sync_record_emittable.rb +69 -0
  19. data/lib/flydata/source/component.rb +1 -1
  20. data/lib/flydata/source/generate_source_dump.rb +3 -2
  21. data/lib/flydata/source_mysql/mysql_compatibility_check.rb +12 -11
  22. data/lib/flydata/source_mysql/parser/dump_parser.rb +0 -4
  23. data/lib/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/alter_table_query_handler.rb +8 -2
  24. data/lib/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/binlog_position_file.rb +7 -1
  25. data/lib/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/binlog_query_dispatcher.rb +10 -4
  26. data/lib/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/binlog_query_handler.rb +8 -2
  27. data/lib/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/binlog_record_dispatcher.rb +9 -3
  28. data/lib/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/binlog_record_handler.rb +16 -34
  29. data/lib/flydata/source_mysql/plugin_support/context.rb +7 -0
  30. data/lib/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/ddl_query_handler.rb +11 -19
  31. data/lib/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/dml_record_handler.rb +8 -2
  32. data/lib/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/drop_database_query_handler.rb +8 -2
  33. data/lib/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/table_meta.rb +5 -1
  34. data/lib/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/truncate_table_query_handler.rb +8 -2
  35. data/lib/flydata/source_postgresql/generate_source_dump.rb +175 -0
  36. data/lib/flydata/source_postgresql/parse_dump_and_send.rb +126 -0
  37. data/lib/flydata/source_postgresql/pg_client.rb +43 -0
  38. data/lib/flydata/source_postgresql/postgresql_component.rb +12 -0
  39. data/lib/flydata/source_postgresql/setup.rb +24 -0
  40. data/lib/flydata/source_postgresql/source_pos.rb +18 -0
  41. data/lib/flydata/source_postgresql/sync_generate_table_ddl.rb +7 -15
  42. data/lib/flydata/sync_file_manager.rb +39 -28
  43. data/spec/flydata/command/setup_spec.rb +0 -1
  44. data/spec/flydata/command/sync_spec.rb +2 -2
  45. data/spec/flydata/fluent-plugins/in_mysql_binlog_flydata_spec.rb +5 -6
  46. data/spec/flydata/plugin_support/context_spec.rb +27 -0
  47. data/spec/flydata/source_mysql/parser/dump_parser_spec.rb +4 -4
  48. data/spec/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/alter_table_query_handler_spec.rb +3 -3
  49. data/spec/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/binlog_query_dispatcher_spec.rb +5 -5
  50. data/spec/flydata/source_mysql/plugin_support/context_spec.rb +26 -0
  51. data/spec/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/ddl_query_handler_spec.rb +3 -3
  52. data/spec/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/dml_record_handler_spec.rb +2 -2
  53. data/spec/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/drop_database_query_handler_spec.rb +3 -3
  54. data/spec/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/shared_query_handler_context.rb +3 -1
  55. data/spec/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/table_meta_spec.rb +3 -3
  56. data/spec/flydata/{fluent-plugins/mysql → source_mysql/plugin_support}/truncate_query_handler_spec.rb +7 -4
  57. data/spec/flydata/source_postgresql/generate_source_dump_spec.rb +144 -0
  58. data/spec/flydata/sync_file_manager_spec.rb +1 -1
  59. metadata +38 -24
  60. data/lib/flydata/fluent-plugins/mysql/context.rb +0 -25
@@ -2,15 +2,16 @@ module Flydata
2
2
  module Parser
3
3
 
4
4
  class SourceTable
5
- def initialize(table_name, columns = {}, primary_keys = [])
5
+ def initialize(table_name, columns = {})
6
6
  @table_name = table_name
7
7
  @columns = columns
8
8
  @column_names = columns.collect{|k,v| v[:column_name]}
9
- @primary_keys = primary_keys
9
+ @primary_keys = [] # no longer used. keeping the instance variable for
10
+ # mashall dump compatibility
10
11
  @value_converters = {}
11
12
  end
12
13
 
13
- attr_accessor :table_name, :columns, :column_names, :primary_keys, :value_converters
14
+ attr_accessor :table_name, :column_names, :value_converters
14
15
 
15
16
  def add_column(column)
16
17
  cn = column[:column_name]
@@ -0,0 +1,46 @@
1
+ module Flydata
2
+ module PluginSupport
3
+ class Context
4
+
5
+ def self.mandatory_opts
6
+ @mandatory_opts ||= []
7
+ end
8
+
9
+ def self.optional_opts
10
+ @optional_opts ||= []
11
+ end
12
+
13
+ def self.register_mandatory_opts(*opts)
14
+ @mandatory_opts ||= []
15
+ opts.each {|opt|
16
+ @mandatory_opts << opt.to_sym
17
+ attr_accessor opt
18
+ }
19
+ nil
20
+ end
21
+
22
+ def self.register_optional_opts(*opts)
23
+ @optional_opts ||= []
24
+ opts.each {|opt|
25
+ @optional_opts << opt.to_sym
26
+ attr_accessor opt
27
+ }
28
+ nil
29
+ end
30
+
31
+ register_mandatory_opts :tables, :tag, :sync_fm, :omit_events, :table_revs
32
+ register_optional_opts :current_binlog_file
33
+
34
+ def initialize(opts)
35
+ missing_opts = self.class.mandatory_opts - opts.keys
36
+ unless (missing_opts.empty?)
37
+ raise "Mandatory option(s) are missing: #{missing_opts.join(', ')}"
38
+ end
39
+
40
+ opts.each do |k, v|
41
+ self.instance_variable_set(:"@#{k}", v)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,69 @@
1
+ require 'flydata-core/record/record'
2
+
3
+ module Flydata
4
+ module PluginSupport
5
+ module SyncRecordEmittable
6
+ TABLE_NAME = :table_name # A Flydata JSON tag to specify a table name
7
+ TYPE = :type
8
+ SEQ = :seq
9
+ RESPECT_ORDER = :respect_order
10
+ SRC_POS = :src_pos
11
+ TABLE_REV = :table_rev
12
+ V = :v # FlyData record format version
13
+
14
+ attr_accessor :context # required
15
+
16
+ # Public Interface: Emit sync records to fluent engine
17
+ #
18
+ # "records" : A record or records for emitting
19
+ # Each record needs to be Hash
20
+ # "options"
21
+ # tag : (optional) tag (default: @context.tag)
22
+ # timestamp : (optional) timestamp (default: current timestamp)
23
+ # src_pos : (required) source position (used for sync:repair)
24
+ # table : (optional) table name
25
+ # increment_table_rev : (optional) set true when incrementing table revision
26
+ def emit_sync_records(records, options)
27
+ return if records.nil? # skip
28
+ records = [records] unless records.kind_of?(Array)
29
+
30
+ # Check options
31
+ tag = options[:tag] || @context.tag
32
+ timestamp = options[:timestamp] || Time.now.to_i
33
+ type = options[:type]
34
+ raise "type option must be set" if type.to_s.empty?
35
+ src_pos = options[:src_pos]
36
+ raise "src_pos option must be set" if src_pos.to_s.empty?
37
+
38
+ seq = nil
39
+ if table = options[:table]
40
+ table_rev = @context.table_revs[table]
41
+ if options[:increment_table_rev]
42
+ table_rev = @context.sync_fm.increment_table_rev(table, table_rev)
43
+ @context.table_revs[table] = table_rev
44
+ end
45
+ seq = @context.sync_fm.get_table_position(table)
46
+ end
47
+
48
+ # Add common information to each record
49
+ array = records.collect do |r|
50
+ r[TYPE] = type
51
+ r[RESPECT_ORDER] = true
52
+ r[SRC_POS] = src_pos
53
+ r[V] = FlydataCore::Record::V2
54
+
55
+ if table
56
+ seq = @context.sync_fm.increment_table_position(seq)
57
+ r[SEQ] = seq
58
+ r[TABLE_NAME] = table
59
+ r[TABLE_REV] = table_rev
60
+ end
61
+ [timestamp, r]
62
+ end
63
+ Fluent::Engine.emit_array(tag, array)
64
+ @context.sync_fm.save_table_position(table, seq) if table
65
+ end
66
+
67
+ end
68
+ end
69
+ end
@@ -13,7 +13,7 @@ class Component
13
13
 
14
14
  protected
15
15
 
16
- attr_reader :options
16
+ attr_reader :source, :options
17
17
  def_delegators :@source, :de
18
18
  end
19
19
 
@@ -55,8 +55,9 @@ class GenerateSourceDump < Component
55
55
  #
56
56
  # tables: An array of tables to be dumped.
57
57
  # file_path: A file path string of the dump file to which data is written.
58
- # This value may be nil, in which case contents are written to a
59
- # pipe.
58
+ # This value may be nil, in which case contents are written to
59
+ # a pipe to which the caller can access via `io` passed in the
60
+ # callback.
60
61
  # src_pos_callback: A callback called when the source position of the dump
61
62
  # becomes available. The callback takes the following arguments.
62
63
  # io: Input IO to the dump.
@@ -43,17 +43,24 @@ module SourceMysql
43
43
  stdin.close
44
44
  while !stderr.eof?
45
45
  lines = []
46
- while line = stderr.gets; lines << line.strip; end
47
- err_reason = lines.join(" ")
48
- log_error("Error occured during access to mysql server.", {err: err_reason})
49
-
50
- unless /Warning: Using a password on the command line interface can be insecure/ === err_reason
46
+ while line = stderr.gets do
47
+ lines << line.strip unless line =~ /Warning: Using a password on the command line interface can be insecure/
48
+ end
49
+ unless lines.empty?
50
+ err_reason = lines.join(" ")
51
+ log_error("Error occured during access to mysql server.", err: err_reason)
51
52
  raise FlydataCore::MysqlCompatibilityError, "Cannot connect to MySQL database. Please make sure you can connect with this command:\n $ mysql -u #{@db_opts[:username]} -h #{@db_opts[:host]} -P #{@db_opts[:port]} #{@db_opts[:database]} --protocol=tcp -p"
52
53
  end
53
54
  end
54
55
  end
55
56
  end
56
57
 
58
+ def check_rds_master_status
59
+ if is_rds?
60
+ FlydataCore::Mysql::RdsMasterStatusChecker.new(@db_opts).do_check
61
+ end
62
+ end
63
+
57
64
  def check_mysql_parameters_compat
58
65
  begin
59
66
  FlydataCore::Mysql::OptionalBinlogParameterChecker.new(@db_opts).do_check
@@ -63,12 +70,6 @@ module SourceMysql
63
70
  FlydataCore::Mysql::RequiredBinlogParameterChecker.new(@db_opts).do_check
64
71
  end
65
72
 
66
- def check_rds_master_status
67
- if is_rds?
68
- FlydataCore::Mysql::RdsMasterStatusChecker.new(@db_opts).do_check
69
- end
70
- end
71
-
72
73
  def check_mysql_binlog_retention
73
74
  if is_rds?
74
75
  run_rds_retention_check
@@ -326,10 +326,6 @@ EOS
326
326
  create_table_block.call(current_table)
327
327
  current_state = Flydata::Parser::State::INSERT_RECORD
328
328
  check_point_block.call(current_table, dump_io.pos, bytesize, @binlog_pos, current_state)
329
- elsif m = /^PRIMARY KEY \((?<primary_keys>[^\)]+)\)/.match(line)
330
- current_table.primary_keys = m[:primary_keys].split(',').collect do |pk_str|
331
- pk_str[1..-2]
332
- end
333
329
  end
334
330
  end
335
331
 
@@ -1,7 +1,10 @@
1
1
  require 'flydata/parser/parser_provider'
2
- require 'flydata/fluent-plugins/mysql/ddl_query_handler'
2
+ require 'flydata/source_mysql/plugin_support/ddl_query_handler'
3
3
 
4
- module Mysql
4
+ module Flydata
5
+ module SourceMysql
6
+
7
+ module PluginSupport
5
8
  class AlterTableQueryHandler < TableDdlQueryHandler
6
9
  PATTERN = /^ALTER TABLE/i
7
10
 
@@ -39,3 +42,6 @@ EOS
39
42
  end
40
43
  end
41
44
  end
45
+
46
+ end
47
+ end
@@ -1,4 +1,7 @@
1
- module Mysql
1
+ module Flydata
2
+ module SourceMysql
3
+
4
+ module PluginSupport
2
5
  class BinLogPositionFile
3
6
  attr_accessor :path
4
7
 
@@ -15,3 +18,6 @@ module Mysql
15
18
  end
16
19
  end
17
20
  end
21
+
22
+ end
23
+ end
@@ -1,8 +1,11 @@
1
- require 'flydata/fluent-plugins/mysql/alter_table_query_handler'
2
- require 'flydata/fluent-plugins/mysql/truncate_table_query_handler'
3
- require 'flydata/fluent-plugins/mysql/drop_database_query_handler'
1
+ require 'flydata/source_mysql/plugin_support/alter_table_query_handler'
2
+ require 'flydata/source_mysql/plugin_support/truncate_table_query_handler'
3
+ require 'flydata/source_mysql/plugin_support/drop_database_query_handler'
4
4
 
5
- module Mysql
5
+ module Flydata
6
+ module SourceMysql
7
+
8
+ module PluginSupport
6
9
  class BinlogQueryDispatcher
7
10
  def initialize
8
11
  @handlers = []
@@ -64,3 +67,6 @@ module Mysql
64
67
  end
65
68
  end
66
69
  end
70
+
71
+ end
72
+ end
@@ -1,6 +1,9 @@
1
- require 'flydata/fluent-plugins/mysql/binlog_record_handler'
1
+ require 'flydata/source_mysql/plugin_support/binlog_record_handler'
2
2
 
3
- module Mysql
3
+ module Flydata
4
+ module SourceMysql
5
+
6
+ module PluginSupport
4
7
  class BinlogQueryHandler < BinlogRecordHandler
5
8
  # Return regexp
6
9
  # This class will be used if the pattern matches with the query
@@ -9,3 +12,6 @@ module Mysql
9
12
  end
10
13
  end
11
14
  end
15
+
16
+ end
17
+ end
@@ -1,9 +1,12 @@
1
1
  require 'fluent/plugin/in_mysql_binlog'
2
2
  require 'binlog'
3
- require 'flydata/fluent-plugins/mysql/dml_record_handler'
4
- require 'flydata/fluent-plugins/mysql/binlog_query_dispatcher'
3
+ require 'flydata/source_mysql/plugin_support/dml_record_handler'
4
+ require 'flydata/source_mysql/plugin_support/binlog_query_dispatcher'
5
5
 
6
- module Mysql
6
+ module Flydata
7
+ module SourceMysql
8
+
9
+ module PluginSupport
7
10
  class BinlogRecordDispatcher
8
11
  def dispatch(event)
9
12
  method_name = "on_#{event.event_type.downcase}"
@@ -48,3 +51,6 @@ module Mysql
48
51
  end
49
52
  end
50
53
  end
54
+
55
+ end
56
+ end
@@ -1,17 +1,14 @@
1
1
  require 'fluent/plugin/in_mysql_binlog'
2
2
  require 'binlog'
3
- require 'flydata-core/record/record'
4
3
  require 'flydata-core/mysql/binlog_pos'
4
+ require 'flydata/plugin_support/sync_record_emittable'
5
5
 
6
- module Mysql
6
+ module Flydata
7
+ module SourceMysql
8
+
9
+ module PluginSupport
7
10
  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
11
+ include Flydata::PluginSupport::SyncRecordEmittable
15
12
 
16
13
  def initialize(context)
17
14
  @context = context
@@ -29,6 +26,7 @@ module Mysql
29
26
  end
30
27
 
31
28
  private
29
+
32
30
  def binlog_pos(record)
33
31
  "#{@context.current_binlog_file}\t#{record['next_position'] - record['event_length']}"
34
32
  end
@@ -70,34 +68,15 @@ module Mysql
70
68
  return if records.nil? # skip
71
69
  records = [records] unless records.kind_of?(Array)
72
70
 
73
- table = records.first[TABLE_NAME] || record['table_name']
71
+ table = records.first[:table_name] || record['table_name']
74
72
  raise "Missing table name. #{record}" if table.to_s.empty?
75
73
  return unless acceptable_table?(record, table) && acceptable_event?(type, table)
76
74
 
77
- table_rev = @context.table_revs[table]
78
-
79
- # Add common information to each record
80
- records.each do |r|
81
- if opt[:increment_table_rev]
82
- table_rev = @context.sync_fm.increment_table_rev(table, table_rev)
83
- @context.table_revs[table] = table_rev
84
- end
85
- r[TYPE] = type
86
- r[RESPECT_ORDER] = true
87
- r[TABLE_NAME] = table
88
- r[SRC_POS] = binlog_pos(record)
89
- r[TABLE_REV] = table_rev
90
- r[V] = FlydataCore::Record::V2
91
- end
92
-
93
- # Use binlog's timestamp
94
- timestamp = record["timestamp"].to_i
95
- records.each do |row|
96
- @context.sync_fm.increment_and_save_table_position(row[TABLE_NAME]) do |seq|
97
- row[SEQ] = seq
98
- Fluent::Engine.emit(@context.tag, timestamp, row)
99
- end
100
- end
75
+ emit_sync_records(records, opt.merge(
76
+ timestamp: record["timestamp"].to_i,
77
+ type: type,
78
+ table: table,
79
+ src_pos: binlog_pos(record)))
101
80
  end
102
81
 
103
82
  def check_empty_binlog
@@ -113,3 +92,6 @@ module Mysql
113
92
  end
114
93
  end
115
94
  end
95
+
96
+ end
97
+ end
@@ -0,0 +1,7 @@
1
+ require 'flydata/plugin_support/context'
2
+
3
+ module Flydata::SourceMysql::PluginSupport
4
+ class Context < ::Flydata::PluginSupport::Context
5
+ register_mandatory_opts :database, :table_meta
6
+ end
7
+ end
@@ -1,6 +1,9 @@
1
- require 'flydata/fluent-plugins/mysql/binlog_query_handler'
1
+ require 'flydata/source_mysql/plugin_support/binlog_query_handler'
2
2
 
3
- module Mysql
3
+ module Flydata
4
+ module SourceMysql
5
+
6
+ module PluginSupport
4
7
 
5
8
  class DdlQueryHandler < BinlogQueryHandler
6
9
  DDL_TABLE_QUERY = /^(?:(?:ALTER|CREATE|DROP|RENAME) +(?:\w+ +)*TABLE +([^ ]+)|TRUNCATE +(?:TABLE +)?([^ ;]+))/i
@@ -39,32 +42,21 @@ end
39
42
  class DatabaseDdlQueryHandler < DdlQueryHandler
40
43
  def emit_record(type, record)
41
44
  return unless acceptable_db?(record)
42
-
43
45
  check_empty_binlog
44
46
 
45
47
  opt = {}
46
48
  records = yield(opt) # The block may set options as necessary
47
49
  return if records.nil? # skip
48
50
  records = [records] unless records.kind_of?(Array)
49
-
50
- database = records.first[DB_NAME] || record['db_name']
51
-
52
51
  return unless acceptable_event?(type)
53
52
 
54
- # Add common information to each record
55
- records.each do |r|
56
- r[TYPE] = type
57
- r[RESPECT_ORDER] = true
58
- r[SRC_POS] = binlog_pos(record)
59
- r[V] = FlydataCore::Record::V2
60
- end
61
-
62
- # Use binlog's timestamp
63
- timestamp = record["timestamp"].to_i
64
- records.each do |row|
65
- Fluent::Engine.emit(@context.tag, timestamp, row)
66
- end
53
+ emit_sync_records(records, opt.merge(
54
+ timestamp: record["timestamp"].to_i,
55
+ type: type,
56
+ src_pos: binlog_pos(record)))
67
57
  end
68
58
  end
69
59
 
70
60
  end
61
+ end
62
+ end