waterdrop 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.
- checksums.yaml +7 -0
- data/.gitignore +66 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +6 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +191 -0
- data/MIT-LICENCE +18 -0
- data/README.md +147 -0
- data/Rakefile +18 -0
- data/lib/water_drop.rb +53 -0
- data/lib/water_drop/aspects/after_aspect.rb +18 -0
- data/lib/water_drop/aspects/around_aspect.rb +21 -0
- data/lib/water_drop/aspects/base_aspect.rb +37 -0
- data/lib/water_drop/aspects/before_aspect.rb +18 -0
- data/lib/water_drop/aspects/formatter.rb +25 -0
- data/lib/water_drop/config.rb +41 -0
- data/lib/water_drop/event.rb +31 -0
- data/lib/water_drop/logger.rb +10 -0
- data/lib/water_drop/pool.rb +24 -0
- data/lib/water_drop/version.rb +5 -0
- data/waterdrop.gemspec +25 -0
- metadata +124 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 68abb1be8f0558b53ff3cc1c8f29134e786b4c1c
|
|
4
|
+
data.tar.gz: 0031802410a38d242c0da4bbd74473a267852b67
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 1ca70187b5b3cc6559d48b276bc228b579cee0a0938c40656dd9158f74ae2094550b6e9059b1a4774188637fcda23fa2fed439b44a37537ffea89a73562746c4
|
|
7
|
+
data.tar.gz: 26c374cde1d74764d2def8933211b7a856a8f032bcd891342bc35121c5c10c0c1478d581834db9a3d9c4e0b9f26e63989c4b81315d21346eb01034b79184ebaf
|
data/.gitignore
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# bundler state
|
|
2
|
+
/.bundle
|
|
3
|
+
/vendor/bundle/
|
|
4
|
+
/vendor/ruby/
|
|
5
|
+
/ruby/
|
|
6
|
+
app.god
|
|
7
|
+
|
|
8
|
+
# minimal Rails specific artifacts
|
|
9
|
+
db/*.sqlite3
|
|
10
|
+
/log/*
|
|
11
|
+
/tmp/*
|
|
12
|
+
*.gem
|
|
13
|
+
*.~
|
|
14
|
+
|
|
15
|
+
# various artifacts
|
|
16
|
+
**.war
|
|
17
|
+
*.rbc
|
|
18
|
+
*.sassc
|
|
19
|
+
.rspec
|
|
20
|
+
.redcar/
|
|
21
|
+
.capistrano/
|
|
22
|
+
.sass-cache
|
|
23
|
+
/config/god/sidekiq.rb
|
|
24
|
+
/config/puma.rb
|
|
25
|
+
/coverage.data
|
|
26
|
+
/coverage/
|
|
27
|
+
/doc/api/
|
|
28
|
+
/doc/app/
|
|
29
|
+
/doc/yard
|
|
30
|
+
/doc/features.html
|
|
31
|
+
/doc/specs.html
|
|
32
|
+
/spec/tmp/*
|
|
33
|
+
/cache
|
|
34
|
+
/capybara*
|
|
35
|
+
/capybara-*.html
|
|
36
|
+
/gems
|
|
37
|
+
/specifications
|
|
38
|
+
rerun.txt
|
|
39
|
+
pickle-email-*.html
|
|
40
|
+
|
|
41
|
+
# If you find yourself ignoring temporary files generated by your text editor
|
|
42
|
+
# or operating system, you probably want to add a global ignore instead:
|
|
43
|
+
# git config --global core.excludesfile ~/.gitignore_global
|
|
44
|
+
#
|
|
45
|
+
# Here are some files you may want to ignore globally:
|
|
46
|
+
|
|
47
|
+
# scm revert files
|
|
48
|
+
**.orig
|
|
49
|
+
|
|
50
|
+
# Mac finder artifacts
|
|
51
|
+
.DS_Store
|
|
52
|
+
|
|
53
|
+
# Netbeans project directory
|
|
54
|
+
/nbproject
|
|
55
|
+
|
|
56
|
+
# RubyMine project files
|
|
57
|
+
.idea
|
|
58
|
+
|
|
59
|
+
# Textmate project files
|
|
60
|
+
/*.tmproj
|
|
61
|
+
|
|
62
|
+
# vim artifacts
|
|
63
|
+
**.swp
|
|
64
|
+
|
|
65
|
+
# documentation
|
|
66
|
+
.yardoc
|
data/.ruby-gemset
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
waterdrop
|
data/.ruby-version
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ruby-2.2.2
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
GEM
|
|
2
|
+
remote: https://rubygems.org/
|
|
3
|
+
specs:
|
|
4
|
+
abstract_type (0.0.7)
|
|
5
|
+
activemodel (4.2.3)
|
|
6
|
+
activesupport (= 4.2.3)
|
|
7
|
+
builder (~> 3.1)
|
|
8
|
+
activesupport (4.2.3)
|
|
9
|
+
i18n (~> 0.7)
|
|
10
|
+
json (~> 1.7, >= 1.7.7)
|
|
11
|
+
minitest (~> 5.1)
|
|
12
|
+
thread_safe (~> 0.3, >= 0.3.4)
|
|
13
|
+
tzinfo (~> 1.1)
|
|
14
|
+
adamantium (0.2.0)
|
|
15
|
+
ice_nine (~> 0.11.0)
|
|
16
|
+
memoizable (~> 0.4.0)
|
|
17
|
+
aspector (0.14.0)
|
|
18
|
+
ast (2.1.0)
|
|
19
|
+
astrolabe (1.3.1)
|
|
20
|
+
parser (~> 2.2)
|
|
21
|
+
axiom-types (0.1.1)
|
|
22
|
+
descendants_tracker (~> 0.0.4)
|
|
23
|
+
ice_nine (~> 0.11.0)
|
|
24
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
|
25
|
+
brakeman (3.0.5)
|
|
26
|
+
erubis (~> 2.6)
|
|
27
|
+
fastercsv (~> 1.5)
|
|
28
|
+
haml (>= 3.0, < 5.0)
|
|
29
|
+
highline (~> 1.6.20)
|
|
30
|
+
multi_json (~> 1.2)
|
|
31
|
+
ruby2ruby (~> 2.1.1)
|
|
32
|
+
ruby_parser (~> 3.7.0)
|
|
33
|
+
sass (~> 3.0)
|
|
34
|
+
terminal-table (~> 1.4)
|
|
35
|
+
bson (3.2.1)
|
|
36
|
+
builder (3.2.2)
|
|
37
|
+
coderay (1.1.0)
|
|
38
|
+
coercible (1.0.0)
|
|
39
|
+
descendants_tracker (~> 0.0.1)
|
|
40
|
+
concord (0.1.5)
|
|
41
|
+
adamantium (~> 0.2.0)
|
|
42
|
+
equalizer (~> 0.0.9)
|
|
43
|
+
connection_pool (2.2.0)
|
|
44
|
+
descendants_tracker (0.0.4)
|
|
45
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
|
46
|
+
diff-lcs (1.2.5)
|
|
47
|
+
docile (1.1.5)
|
|
48
|
+
equalizer (0.0.11)
|
|
49
|
+
erubis (2.7.0)
|
|
50
|
+
faker (1.5.0)
|
|
51
|
+
i18n (~> 0.5)
|
|
52
|
+
fastercsv (1.5.5)
|
|
53
|
+
flay (2.4.0)
|
|
54
|
+
ruby_parser (~> 3.0)
|
|
55
|
+
sexp_processor (~> 4.0)
|
|
56
|
+
flog (4.2.1)
|
|
57
|
+
ruby_parser (~> 3.1, > 3.1.0)
|
|
58
|
+
sexp_processor (~> 4.4)
|
|
59
|
+
haml (4.0.7)
|
|
60
|
+
tilt
|
|
61
|
+
haml-lint (0.13.0)
|
|
62
|
+
haml (~> 4.0)
|
|
63
|
+
rubocop (>= 0.25.0)
|
|
64
|
+
sysexits (~> 1.1)
|
|
65
|
+
highline (1.6.21)
|
|
66
|
+
i18n (0.7.0)
|
|
67
|
+
ice_nine (0.11.1)
|
|
68
|
+
json (1.8.3)
|
|
69
|
+
memoizable (0.4.2)
|
|
70
|
+
thread_safe (~> 0.3, >= 0.3.1)
|
|
71
|
+
method_source (0.8.2)
|
|
72
|
+
minitest (5.8.0)
|
|
73
|
+
mongoid (4.0.2)
|
|
74
|
+
activemodel (~> 4.0)
|
|
75
|
+
moped (~> 2.0.0)
|
|
76
|
+
origin (~> 2.1)
|
|
77
|
+
tzinfo (>= 0.3.37)
|
|
78
|
+
mongoid-rspec (2.2.0)
|
|
79
|
+
mongoid (~> 4.0.0)
|
|
80
|
+
rake
|
|
81
|
+
rspec (~> 3.1)
|
|
82
|
+
moped (2.0.7)
|
|
83
|
+
bson (~> 3.0)
|
|
84
|
+
connection_pool (~> 2.0)
|
|
85
|
+
optionable (~> 0.2.0)
|
|
86
|
+
multi_json (1.11.2)
|
|
87
|
+
optionable (0.2.0)
|
|
88
|
+
origin (2.1.1)
|
|
89
|
+
parser (2.2.2.6)
|
|
90
|
+
ast (>= 1.1, < 3.0)
|
|
91
|
+
polishgeeks-dev-tools (1.0.0)
|
|
92
|
+
brakeman
|
|
93
|
+
faker
|
|
94
|
+
haml-lint
|
|
95
|
+
mongoid-rspec
|
|
96
|
+
pry
|
|
97
|
+
rspec
|
|
98
|
+
rubocop
|
|
99
|
+
rubycritic (= 1.2.1)
|
|
100
|
+
shoulda
|
|
101
|
+
simplecov
|
|
102
|
+
timecop
|
|
103
|
+
yard
|
|
104
|
+
poseidon (0.0.5)
|
|
105
|
+
powerpack (0.1.1)
|
|
106
|
+
procto (0.0.2)
|
|
107
|
+
pry (0.10.1)
|
|
108
|
+
coderay (~> 1.1.0)
|
|
109
|
+
method_source (~> 0.8.1)
|
|
110
|
+
slop (~> 3.4)
|
|
111
|
+
rainbow (2.0.0)
|
|
112
|
+
rake (10.4.2)
|
|
113
|
+
reek (1.6.3)
|
|
114
|
+
parser (~> 2.2.0.pre.7)
|
|
115
|
+
rainbow (>= 1.99, < 3.0)
|
|
116
|
+
unparser (~> 0.2.2)
|
|
117
|
+
rspec (3.3.0)
|
|
118
|
+
rspec-core (~> 3.3.0)
|
|
119
|
+
rspec-expectations (~> 3.3.0)
|
|
120
|
+
rspec-mocks (~> 3.3.0)
|
|
121
|
+
rspec-core (3.3.2)
|
|
122
|
+
rspec-support (~> 3.3.0)
|
|
123
|
+
rspec-expectations (3.3.1)
|
|
124
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
125
|
+
rspec-support (~> 3.3.0)
|
|
126
|
+
rspec-mocks (3.3.2)
|
|
127
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
128
|
+
rspec-support (~> 3.3.0)
|
|
129
|
+
rspec-support (3.3.0)
|
|
130
|
+
rubocop (0.33.0)
|
|
131
|
+
astrolabe (~> 1.3)
|
|
132
|
+
parser (>= 2.2.2.5, < 3.0)
|
|
133
|
+
powerpack (~> 0.1)
|
|
134
|
+
rainbow (>= 1.99.1, < 3.0)
|
|
135
|
+
ruby-progressbar (~> 1.4)
|
|
136
|
+
ruby-progressbar (1.7.5)
|
|
137
|
+
ruby2ruby (2.1.4)
|
|
138
|
+
ruby_parser (~> 3.1)
|
|
139
|
+
sexp_processor (~> 4.0)
|
|
140
|
+
ruby_parser (3.7.1)
|
|
141
|
+
sexp_processor (~> 4.1)
|
|
142
|
+
rubycritic (1.2.1)
|
|
143
|
+
flay (= 2.4.0)
|
|
144
|
+
flog (= 4.2.1)
|
|
145
|
+
parser (>= 2.2.0, < 3.0)
|
|
146
|
+
reek (= 1.6.3)
|
|
147
|
+
ruby2ruby (>= 2.1.1, < 3.0)
|
|
148
|
+
virtus (~> 1.0)
|
|
149
|
+
sass (3.4.16)
|
|
150
|
+
sexp_processor (4.6.0)
|
|
151
|
+
shoulda (3.5.0)
|
|
152
|
+
shoulda-context (~> 1.0, >= 1.0.1)
|
|
153
|
+
shoulda-matchers (>= 1.4.1, < 3.0)
|
|
154
|
+
shoulda-context (1.2.1)
|
|
155
|
+
shoulda-matchers (2.8.0)
|
|
156
|
+
activesupport (>= 3.0.0)
|
|
157
|
+
simplecov (0.10.0)
|
|
158
|
+
docile (~> 1.1.0)
|
|
159
|
+
json (~> 1.8)
|
|
160
|
+
simplecov-html (~> 0.10.0)
|
|
161
|
+
simplecov-html (0.10.0)
|
|
162
|
+
slop (3.6.0)
|
|
163
|
+
sysexits (1.2.0)
|
|
164
|
+
terminal-table (1.5.2)
|
|
165
|
+
thread_safe (0.3.5)
|
|
166
|
+
tilt (2.0.1)
|
|
167
|
+
timecop (0.8.0)
|
|
168
|
+
tzinfo (1.2.2)
|
|
169
|
+
thread_safe (~> 0.1)
|
|
170
|
+
unparser (0.2.4)
|
|
171
|
+
abstract_type (~> 0.0.7)
|
|
172
|
+
adamantium (~> 0.2.0)
|
|
173
|
+
concord (~> 0.1.5)
|
|
174
|
+
diff-lcs (~> 1.2.5)
|
|
175
|
+
equalizer (~> 0.0.9)
|
|
176
|
+
parser (~> 2.2.2)
|
|
177
|
+
procto (~> 0.0.2)
|
|
178
|
+
virtus (1.0.5)
|
|
179
|
+
axiom-types (~> 0.1)
|
|
180
|
+
coercible (~> 1.0)
|
|
181
|
+
descendants_tracker (~> 0.0, >= 0.0.3)
|
|
182
|
+
equalizer (~> 0.0, >= 0.0.9)
|
|
183
|
+
yard (0.8.7.6)
|
|
184
|
+
|
|
185
|
+
PLATFORMS
|
|
186
|
+
ruby
|
|
187
|
+
|
|
188
|
+
DEPENDENCIES
|
|
189
|
+
aspector
|
|
190
|
+
polishgeeks-dev-tools
|
|
191
|
+
poseidon
|
data/MIT-LICENCE
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
2
|
+
a copy of this software and associated documentation files (the
|
|
3
|
+
"Software"), to deal in the Software without restriction, including
|
|
4
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
5
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
6
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
7
|
+
the following conditions:
|
|
8
|
+
|
|
9
|
+
The above copyright notice and this permission notice shall be
|
|
10
|
+
included in all copies or substantial portions of the Software.
|
|
11
|
+
|
|
12
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
13
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
14
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
15
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
16
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
17
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
18
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# WaterDrop
|
|
2
|
+
|
|
3
|
+
[](https://travis-ci.org/karafka/waterdrop)
|
|
4
|
+
[](https://codeclimate.com/github/karafka/waterdrop)
|
|
5
|
+
|
|
6
|
+
Gem used to send events to Kafka in a standard and in an aspect way.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
gem install waterdrop
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
or add this to your Gemfile:
|
|
15
|
+
|
|
16
|
+
```ruby
|
|
17
|
+
gem 'waterdrop'
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
and run
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
bundle install
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Setup
|
|
27
|
+
|
|
28
|
+
WaterDrop has following configuration options:
|
|
29
|
+
|
|
30
|
+
| Option | Value type | Description |
|
|
31
|
+
|-------------------------|---------------|--------------------------------|
|
|
32
|
+
| send_events | Boolean | Should we send events to Kafka |
|
|
33
|
+
| kafka_host | String | Kafka server host |
|
|
34
|
+
| kafka_ports | Array<String> | Kafka server ports |
|
|
35
|
+
| connection_pool_size | Integer | Kafka connection pool size |
|
|
36
|
+
| connection_pool_timeout | Integer | Kafka connection pool timeout |
|
|
37
|
+
|
|
38
|
+
To apply this configuration, you need to use a *setup* method:
|
|
39
|
+
|
|
40
|
+
```ruby
|
|
41
|
+
WaterDrop.setup do |config|
|
|
42
|
+
config.send_events = true
|
|
43
|
+
config.connection_pool_size = 20
|
|
44
|
+
config.connection_pool_timeout = 1
|
|
45
|
+
config.kafka_ports = %w( 9092 )
|
|
46
|
+
config.kafka_host = 'localhost'
|
|
47
|
+
end
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
This configuration can be placed in *config/initializers* and can vary based on the environment:
|
|
51
|
+
|
|
52
|
+
```ruby
|
|
53
|
+
WaterDrop.setup do |config|
|
|
54
|
+
config.send_events = Rails.env.production?
|
|
55
|
+
config.connection_pool_size = 20
|
|
56
|
+
config.connection_pool_timeout = 1
|
|
57
|
+
config.kafka_ports = %w( 9092 )
|
|
58
|
+
config.kafka_host = Rails.env.production? ? 'prod-host' : 'localhost'
|
|
59
|
+
end
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Usage
|
|
63
|
+
|
|
64
|
+
### Creating and sending standard events
|
|
65
|
+
|
|
66
|
+
To send Kafka messages, you don't need to use aspects, you can create and send events directly:
|
|
67
|
+
|
|
68
|
+
```ruby
|
|
69
|
+
event = WaterDrop::Event.new('topic', 'message')
|
|
70
|
+
event.send!
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
message that you want to send should be either castable to string or to json. If it can be casted to both, it will be casted to json.
|
|
74
|
+
|
|
75
|
+
### Using aspects to handle events
|
|
76
|
+
|
|
77
|
+
WaterDrop uses [Aspector](https://github.com/gcao/aspector) to allow aspect oriented events hookup. If you need extensive details about aspector usage, please refer to the [examples](https://github.com/gcao/aspector/tree/master/examples) directory of this project.
|
|
78
|
+
|
|
79
|
+
In general aspects allows adding additional behavior to existing code without modifying the code itself. This way we can create and send events, without "polluting" the business logic with it.
|
|
80
|
+
|
|
81
|
+
All the WaterDrop aspects accept following parameters:
|
|
82
|
+
|
|
83
|
+
| Option | Value type | Description |
|
|
84
|
+
|-------------------------|-----------------------|----------------------------------------------|
|
|
85
|
+
| ClassName | Class | Class to which we want to hook |
|
|
86
|
+
| method: :method_name | Symbol, Array<Symbol> | Method (or methods) to which we want to hook |
|
|
87
|
+
| topic: 'karafka_topic' | String, Symbol | Kafka topic to which we will send the event |
|
|
88
|
+
|
|
89
|
+
There also a *message*, *after_message* and *before_message* proc parameter that will be evaluated in the methods object context.
|
|
90
|
+
|
|
91
|
+
#### Before aspects hookup
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
WaterDrop::Aspects::BeforeAspect.apply(
|
|
95
|
+
ClassName,
|
|
96
|
+
method: :run,
|
|
97
|
+
topic: 'karafka_topic',
|
|
98
|
+
message: -> { any_class_name_instance_method }
|
|
99
|
+
)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
now each time before you run:
|
|
103
|
+
|
|
104
|
+
```ruby
|
|
105
|
+
ClassName.new.run
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
an event with the given message will be send to Kafka.
|
|
109
|
+
|
|
110
|
+
#### After aspects hookup
|
|
111
|
+
|
|
112
|
+
```ruby
|
|
113
|
+
WaterDrop::Aspects::AfterAspect.apply(
|
|
114
|
+
ClassName,
|
|
115
|
+
method: :run,
|
|
116
|
+
topic: 'karafka_topic',
|
|
117
|
+
message: ->(result) { "This is result of method run: #{result}" }
|
|
118
|
+
)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
now each time after you run:
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
ClassName.new.run
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
an event with the given message will be send to Kafka.
|
|
128
|
+
|
|
129
|
+
#### Around aspects hookup
|
|
130
|
+
|
|
131
|
+
```ruby
|
|
132
|
+
WaterDrop::Aspects::AroundAspect.apply(
|
|
133
|
+
ClassName,
|
|
134
|
+
method: :run,
|
|
135
|
+
topic: 'karafka_topic',
|
|
136
|
+
before_message: -> { any_class_name_instance_method },
|
|
137
|
+
after_message: ->(result) { "This is result of method run: #{result}" }
|
|
138
|
+
)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
now each time you run:
|
|
142
|
+
|
|
143
|
+
```ruby
|
|
144
|
+
ClassName.new.run
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
an event with the given message will be send before and after the method execution.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'bundler'
|
|
2
|
+
require 'bundler/gem_tasks'
|
|
3
|
+
require 'rake'
|
|
4
|
+
require 'polishgeeks-dev-tools'
|
|
5
|
+
|
|
6
|
+
PolishGeeks::DevTools.setup do |config|
|
|
7
|
+
config.brakeman = false
|
|
8
|
+
config.haml_lint = false
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
desc 'Self check using strike-dev-tools'
|
|
12
|
+
task :check do
|
|
13
|
+
PolishGeeks::DevTools::Runner.new.execute(
|
|
14
|
+
PolishGeeks::DevTools::Logger.new
|
|
15
|
+
)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
task default: :check
|
data/lib/water_drop.rb
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# External components
|
|
2
|
+
%w(
|
|
3
|
+
rake
|
|
4
|
+
rubygems
|
|
5
|
+
bundler
|
|
6
|
+
logger
|
|
7
|
+
pathname
|
|
8
|
+
json
|
|
9
|
+
poseidon
|
|
10
|
+
aspector
|
|
11
|
+
forwardable
|
|
12
|
+
connection_pool
|
|
13
|
+
).each { |lib| require lib }
|
|
14
|
+
|
|
15
|
+
# Internal components
|
|
16
|
+
|
|
17
|
+
base_path = File.dirname(__FILE__) + '/water_drop'
|
|
18
|
+
|
|
19
|
+
%w(
|
|
20
|
+
version
|
|
21
|
+
pool
|
|
22
|
+
config
|
|
23
|
+
event
|
|
24
|
+
logger
|
|
25
|
+
aspects/base_aspect
|
|
26
|
+
aspects/formatter
|
|
27
|
+
aspects/after_aspect
|
|
28
|
+
aspects/around_aspect
|
|
29
|
+
aspects/before_aspect
|
|
30
|
+
).each { |lib| require "#{base_path}/#{lib}" }
|
|
31
|
+
|
|
32
|
+
# WaterDrop library
|
|
33
|
+
module WaterDrop
|
|
34
|
+
class << self
|
|
35
|
+
attr_writer :logger
|
|
36
|
+
|
|
37
|
+
# @return [Logger] logger that we want to use
|
|
38
|
+
def logger
|
|
39
|
+
@logger ||= Logger.new
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Sets up the whole configuration
|
|
43
|
+
# @param [Block] block configuration block
|
|
44
|
+
def setup(&block)
|
|
45
|
+
Config.setup(&block)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# @return [WaterDrop::Config] config instance
|
|
49
|
+
def config
|
|
50
|
+
Config.config
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module WaterDrop
|
|
2
|
+
module Aspects
|
|
3
|
+
# After method execution aspect
|
|
4
|
+
# @example Apply after aspect to a method
|
|
5
|
+
# WaterDrop::Aspects::AfterAspect.apply(
|
|
6
|
+
# ClassName,
|
|
7
|
+
# method: :run,
|
|
8
|
+
# topic: 'karafka_topic',
|
|
9
|
+
# message: ->(result) { "This is result of method run: #{result}" }
|
|
10
|
+
# )
|
|
11
|
+
class AfterAspect < BaseAspect
|
|
12
|
+
after options[:method], interception_arg: true do |interception, result, *args|
|
|
13
|
+
options = interception.options
|
|
14
|
+
interception.aspect.handle(self, options, args, options[:message], result)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module WaterDrop
|
|
2
|
+
module Aspects
|
|
3
|
+
# Around method execution aspect
|
|
4
|
+
# @example Apply around aspect to a method
|
|
5
|
+
# WaterDrop::Aspects::AroundAspect.apply(
|
|
6
|
+
# ClassName,
|
|
7
|
+
# method: :run,
|
|
8
|
+
# topic: 'karafka_topic',
|
|
9
|
+
# before_message: -> { any_class_name_instance_method },
|
|
10
|
+
# after_message: ->(result) { "This is result of method run: #{result}" }
|
|
11
|
+
# )
|
|
12
|
+
class AroundAspect < BaseAspect
|
|
13
|
+
around options[:method], interception_arg: true do |interception, proxy, *args, &block|
|
|
14
|
+
options = interception.options
|
|
15
|
+
interception.aspect.handle(self, options, args, options[:before_message])
|
|
16
|
+
result = proxy.call(*args, &block)
|
|
17
|
+
interception.aspect.handle(self, options, args, options[:after_message], result)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module WaterDrop
|
|
2
|
+
# Aspects module which include all available aspects
|
|
3
|
+
module Aspects
|
|
4
|
+
# Base class for all aspects
|
|
5
|
+
class BaseAspect < ::Aspector::Base
|
|
6
|
+
default private_methods: true
|
|
7
|
+
|
|
8
|
+
# @param this is an instance on which we execute aspect (original method caller)
|
|
9
|
+
# @param [Hash] options aspect options
|
|
10
|
+
# @param [Array] args original method arguments
|
|
11
|
+
# @param [Block] message block which we evaluate to get a message that we will send
|
|
12
|
+
# @param result original method result
|
|
13
|
+
def handle(this, options, args, message, *result)
|
|
14
|
+
formatter = Formatter.new(
|
|
15
|
+
options,
|
|
16
|
+
args,
|
|
17
|
+
instance_run(this, result, message)
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
Event.new(options[:topic], formatter.message).send!
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
private
|
|
24
|
+
|
|
25
|
+
# Method used to change message block binding, so it will be evaluated
|
|
26
|
+
# in the caller instance context
|
|
27
|
+
# @param this is an instance on which we execute aspect (original method caller)
|
|
28
|
+
# @param result original method call result
|
|
29
|
+
# @param [Block] message block
|
|
30
|
+
def instance_run(this, result, message)
|
|
31
|
+
return this.instance_eval(&message) if message.parameters.empty?
|
|
32
|
+
|
|
33
|
+
this.instance_exec(result, message) { |res, block| block.call(res.first) }
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module WaterDrop
|
|
2
|
+
module Aspects
|
|
3
|
+
# Before method execution aspect
|
|
4
|
+
# @example Apply before aspect to a method
|
|
5
|
+
# WaterDrop::Aspects::BeforeAspect.apply(
|
|
6
|
+
# ClassName,
|
|
7
|
+
# method: :run,
|
|
8
|
+
# topic: 'karafka_topic',
|
|
9
|
+
# message: -> { any_class_name_instance_method }
|
|
10
|
+
# )
|
|
11
|
+
class BeforeAspect < BaseAspect
|
|
12
|
+
before options[:method], interception_arg: true do |interception, *args|
|
|
13
|
+
options = interception.options
|
|
14
|
+
interception.aspect.handle(self, options, args, options[:message])
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module WaterDrop
|
|
2
|
+
module Aspects
|
|
3
|
+
# Class used to format message that will be send from an aspect
|
|
4
|
+
class Formatter
|
|
5
|
+
# @param [Hash] options from an aspect
|
|
6
|
+
# @param [Array] args original method arguments
|
|
7
|
+
# @param result of execution of the method
|
|
8
|
+
def initialize(options, args, result)
|
|
9
|
+
@options = options
|
|
10
|
+
@args = args
|
|
11
|
+
@result = result
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# @return [Hash] hash with formatted message that can be send
|
|
15
|
+
def message
|
|
16
|
+
{
|
|
17
|
+
topic: @options[:topic],
|
|
18
|
+
method: @options[:method],
|
|
19
|
+
message: @result,
|
|
20
|
+
args: @args
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
module WaterDrop
|
|
2
|
+
# Configurator for setting up all options required by WaterDrop
|
|
3
|
+
class Config
|
|
4
|
+
class << self
|
|
5
|
+
attr_accessor :config
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
# Available options
|
|
9
|
+
# @option connection_pool_size [Fixnum] The number of connections to pool.
|
|
10
|
+
# @option connection_pool_timeout [Fixnum] Amount of time in seconds to wait for a connection
|
|
11
|
+
# if none currently available.
|
|
12
|
+
# @option kafka_ports [Array] the ports of kafka brokers
|
|
13
|
+
# @option kafka_host [String] the host of kafka server
|
|
14
|
+
# @option send_events [Boolean] boolean value to define whether events should be sent
|
|
15
|
+
#
|
|
16
|
+
OPTIONS = %i(
|
|
17
|
+
connection_pool_size
|
|
18
|
+
connection_pool_timeout
|
|
19
|
+
kafka_ports
|
|
20
|
+
kafka_host
|
|
21
|
+
send_events
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
OPTIONS.each do |attr_name|
|
|
25
|
+
attr_accessor attr_name
|
|
26
|
+
|
|
27
|
+
# @return [Boolean] is given command enabled
|
|
28
|
+
define_method :"#{attr_name}?" do
|
|
29
|
+
public_send(attr_name) == true
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Configurating method
|
|
34
|
+
def self.setup(&block)
|
|
35
|
+
self.config = new
|
|
36
|
+
|
|
37
|
+
block.call(config)
|
|
38
|
+
config.freeze
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module WaterDrop
|
|
2
|
+
# Event module which encapsulate single Kafka event logic and its delivery
|
|
3
|
+
class Event
|
|
4
|
+
attr_reader :topic, :message
|
|
5
|
+
|
|
6
|
+
# @param topic [String, Symbol] a topic to which we want to send a message
|
|
7
|
+
# @param message [Object] any object that can be serialized to a JSON string or
|
|
8
|
+
# that can be casted to a string
|
|
9
|
+
# @return [WaterDrop::Event] WaterDrop event instance
|
|
10
|
+
# @example Creating a new event
|
|
11
|
+
# WaterDrop::Event.new(topic, message)
|
|
12
|
+
def initialize(topic, message)
|
|
13
|
+
@topic = topic.to_s
|
|
14
|
+
@message = message.respond_to?(:to_json) ? message.to_json : message.to_s
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Sents a current event to Kafka
|
|
18
|
+
# @note Won't send any events if send_events config flag is set to false
|
|
19
|
+
# @example Set a message
|
|
20
|
+
# WaterDrop::Event.new(topic, message).send!
|
|
21
|
+
def send!
|
|
22
|
+
return true unless ::WaterDrop.config.send_events?
|
|
23
|
+
|
|
24
|
+
Pool.with do |producer|
|
|
25
|
+
producer.send_messages([
|
|
26
|
+
Poseidon::MessageToSend.new(topic, message)
|
|
27
|
+
])
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module WaterDrop
|
|
2
|
+
# Raw poseidon connection pool for WaterDrop events delivery
|
|
3
|
+
module Pool
|
|
4
|
+
extend SingleForwardable
|
|
5
|
+
# Delegate directly to pool
|
|
6
|
+
def_delegators :pool, :with
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
# @return [::ConnectionPool] connection pool instance that we can then use
|
|
10
|
+
def pool
|
|
11
|
+
@pool ||= ConnectionPool.new(
|
|
12
|
+
size: ::WaterDrop.config.connection_pool_size,
|
|
13
|
+
timeout: ::WaterDrop.config.connection_pool_timeout
|
|
14
|
+
) do
|
|
15
|
+
addresses = ::WaterDrop.config.kafka_ports.map do |port|
|
|
16
|
+
"#{::WaterDrop.config.kafka_host}:#{port}"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
Poseidon::Producer.new(addresses, object_id.to_s)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
data/waterdrop.gemspec
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
lib = File.expand_path('../lib', __FILE__)
|
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
3
|
+
require 'rake'
|
|
4
|
+
require 'water_drop/version'
|
|
5
|
+
|
|
6
|
+
Gem::Specification.new do |spec|
|
|
7
|
+
spec.name = 'waterdrop'
|
|
8
|
+
spec.version = ::WaterDrop::VERSION
|
|
9
|
+
spec.platform = Gem::Platform::RUBY
|
|
10
|
+
spec.authors = ['Maciej Mensfeld', 'Pavlo Vavruk']
|
|
11
|
+
spec.email = %w( maciej@mensfeld.pl pavlo.vavruk@gmail.com )
|
|
12
|
+
spec.homepage = ''
|
|
13
|
+
spec.summary = %q{ Kafka events with aspects made easy! }
|
|
14
|
+
spec.description = spec.summary
|
|
15
|
+
spec.license = 'MIT'
|
|
16
|
+
|
|
17
|
+
spec.add_dependency 'bundler', '~> 0'
|
|
18
|
+
spec.add_dependency 'rake', '~> 0'
|
|
19
|
+
spec.add_dependency 'aspector', '~> 0'
|
|
20
|
+
spec.add_dependency 'poseidon', '~> 0'
|
|
21
|
+
|
|
22
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec)/}) }
|
|
23
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
24
|
+
spec.require_paths = %w( lib )
|
|
25
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: waterdrop
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Maciej Mensfeld
|
|
8
|
+
- Pavlo Vavruk
|
|
9
|
+
autorequire:
|
|
10
|
+
bindir: bin
|
|
11
|
+
cert_chain: []
|
|
12
|
+
date: 2015-08-20 00:00:00.000000000 Z
|
|
13
|
+
dependencies:
|
|
14
|
+
- !ruby/object:Gem::Dependency
|
|
15
|
+
name: bundler
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
|
+
requirements:
|
|
18
|
+
- - "~>"
|
|
19
|
+
- !ruby/object:Gem::Version
|
|
20
|
+
version: '0'
|
|
21
|
+
type: :runtime
|
|
22
|
+
prerelease: false
|
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
24
|
+
requirements:
|
|
25
|
+
- - "~>"
|
|
26
|
+
- !ruby/object:Gem::Version
|
|
27
|
+
version: '0'
|
|
28
|
+
- !ruby/object:Gem::Dependency
|
|
29
|
+
name: rake
|
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
|
31
|
+
requirements:
|
|
32
|
+
- - "~>"
|
|
33
|
+
- !ruby/object:Gem::Version
|
|
34
|
+
version: '0'
|
|
35
|
+
type: :runtime
|
|
36
|
+
prerelease: false
|
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
38
|
+
requirements:
|
|
39
|
+
- - "~>"
|
|
40
|
+
- !ruby/object:Gem::Version
|
|
41
|
+
version: '0'
|
|
42
|
+
- !ruby/object:Gem::Dependency
|
|
43
|
+
name: aspector
|
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - "~>"
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: '0'
|
|
49
|
+
type: :runtime
|
|
50
|
+
prerelease: false
|
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
52
|
+
requirements:
|
|
53
|
+
- - "~>"
|
|
54
|
+
- !ruby/object:Gem::Version
|
|
55
|
+
version: '0'
|
|
56
|
+
- !ruby/object:Gem::Dependency
|
|
57
|
+
name: poseidon
|
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
|
59
|
+
requirements:
|
|
60
|
+
- - "~>"
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: '0'
|
|
63
|
+
type: :runtime
|
|
64
|
+
prerelease: false
|
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
66
|
+
requirements:
|
|
67
|
+
- - "~>"
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: '0'
|
|
70
|
+
description: Kafka events with aspects made easy!
|
|
71
|
+
email:
|
|
72
|
+
- maciej@mensfeld.pl
|
|
73
|
+
- pavlo.vavruk@gmail.com
|
|
74
|
+
executables: []
|
|
75
|
+
extensions: []
|
|
76
|
+
extra_rdoc_files: []
|
|
77
|
+
files:
|
|
78
|
+
- ".gitignore"
|
|
79
|
+
- ".ruby-gemset"
|
|
80
|
+
- ".ruby-version"
|
|
81
|
+
- ".travis.yml"
|
|
82
|
+
- Gemfile
|
|
83
|
+
- Gemfile.lock
|
|
84
|
+
- MIT-LICENCE
|
|
85
|
+
- README.md
|
|
86
|
+
- Rakefile
|
|
87
|
+
- lib/water_drop.rb
|
|
88
|
+
- lib/water_drop/aspects/after_aspect.rb
|
|
89
|
+
- lib/water_drop/aspects/around_aspect.rb
|
|
90
|
+
- lib/water_drop/aspects/base_aspect.rb
|
|
91
|
+
- lib/water_drop/aspects/before_aspect.rb
|
|
92
|
+
- lib/water_drop/aspects/formatter.rb
|
|
93
|
+
- lib/water_drop/config.rb
|
|
94
|
+
- lib/water_drop/event.rb
|
|
95
|
+
- lib/water_drop/logger.rb
|
|
96
|
+
- lib/water_drop/pool.rb
|
|
97
|
+
- lib/water_drop/version.rb
|
|
98
|
+
- waterdrop.gemspec
|
|
99
|
+
homepage: ''
|
|
100
|
+
licenses:
|
|
101
|
+
- MIT
|
|
102
|
+
metadata: {}
|
|
103
|
+
post_install_message:
|
|
104
|
+
rdoc_options: []
|
|
105
|
+
require_paths:
|
|
106
|
+
- lib
|
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
108
|
+
requirements:
|
|
109
|
+
- - ">="
|
|
110
|
+
- !ruby/object:Gem::Version
|
|
111
|
+
version: '0'
|
|
112
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
113
|
+
requirements:
|
|
114
|
+
- - ">="
|
|
115
|
+
- !ruby/object:Gem::Version
|
|
116
|
+
version: '0'
|
|
117
|
+
requirements: []
|
|
118
|
+
rubyforge_project:
|
|
119
|
+
rubygems_version: 2.4.6
|
|
120
|
+
signing_key:
|
|
121
|
+
specification_version: 4
|
|
122
|
+
summary: Kafka events with aspects made easy!
|
|
123
|
+
test_files: []
|
|
124
|
+
has_rdoc:
|