oplog_event_handler 0.0.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 +15 -0
- data/lib/oplog_event_handler.rb +163 -0
- metadata +43 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YjBkYzI1Y2NjNGIyMDg4NmU0MTNhMGNjMTc3ZDMxMDgxZGM3NGYyZA==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
OTIyZWEyMDJmY2RkZjUyMjRjMmFhM2VhMzdlYzAxNDIxMDZlOWMyMQ==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZTcxYjhlMzk3OWYxYmUwMTQxMjIwZmQzYWIzYTU5MzU5MDVkNmUwMDZmMDdi
|
10
|
+
ZGQzZTFjZjk0ZGJmNzQ1MzY0NTNiNTc2ZjM4MjMxMGFkNTA1NTAzYTY5OTIy
|
11
|
+
MjY2ZDkzM2Y0YTRlODgzYWEwZTlkYWY1NDVmNWUxZjdmODMxZGQ=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
OTQ1ZDM0YmYzZWJkOWEyZWZmOTZkMzE0YzMwMDllOTU2YjVkY2MwMzlmMzdh
|
14
|
+
ZTBkMTkzMWEyYTdjNjk4NzZhYmU5NWQyOTI5ZDE1YTI2YzJlNjUwNzhmOTJl
|
15
|
+
MzkwMDBlYTkxYzIyY2QyNTdhMTA5NzBjNjZmYThlZWYzZDM4ZTc=
|
@@ -0,0 +1,163 @@
|
|
1
|
+
require 'mongo'
|
2
|
+
module OplogEventHandler
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
OPERATIONS = {
|
9
|
+
'i' => :insert,
|
10
|
+
'u' => :update,
|
11
|
+
'd' => :delete,
|
12
|
+
'c' => :dbcmd,
|
13
|
+
'n' => :noop
|
14
|
+
}
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
|
18
|
+
def connect_to(h)
|
19
|
+
@connection = h
|
20
|
+
end
|
21
|
+
|
22
|
+
def host
|
23
|
+
@connection[:host]
|
24
|
+
end
|
25
|
+
|
26
|
+
def port
|
27
|
+
@connection[:port]
|
28
|
+
end
|
29
|
+
|
30
|
+
def db_name
|
31
|
+
@db_name
|
32
|
+
end
|
33
|
+
|
34
|
+
def for_db(db)
|
35
|
+
@db_name = db
|
36
|
+
yield
|
37
|
+
end
|
38
|
+
|
39
|
+
def mapping
|
40
|
+
return @mapping ||= {}
|
41
|
+
end
|
42
|
+
|
43
|
+
def on_insert(opts)
|
44
|
+
mapping[:"insert_#{db_name}_#{opts[:in]}"] = opts[:call]
|
45
|
+
end
|
46
|
+
|
47
|
+
def on_update(opts)
|
48
|
+
if opts[:only].nil?
|
49
|
+
mapping[:"update_#{db_name}_#{opts[:in]}"] = opts[:call]
|
50
|
+
else
|
51
|
+
opts[:only].each do |e|
|
52
|
+
mapping[:"update_#{db_name}_#{opts[:in]}##{e}"] = opts[:call]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def on_delete(opts)
|
58
|
+
mapping[:"delete_#{db_name}_#{opts[:in]}"] = opts[:call]
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
def run()
|
64
|
+
tail do |log|
|
65
|
+
callbacks = get_callbaks(log)
|
66
|
+
unless callbacks.empty?
|
67
|
+
send_events(log, callbacks)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def send_events(log, callbacks)
|
75
|
+
callbacks.each do |callback|
|
76
|
+
begin
|
77
|
+
case log['op']
|
78
|
+
when 'u'
|
79
|
+
send(callback, id: get_object_id(log), log: log)
|
80
|
+
when 'i'
|
81
|
+
send(callback, id: get_object_id(log), object: log['o'])
|
82
|
+
when 'd'
|
83
|
+
send(callback, id: get_object_id(log))
|
84
|
+
end
|
85
|
+
rescue Exception => e
|
86
|
+
puts present_error(e, callback)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def present_error(ex, callback)
|
92
|
+
"""
|
93
|
+
=============================
|
94
|
+
Erorr in callback
|
95
|
+
#{callback}
|
96
|
+
#{ex.to_s}
|
97
|
+
=============================
|
98
|
+
#{ex.backtrace}
|
99
|
+
"""
|
100
|
+
end
|
101
|
+
|
102
|
+
def get_callbaks(log)
|
103
|
+
callbacks = [self.class.mapping[:"#{extract_operation(log)}_#{extract_db_name(log)}_#{extract_collection_name(log)}"]]
|
104
|
+
if log['op'] == 'u'
|
105
|
+
fields(log).each do |f|
|
106
|
+
callbacks << self.class.mapping[:"#{extract_operation(log)}_#{extract_db_name(log)}_#{extract_collection_name(log)}##{f}"]
|
107
|
+
end
|
108
|
+
end
|
109
|
+
callbacks.compact!
|
110
|
+
callbacks.uniq!
|
111
|
+
return callbacks
|
112
|
+
end
|
113
|
+
|
114
|
+
def extract_db_name(doc)
|
115
|
+
doc['ns'].split('.')[0]
|
116
|
+
end
|
117
|
+
|
118
|
+
def extract_collection_name(doc)
|
119
|
+
doc['ns'].sub(/\A\w+\./, '')
|
120
|
+
end
|
121
|
+
|
122
|
+
def extract_operation(doc)
|
123
|
+
OPERATIONS[doc['op']]
|
124
|
+
end
|
125
|
+
|
126
|
+
def get_object_id(doc)
|
127
|
+
case doc['op']
|
128
|
+
when 'u'
|
129
|
+
doc['o2']['_id']
|
130
|
+
else
|
131
|
+
doc['o']['_id']
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def get_keys(h)
|
136
|
+
ks = []
|
137
|
+
h.each do |k, v|
|
138
|
+
k.split('.').each { |e| ks << e }
|
139
|
+
ks << get_keys(v) if v.kind_of?(Hash)
|
140
|
+
end
|
141
|
+
ks.flatten
|
142
|
+
end
|
143
|
+
|
144
|
+
def fields(doc)
|
145
|
+
if doc['op'] == 'u'
|
146
|
+
get_keys(doc['o']).keep_if { |e| e[0] != '$' }
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def tail
|
151
|
+
oplog_coll = Mongo::Connection.new(self.class.host, self.class.port)['local']['oplog.rs']
|
152
|
+
start = oplog_coll.count
|
153
|
+
tailable_oplog = Mongo::Cursor.new(oplog_coll, :timeout => false, :tailable => true).skip(start)
|
154
|
+
while not tailable_oplog.closed?
|
155
|
+
doc = tailable_oplog.next_document
|
156
|
+
if doc
|
157
|
+
yield doc
|
158
|
+
else
|
159
|
+
sleep(0.1)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
metadata
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: oplog_event_handler
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mathieu Laporte
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-04-18 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Just parse the oplog
|
14
|
+
email: mathieu.laporte+rubygem@gmail.com
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/oplog_event_handler.rb
|
20
|
+
homepage: https://github.com/mathieulaporte/oplog_event_handler
|
21
|
+
licenses: []
|
22
|
+
metadata: {}
|
23
|
+
post_install_message:
|
24
|
+
rdoc_options: []
|
25
|
+
require_paths:
|
26
|
+
- lib
|
27
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
28
|
+
requirements:
|
29
|
+
- - ! '>='
|
30
|
+
- !ruby/object:Gem::Version
|
31
|
+
version: '0'
|
32
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - ! '>='
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '0'
|
37
|
+
requirements: []
|
38
|
+
rubyforge_project:
|
39
|
+
rubygems_version: 2.0.3
|
40
|
+
signing_key:
|
41
|
+
specification_version: 4
|
42
|
+
summary: oplog parser
|
43
|
+
test_files: []
|