kodama 0.0.1 → 0.1.0
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.
- data/README.md +18 -13
- data/lib/kodama/client.rb +67 -29
- data/lib/kodama/version.rb +1 -1
- data/spec/lib/client_spec.rb +11 -2
- metadata +32 -32
data/README.md
CHANGED
@@ -61,6 +61,9 @@ Kodama::Client.start(:host => '127.0.0.1', :username => 'user') do |c|
|
|
61
61
|
c.connection_retry_limit = 100 # times
|
62
62
|
c.connection_retry_wait = 3 # second
|
63
63
|
|
64
|
+
# Exit gracefully when kodama receives specified signals
|
65
|
+
c.gracefully_stop_on :QUIT, :INT
|
66
|
+
|
64
67
|
c.on_query_event do |event|
|
65
68
|
p event.query
|
66
69
|
end
|
@@ -76,25 +79,17 @@ end
|
|
76
79
|
```ruby
|
77
80
|
require 'rubygems'
|
78
81
|
require 'kodama'
|
79
|
-
require 'thread'
|
80
82
|
require 'json'
|
81
83
|
require 'redis'
|
82
84
|
|
83
85
|
class Worker
|
84
|
-
attr_accessor :queue
|
85
86
|
def initialize
|
86
|
-
@queue = Queue.new
|
87
87
|
@redis = Redis.new
|
88
88
|
end
|
89
89
|
|
90
|
-
def
|
91
|
-
|
92
|
-
|
93
|
-
event = @queue.pop
|
94
|
-
record_id = get_row(event)[0] # first column is id
|
95
|
-
@redis.set "#{event.table_name}_#{record_id}", event.rows.to_json
|
96
|
-
end
|
97
|
-
end
|
90
|
+
def perform(event)
|
91
|
+
record_id = get_row(event)[0] # first column is id
|
92
|
+
@redis.set "#{event.table_name}_#{record_id}", event.rows.to_json
|
98
93
|
end
|
99
94
|
|
100
95
|
def get_row(event)
|
@@ -109,13 +104,12 @@ end
|
|
109
104
|
|
110
105
|
|
111
106
|
worker = Worker.new
|
112
|
-
worker.start
|
113
107
|
|
114
108
|
Kodama::Client.start(:host => '127.0.0.1', :username => 'user') do |c|
|
115
109
|
c.binlog_position_file = 'position.log'
|
116
110
|
|
117
111
|
c.on_row_event do |event|
|
118
|
-
worker.
|
112
|
+
worker.perform(event)
|
119
113
|
end
|
120
114
|
end
|
121
115
|
```
|
@@ -136,6 +130,17 @@ It accepts ``:debug``, ``:info``, ``:warn``, ``:error``, ``:fatal``.
|
|
136
130
|
|
137
131
|
If for some reason the connection to MySQL is terminated, Kodama will attempt to reconnect ``connection_retry_limit`` times, while waiting ``connection_retry_wait`` seconds between attempts.
|
138
132
|
|
133
|
+
### gracefully_stop_on
|
134
|
+
|
135
|
+
Kodama traps specified signals and stop gracefully.
|
136
|
+
It accpets multiple signals like following.
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
Kodama::Client.start do |c|
|
140
|
+
c.gracefully_stop_on :INT, :QUIT
|
141
|
+
end
|
142
|
+
```
|
143
|
+
|
139
144
|
## Authors
|
140
145
|
|
141
146
|
Yusuke Mito, Genki Sugawara
|
data/lib/kodama/client.rb
CHANGED
@@ -33,6 +33,7 @@ module Kodama
|
|
33
33
|
@retry_info = RetryInfo.new(:limit => 100, :wait => 3)
|
34
34
|
@callbacks = {}
|
35
35
|
@logger = Logger.new(STDOUT)
|
36
|
+
@safe_to_stop = true
|
36
37
|
|
37
38
|
self.log_level = :info
|
38
39
|
end
|
@@ -65,6 +66,18 @@ module Kodama
|
|
65
66
|
@logger.level = LOG_LEVEL[level]
|
66
67
|
end
|
67
68
|
|
69
|
+
def gracefully_stop_on(*signals)
|
70
|
+
signals.each do |signal|
|
71
|
+
Signal.trap(signal) do
|
72
|
+
if safe_to_stop?
|
73
|
+
exit(0)
|
74
|
+
else
|
75
|
+
stop_request
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
68
81
|
def binlog_client(url)
|
69
82
|
Binlog::Client.new(url)
|
70
83
|
end
|
@@ -77,6 +90,14 @@ module Kodama
|
|
77
90
|
@retry_info.count
|
78
91
|
end
|
79
92
|
|
93
|
+
def safe_to_stop?
|
94
|
+
!!@safe_to_stop
|
95
|
+
end
|
96
|
+
|
97
|
+
def stop_request
|
98
|
+
@stop_requested = true
|
99
|
+
end
|
100
|
+
|
80
101
|
def start
|
81
102
|
begin
|
82
103
|
client = binlog_client(@url)
|
@@ -88,36 +109,10 @@ module Kodama
|
|
88
109
|
end
|
89
110
|
|
90
111
|
while event = client.wait_for_next_event
|
91
|
-
|
92
|
-
|
93
|
-
when Binlog::QueryEvent
|
94
|
-
callback :on_query_event, event
|
95
|
-
@binlog_info.save(@position_file)
|
96
|
-
when Binlog::RotateEvent
|
97
|
-
callback :on_rotate_event, event
|
98
|
-
@binlog_info.filename = event.binlog_file
|
99
|
-
@binlog_info.position = event.binlog_pos
|
100
|
-
@binlog_info.save(@position_file)
|
101
|
-
when Binlog::IntVarEvent
|
102
|
-
callback :on_int_var_event, event
|
103
|
-
when Binlog::UserVarEvent
|
104
|
-
callback :on_user_var_event, event
|
105
|
-
when Binlog::FormatEvent
|
106
|
-
callback :on_format_event, event
|
107
|
-
when Binlog::Xid
|
108
|
-
callback :on_xid, event
|
109
|
-
when Binlog::TableMapEvent
|
110
|
-
callback :on_table_map_event, event
|
111
|
-
when Binlog::RowEvent
|
112
|
-
callback :on_row_event, event
|
113
|
-
@binlog_info.save(@position_file)
|
114
|
-
when Binlog::IncidentEvent
|
115
|
-
callback :on_incident_event, event
|
116
|
-
when Binlog::UnimplementedEvent
|
117
|
-
callback :on_unimplemented_event, event
|
118
|
-
else
|
119
|
-
@logger.debug "Not Implemented: #{event.event_type}"
|
112
|
+
unsafe do
|
113
|
+
process_event(event)
|
120
114
|
end
|
115
|
+
break if stop_requested?
|
121
116
|
end
|
122
117
|
rescue Binlog::Error => e
|
123
118
|
@logger.debug e
|
@@ -131,6 +126,49 @@ module Kodama
|
|
131
126
|
end
|
132
127
|
|
133
128
|
private
|
129
|
+
def unsafe
|
130
|
+
@safe_to_stop = false
|
131
|
+
yield
|
132
|
+
@safe_to_stop = true
|
133
|
+
end
|
134
|
+
|
135
|
+
def stop_requested?
|
136
|
+
@stop_requested
|
137
|
+
end
|
138
|
+
|
139
|
+
def process_event(event)
|
140
|
+
@binlog_info.position = event.next_position
|
141
|
+
case event
|
142
|
+
when Binlog::QueryEvent
|
143
|
+
callback :on_query_event, event
|
144
|
+
@binlog_info.save(@position_file)
|
145
|
+
when Binlog::RotateEvent
|
146
|
+
callback :on_rotate_event, event
|
147
|
+
@binlog_info.filename = event.binlog_file
|
148
|
+
@binlog_info.position = event.binlog_pos
|
149
|
+
@binlog_info.save(@position_file)
|
150
|
+
when Binlog::IntVarEvent
|
151
|
+
callback :on_int_var_event, event
|
152
|
+
when Binlog::UserVarEvent
|
153
|
+
callback :on_user_var_event, event
|
154
|
+
when Binlog::FormatEvent
|
155
|
+
callback :on_format_event, event
|
156
|
+
when Binlog::Xid
|
157
|
+
callback :on_xid, event
|
158
|
+
when Binlog::TableMapEvent
|
159
|
+
callback :on_table_map_event, event
|
160
|
+
when Binlog::RowEvent
|
161
|
+
callback :on_row_event, event
|
162
|
+
@binlog_info.save(@position_file)
|
163
|
+
when Binlog::IncidentEvent
|
164
|
+
callback :on_incident_event, event
|
165
|
+
when Binlog::UnimplementedEvent
|
166
|
+
callback :on_unimplemented_event, event
|
167
|
+
else
|
168
|
+
@logger.error "Not Implemented: #{event.event_type}"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
134
172
|
def callback(name, *args)
|
135
173
|
if @callbacks[name]
|
136
174
|
instance_exec *args, &@callbacks[name]
|
data/lib/kodama/version.rb
CHANGED
data/spec/lib/client_spec.rb
CHANGED
@@ -106,7 +106,7 @@ describe Kodama::Client do
|
|
106
106
|
}.to yield_with_args(row_event)
|
107
107
|
end
|
108
108
|
|
109
|
-
it '
|
109
|
+
it 'should save position only on row, query and rotate event' do
|
110
110
|
stub_binlog_client([rotate_event, query_event, row_event, xid_event])
|
111
111
|
position_file = TestPositionFile.new.tap do |pf|
|
112
112
|
pf.should_receive(:update).with('binlog', 100).once.ordered
|
@@ -118,12 +118,21 @@ describe Kodama::Client do
|
|
118
118
|
client.start
|
119
119
|
end
|
120
120
|
|
121
|
-
it 'retry exactly specifeid times' do
|
121
|
+
it 'should retry exactly specifeid times' do
|
122
122
|
stub_binlog_client([query_event], false)
|
123
123
|
client.connection_retry_limit = 2
|
124
124
|
client.connection_retry_wait = 0.1
|
125
125
|
expect { client.start }.to raise_error(Binlog::Error)
|
126
126
|
client.connection_retry_count.should == 2
|
127
127
|
end
|
128
|
+
|
129
|
+
it 'should stop when it receives stop request' do
|
130
|
+
stub_binlog_client([query_event, row_event])
|
131
|
+
client.on_query_event do |event|
|
132
|
+
self.stop_request
|
133
|
+
end
|
134
|
+
expect {|block| client.on_row_event(&block) }.not_to yield_control
|
135
|
+
client.start
|
136
|
+
end
|
128
137
|
end
|
129
138
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kodama
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
- 0
|
9
8
|
- 1
|
10
|
-
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Yusuke Mito
|
@@ -15,12 +15,10 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-
|
18
|
+
date: 2012-12-04 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
|
22
|
-
prerelease: false
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
21
|
+
version_requirements: &id001 !ruby/object:Gem::Requirement
|
24
22
|
none: false
|
25
23
|
requirements:
|
26
24
|
- - ">="
|
@@ -31,12 +29,12 @@ dependencies:
|
|
31
29
|
- 1
|
32
30
|
- 8
|
33
31
|
version: 0.1.8
|
32
|
+
prerelease: false
|
34
33
|
type: :runtime
|
35
|
-
|
34
|
+
name: ruby-binlog
|
35
|
+
requirement: *id001
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
|
-
|
38
|
-
prerelease: false
|
39
|
-
requirement: &id002 !ruby/object:Gem::Requirement
|
37
|
+
version_requirements: &id002 !ruby/object:Gem::Requirement
|
40
38
|
none: false
|
41
39
|
requirements:
|
42
40
|
- - ">="
|
@@ -45,12 +43,12 @@ dependencies:
|
|
45
43
|
segments:
|
46
44
|
- 0
|
47
45
|
version: "0"
|
46
|
+
prerelease: false
|
48
47
|
type: :development
|
49
|
-
|
48
|
+
name: rake
|
49
|
+
requirement: *id002
|
50
50
|
- !ruby/object:Gem::Dependency
|
51
|
-
|
52
|
-
prerelease: false
|
53
|
-
requirement: &id003 !ruby/object:Gem::Requirement
|
51
|
+
version_requirements: &id003 !ruby/object:Gem::Requirement
|
54
52
|
none: false
|
55
53
|
requirements:
|
56
54
|
- - ">="
|
@@ -59,12 +57,12 @@ dependencies:
|
|
59
57
|
segments:
|
60
58
|
- 0
|
61
59
|
version: "0"
|
60
|
+
prerelease: false
|
62
61
|
type: :development
|
63
|
-
|
62
|
+
name: rspec
|
63
|
+
requirement: *id003
|
64
64
|
- !ruby/object:Gem::Dependency
|
65
|
-
|
66
|
-
prerelease: false
|
67
|
-
requirement: &id004 !ruby/object:Gem::Requirement
|
65
|
+
version_requirements: &id004 !ruby/object:Gem::Requirement
|
68
66
|
none: false
|
69
67
|
requirements:
|
70
68
|
- - ">="
|
@@ -73,12 +71,12 @@ dependencies:
|
|
73
71
|
segments:
|
74
72
|
- 0
|
75
73
|
version: "0"
|
74
|
+
prerelease: false
|
76
75
|
type: :development
|
77
|
-
|
76
|
+
name: pry
|
77
|
+
requirement: *id004
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
|
-
|
80
|
-
prerelease: false
|
81
|
-
requirement: &id005 !ruby/object:Gem::Requirement
|
79
|
+
version_requirements: &id005 !ruby/object:Gem::Requirement
|
82
80
|
none: false
|
83
81
|
requirements:
|
84
82
|
- - ">="
|
@@ -87,12 +85,12 @@ dependencies:
|
|
87
85
|
segments:
|
88
86
|
- 0
|
89
87
|
version: "0"
|
88
|
+
prerelease: false
|
90
89
|
type: :development
|
91
|
-
|
90
|
+
name: pry-nav
|
91
|
+
requirement: *id005
|
92
92
|
- !ruby/object:Gem::Dependency
|
93
|
-
|
94
|
-
prerelease: false
|
95
|
-
requirement: &id006 !ruby/object:Gem::Requirement
|
93
|
+
version_requirements: &id006 !ruby/object:Gem::Requirement
|
96
94
|
none: false
|
97
95
|
requirements:
|
98
96
|
- - "="
|
@@ -103,12 +101,12 @@ dependencies:
|
|
103
101
|
- 1
|
104
102
|
- 2
|
105
103
|
version: 2.1.2
|
104
|
+
prerelease: false
|
106
105
|
type: :development
|
107
|
-
|
106
|
+
name: guard-rspec
|
107
|
+
requirement: *id006
|
108
108
|
- !ruby/object:Gem::Dependency
|
109
|
-
|
110
|
-
prerelease: false
|
111
|
-
requirement: &id007 !ruby/object:Gem::Requirement
|
109
|
+
version_requirements: &id007 !ruby/object:Gem::Requirement
|
112
110
|
none: false
|
113
111
|
requirements:
|
114
112
|
- - ~>
|
@@ -119,8 +117,10 @@ dependencies:
|
|
119
117
|
- 9
|
120
118
|
- 1
|
121
119
|
version: 0.9.1
|
120
|
+
prerelease: false
|
122
121
|
type: :development
|
123
|
-
|
122
|
+
name: rb-fsevent
|
123
|
+
requirement: *id007
|
124
124
|
description: ruby-binlog based MySQL replication listener
|
125
125
|
email:
|
126
126
|
- y310.1984@gmail.com
|