flydata 0.6.11 → 0.6.12

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.
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