pipeline.rb 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +25 -0
- data/LINCENSE +21 -0
- data/README.md +141 -0
- data/example/Gemfile +12 -0
- data/example/Gemfile.lock +52 -0
- data/example/README.md +38 -0
- data/example/app.rb +29 -0
- data/example/config/amqp.json +5 -0
- data/example/config/smtp.json +9 -0
- data/example/config/smtp.local.json +4 -0
- data/example/tasks.rb +11 -0
- data/lib/pipeline/client.rb +98 -0
- data/lib/pipeline/plugin.rb +63 -0
- data/lib/pipeline/tasks.rb +16 -0
- data/lib/pipeline/version.rb +3 -0
- data/pipeline.rb.gemspec +20 -0
- data/spec/data/app/config/amqp.json +5 -0
- data/spec/data/app/config/smtp.json +8 -0
- data/spec/data/app/config/smtp.local.json +4 -0
- data/spec/data/app/config/test.json +3 -0
- data/spec/plugin_spec.rb +42 -0
- data/spec/spec_helper.rb +3 -0
- metadata +81 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 197e078f9b2e93718eedbde53a8c453536c166a2
|
4
|
+
data.tar.gz: ff87a1819aacea18aa67db93c54c1364d14d388e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 90ab0ea4b657163aaf74ffd388377ac730e073292a56ccfab08fe9ea70f60d1e091dc6ed5205729b107bc22593e4725f0e2ce2ea4173231fb4d77d9b2ecd848d
|
7
|
+
data.tar.gz: 8e176b651fc34d7d05e18d510214c9967f5e867bcd6c40997377abf5603f1a1392f0e1b79fd6284eb399235d7b361921fef458142979e969e118b1e317b74a31
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
pipeline.rb (0.0.1)
|
5
|
+
amq-client
|
6
|
+
|
7
|
+
GEM
|
8
|
+
specs:
|
9
|
+
amq-client (1.0.4)
|
10
|
+
amq-protocol (>= 1.9.0)
|
11
|
+
eventmachine
|
12
|
+
amq-protocol (1.9.2)
|
13
|
+
diff-lcs (1.2.5)
|
14
|
+
eventmachine (1.0.3)
|
15
|
+
rspec-core (2.14.7)
|
16
|
+
rspec-expectations (2.14.4)
|
17
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
18
|
+
|
19
|
+
PLATFORMS
|
20
|
+
ruby
|
21
|
+
|
22
|
+
DEPENDENCIES
|
23
|
+
pipeline.rb!
|
24
|
+
rspec-core
|
25
|
+
rspec-expectations
|
data/LINCENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 @botanicus
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
# About
|
2
|
+
|
3
|
+
Plugin pipeline infrastructure connected **through RabbitMQ**. The plugins are just **normal Ruby gems**.
|
4
|
+
|
5
|
+
```
|
6
|
+
Instance(s) of plugin 1 -> RabbitMQ broker -> Instance(s) of plugin 2
|
7
|
+
```
|
8
|
+
|
9
|
+
It uses `amq.topic` exchange, so **you can use globs** to consume from within a plugin or a custom script. So if you want to see all the messages going through the system, simply create a queue a bind it to `amq.topic` with routing key `#`. Need all the events? `#event#`. Easy as that.
|
10
|
+
|
11
|
+
# Why?
|
12
|
+
|
13
|
+
It's been proved over and over that splitting app into services and is the way to go, because:
|
14
|
+
|
15
|
+
* It's **easier to maintain** such app.
|
16
|
+
* **Rewriting components** is easy.
|
17
|
+
* It's **easy to scale** by adding more consumers of given service.
|
18
|
+
* It's **easy to inspect** what's going on.
|
19
|
+
* It's much **easier to split work** on the project between multiple developers.
|
20
|
+
* You can **restart services without losing any data**, as they are kept in RabbitMQ.
|
21
|
+
* You don't have to introduce any code dependencies: just consume given queue and publish to another one.
|
22
|
+
|
23
|
+
# Settings
|
24
|
+
|
25
|
+
Pipeline.rb uses JSON for configuration.
|
26
|
+
|
27
|
+
The cool thing is it supports global and local configuration. That means for instance if you want to configure a database, you're probably going to use the same database drivers on either development machine or on production server.
|
28
|
+
|
29
|
+
So first let's create a global configuration file `config/database.json`:
|
30
|
+
|
31
|
+
```json
|
32
|
+
{
|
33
|
+
"adapter": "mysql",
|
34
|
+
"username": "mysql",
|
35
|
+
"database": "example"
|
36
|
+
}
|
37
|
+
```
|
38
|
+
|
39
|
+
And now the local `config/database.local.json`:
|
40
|
+
|
41
|
+
```json
|
42
|
+
{
|
43
|
+
"password": "ae28cd87adb5c385117f89e9bd452d18"
|
44
|
+
}
|
45
|
+
```
|
46
|
+
|
47
|
+
Don't forget to ignore the local settings `.gitignore`:
|
48
|
+
|
49
|
+
```
|
50
|
+
config/*.local.json
|
51
|
+
```
|
52
|
+
|
53
|
+
# HOWTO
|
54
|
+
|
55
|
+
Pipeline.rb expects you to provide AMQP configuration, so it knows how to connect to RabbitMQ:
|
56
|
+
|
57
|
+
`config/amqp.json`:
|
58
|
+
|
59
|
+
```json
|
60
|
+
{
|
61
|
+
"vhost": "example",
|
62
|
+
"user": "example",
|
63
|
+
}
|
64
|
+
```
|
65
|
+
|
66
|
+
`config/amqp.local.json`:
|
67
|
+
|
68
|
+
```json
|
69
|
+
{
|
70
|
+
"password": "ae28cd87adb5c385117f89e9bd452d18"
|
71
|
+
}
|
72
|
+
```
|
73
|
+
|
74
|
+
Don't forget to ignore the local settings `.gitignore`:
|
75
|
+
|
76
|
+
```
|
77
|
+
config/*.local.json
|
78
|
+
```
|
79
|
+
|
80
|
+
Shop for plugins and add them to your `Gemfile`:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
source 'https://rubygems.org'
|
84
|
+
|
85
|
+
# The app uses pipeline.rb itself.
|
86
|
+
gem 'pipeline.rb'
|
87
|
+
|
88
|
+
# Tasks.
|
89
|
+
gem 'nake'
|
90
|
+
|
91
|
+
# Existing pipeline.rb plugins.
|
92
|
+
group(:plugins) do
|
93
|
+
gem 'mail_queue'
|
94
|
+
end
|
95
|
+
```
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
#!/usr/bin/env bundle exec ruby
|
99
|
+
|
100
|
+
require 'nake/runner'
|
101
|
+
|
102
|
+
# Load all the plugins.
|
103
|
+
Bundler.require(:plugins)
|
104
|
+
|
105
|
+
# Tasks: declare.
|
106
|
+
require 'pipeline/tasks'
|
107
|
+
|
108
|
+
Nake.run
|
109
|
+
```
|
110
|
+
|
111
|
+
Now run `./tasks.rb declare` to declare all the required queues.
|
112
|
+
|
113
|
+
And finally create your app:
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
require 'mail_queue'
|
117
|
+
|
118
|
+
# This is already loaded,
|
119
|
+
# but just to make it clear
|
120
|
+
# that the app is actually
|
121
|
+
# just another plugin.
|
122
|
+
require 'pipeline/plugin'
|
123
|
+
|
124
|
+
class App < Pipeline::Plugin
|
125
|
+
def run
|
126
|
+
EM.add_timer(0.5) do
|
127
|
+
client.publish("Hello World!", 'emails.random')
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
133
|
+
And finally run it all:
|
134
|
+
|
135
|
+
1. Start RabbitMQ.
|
136
|
+
2. Start `bin/mail_queue.rb` to send your emails.
|
137
|
+
3. Run your app.
|
138
|
+
|
139
|
+
# Deployment
|
140
|
+
|
141
|
+
TODO: Show example Upstart scripts.
|
data/example/Gemfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Local Machine
|
4
|
+
# bundle config local.pipeline-mail_queue ~/Dropbox/Code/pipeline-plugins/mail_queue
|
5
|
+
# bundle config local.pipeline.rb ~/Dropbox/Code/sources/pipeline.rb
|
6
|
+
# bundle config local.nake ~/Dropbox/Code/sources/nake
|
7
|
+
gem 'pipeline.rb', github: 'botanicus/pipeline.rb', branch: 'master'
|
8
|
+
gem 'nake', github: 'botanicus/nake', branch: 'master'
|
9
|
+
|
10
|
+
group(:plugins) do
|
11
|
+
gem 'pipeline-mail_queue', github: 'botanicus/pipeline-mail_queue', branch: 'master'
|
12
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
GIT
|
2
|
+
remote: git://github.com/botanicus/nake.git
|
3
|
+
revision: 6361daacec1caa6af9e12e7e52e0fcb6cf1b91ac
|
4
|
+
branch: master
|
5
|
+
specs:
|
6
|
+
nake (0.0.9.5)
|
7
|
+
term-ansicolor
|
8
|
+
|
9
|
+
GIT
|
10
|
+
remote: git://github.com/botanicus/pipeline-mail_queue.git
|
11
|
+
revision: 5f860a6a01de0a85f181e918f1432c05a20b5b37
|
12
|
+
branch: master
|
13
|
+
specs:
|
14
|
+
pipeline-mail_queue (0.0.1)
|
15
|
+
mail
|
16
|
+
pipeline.rb
|
17
|
+
|
18
|
+
GIT
|
19
|
+
remote: git://github.com/botanicus/pipeline.rb.git
|
20
|
+
revision: 345259bc7bc48b8e3a5cc6e8e2594aaefe2bfa96
|
21
|
+
branch: master
|
22
|
+
specs:
|
23
|
+
pipeline.rb (0.0.1)
|
24
|
+
amq-client
|
25
|
+
|
26
|
+
GEM
|
27
|
+
remote: https://rubygems.org/
|
28
|
+
specs:
|
29
|
+
amq-client (1.0.4)
|
30
|
+
amq-protocol (>= 1.9.0)
|
31
|
+
eventmachine
|
32
|
+
amq-protocol (1.9.2)
|
33
|
+
eventmachine (1.0.3)
|
34
|
+
mail (2.5.4)
|
35
|
+
mime-types (~> 1.16)
|
36
|
+
treetop (~> 1.4.8)
|
37
|
+
mime-types (1.25.1)
|
38
|
+
polyglot (0.3.3)
|
39
|
+
term-ansicolor (1.2.2)
|
40
|
+
tins (~> 0.8)
|
41
|
+
tins (0.13.1)
|
42
|
+
treetop (1.4.15)
|
43
|
+
polyglot
|
44
|
+
polyglot (>= 0.3.1)
|
45
|
+
|
46
|
+
PLATFORMS
|
47
|
+
ruby
|
48
|
+
|
49
|
+
DEPENDENCIES
|
50
|
+
nake!
|
51
|
+
pipeline-mail_queue!
|
52
|
+
pipeline.rb!
|
data/example/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# About
|
2
|
+
|
3
|
+
# Setup
|
4
|
+
|
5
|
+
## Set Up and Run RabbitMQ
|
6
|
+
|
7
|
+
```bash
|
8
|
+
rabbitmqctl add_user example ae28cd87adb5c385117f89e9bd452d18
|
9
|
+
rabbitmqctl add_vhost example
|
10
|
+
rabbitmqctl set_permissions -p example example '.*' '.*' '.*'
|
11
|
+
```
|
12
|
+
|
13
|
+
## Fill In Your Gmail Details
|
14
|
+
|
15
|
+
`config/smtp.local.json`
|
16
|
+
|
17
|
+
```json
|
18
|
+
{
|
19
|
+
"user_name": "you@gmail.com",
|
20
|
+
"password": "password",
|
21
|
+
}
|
22
|
+
```
|
23
|
+
|
24
|
+
## Run Bundler
|
25
|
+
|
26
|
+
`bundle install`
|
27
|
+
|
28
|
+
## Declare Queues
|
29
|
+
|
30
|
+
`./tasks.rb declare`
|
31
|
+
|
32
|
+
## Run `mail_queue` Consumer
|
33
|
+
|
34
|
+
`bundle exec mail_queue.rb`
|
35
|
+
|
36
|
+
## Run The App
|
37
|
+
|
38
|
+
`./app.rb`
|
data/example/app.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env bundle exec ruby
|
2
|
+
|
3
|
+
require 'mail_queue'
|
4
|
+
|
5
|
+
# This is already loaded,
|
6
|
+
# but just to make it clear
|
7
|
+
# that the app is actually
|
8
|
+
# just another plugin.
|
9
|
+
require 'pipeline/plugin'
|
10
|
+
|
11
|
+
$receiver_email = (ARGV.shift || abort("Usage: #{$0} [receiver_email"))
|
12
|
+
|
13
|
+
class App < Pipeline::Plugin
|
14
|
+
def run
|
15
|
+
email = Mail.new do
|
16
|
+
from 'james@101ideas.cz'
|
17
|
+
to $receiver_email
|
18
|
+
subject "Hello World!"
|
19
|
+
body "Hello World!"
|
20
|
+
end
|
21
|
+
|
22
|
+
EM.add_periodic_timer(1.5) do
|
23
|
+
puts "~ Publishing #{email.inspect}"
|
24
|
+
client.publish(email.to_s, 'emails.random')
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
App.run(Dir.pwd)
|
data/example/tasks.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'amq/client'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
# We aren't handling TCP connection lost, since this is running on the same machine.
|
6
|
+
# It means, however, that if we restart the broker, we have to restart all the services manually.
|
7
|
+
module Pipeline
|
8
|
+
class Client
|
9
|
+
def self.boot(config)
|
10
|
+
client = self.new
|
11
|
+
|
12
|
+
# Next tick, so we can use it with Thin.
|
13
|
+
EM.next_tick do
|
14
|
+
client.connect(config.merge(adapter: 'eventmachine'))
|
15
|
+
|
16
|
+
# Set up signals.
|
17
|
+
['INT', 'TERM'].each do |signal|
|
18
|
+
Signal.trap(signal) do
|
19
|
+
puts "~ Received #{signal} signal, terminating."
|
20
|
+
client.disconnect { EM.stop }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
client
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
@on_open_callbacks = Array.new
|
30
|
+
end
|
31
|
+
|
32
|
+
attr_reader :connection, :channel, :exchange, :on_open_callbacks
|
33
|
+
def connect(opts)
|
34
|
+
@connection = AMQ::Client.connect(opts)
|
35
|
+
@channel = AMQ::Client::Channel.new(@connection, 1)
|
36
|
+
|
37
|
+
@connection.on_open do
|
38
|
+
puts "~ Connected to RabbitMQ."
|
39
|
+
|
40
|
+
@channel.open do
|
41
|
+
self.on_open_callbacks.each do |callback|
|
42
|
+
callback.call
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def exchange
|
49
|
+
@exchange ||= AMQ::Client::Exchange.new(@connection, @channel, 'amq.topic')
|
50
|
+
end
|
51
|
+
|
52
|
+
def declare_queue(name, routing_key)
|
53
|
+
queue = AMQ::Client::Queue.new(@connection, @channel, name)
|
54
|
+
|
55
|
+
self.on_open do
|
56
|
+
queue.declare(false, true, false, true) do
|
57
|
+
# puts "~ Queue #{queue.name.inspect} is ready"
|
58
|
+
end
|
59
|
+
|
60
|
+
queue.bind(self.exchange.name, routing_key) do
|
61
|
+
puts "~ Queue #{queue.name} is now bound to #{self.exchange.name} with routing key #{routing_key}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
queue
|
66
|
+
end
|
67
|
+
|
68
|
+
def consumer(name, routing_key = name, &block)
|
69
|
+
queue = self.declare_queue(name, routing_key)
|
70
|
+
|
71
|
+
queue.consume(true) do |consume_ok|
|
72
|
+
puts "Subscribed for messages routed to #{queue.name}, consumer tag is #{consume_ok.consumer_tag}, using no-ack mode"
|
73
|
+
|
74
|
+
queue.on_delivery do |basic_deliver, header, payload|
|
75
|
+
block.call(payload, header, basic_deliver)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# This runs after the channel is open.
|
81
|
+
# TODO: Why amq-client doesn't support adding multiple callbacks?
|
82
|
+
def on_open(&block)
|
83
|
+
if @channel.status == :opening
|
84
|
+
self.on_open_callbacks << block
|
85
|
+
else
|
86
|
+
block.call
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def publish(*args)
|
91
|
+
self.exchange.publish(*args)
|
92
|
+
end
|
93
|
+
|
94
|
+
def disconnect(&block)
|
95
|
+
@connection.disconnect(&block)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'pathname'
|
3
|
+
require 'pipeline/client'
|
4
|
+
|
5
|
+
module Pipeline
|
6
|
+
class Plugin
|
7
|
+
def self.plugins
|
8
|
+
@@plugins ||= Array.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.inherited(subclass)
|
12
|
+
Pipeline::Plugin.plugins << subclass
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.run(root)
|
16
|
+
plugin = self.new(root)
|
17
|
+
|
18
|
+
Dir.chdir(plugin.root.to_s) do
|
19
|
+
EM.run do
|
20
|
+
# First runs next tick from Client.boot.
|
21
|
+
EM.next_tick do
|
22
|
+
plugin.run!
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
attr_reader :root
|
29
|
+
def initialize(root)
|
30
|
+
@root = Pathname.new(root)
|
31
|
+
@config = Hash.new
|
32
|
+
|
33
|
+
self.client
|
34
|
+
end
|
35
|
+
|
36
|
+
def config(key)
|
37
|
+
@config[key] ||= begin
|
38
|
+
path = self.root.join("config/#{key}.json")
|
39
|
+
data = JSON.parse(path.read)
|
40
|
+
|
41
|
+
path = self.root.join("config/#{key}.local.json")
|
42
|
+
data.merge!(JSON.parse(path.read)) if path.exist?
|
43
|
+
|
44
|
+
data.reduce(Hash.new) do |buffer, (key, value)|
|
45
|
+
buffer.merge!(key.to_sym => value)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def client
|
51
|
+
@client ||= Pipeline::Client.boot(self.config('amqp'))
|
52
|
+
end
|
53
|
+
|
54
|
+
def run!
|
55
|
+
self.client.on_open do
|
56
|
+
EM.add_timer(0.1) do # Oh my, yeah, whatever, it's for now only, dammit!
|
57
|
+
puts "~ Running #{self.class}#run."
|
58
|
+
self.run
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'nake'
|
2
|
+
|
3
|
+
Nake::Task.new(:queues) do |task|
|
4
|
+
task.define do
|
5
|
+
Pipeline::Plugin.plugins.each do |plugin|
|
6
|
+
puts "#{plugin}: #{plugin::QUEUES.inspect rescue []}"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
Nake::Task.new(:declare) do |task|
|
13
|
+
task.define do
|
14
|
+
abort "Still on the TODO list.\nFor now, just run all the consumers and everything gets declared at runtime."
|
15
|
+
end
|
16
|
+
end
|
data/pipeline.rb.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env gem build
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
|
4
|
+
|
5
|
+
require 'pipeline/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |s|
|
8
|
+
s.name = 'pipeline.rb'
|
9
|
+
s.version = Pipeline::VERSION
|
10
|
+
s.authors = ['@botanicus']
|
11
|
+
s.homepage = 'http://github.com/botanicus/pipeline.rb'
|
12
|
+
s.summary = "Plugin pipeline infrastructure connected through RabbitMQ."
|
13
|
+
s.description = "#{s.summary}. Asynchronous and robust. Also contains configuration system."
|
14
|
+
s.email = 'james@101ideas.cz'
|
15
|
+
s.files = Dir.glob('**/*')
|
16
|
+
s.license = 'MIT'
|
17
|
+
s.require_paths = ['lib']
|
18
|
+
|
19
|
+
s.add_dependency 'amq-client'
|
20
|
+
end
|
data/spec/plugin_spec.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'pipeline/plugin'
|
4
|
+
|
5
|
+
describe Pipeline::Plugin do
|
6
|
+
describe '#new(root)' do
|
7
|
+
it "takes one argument which is the root directory" do
|
8
|
+
expect { described_class.new(File.join(Dir.pwd, 'spec', 'data', 'app')) }.not_to raise_error
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '#root' do
|
13
|
+
subject { described_class.new(File.join(Dir.pwd, 'spec', 'data', 'app')) }
|
14
|
+
|
15
|
+
it "returns path to the root directory" do
|
16
|
+
subject.root.should be_kind_of(Pathname)
|
17
|
+
subject.root.to_s.should match('pipeline.rb/spec/data/app')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe '#config' do
|
22
|
+
subject { described_class.new(File.join(Dir.pwd, 'spec', 'data', 'app')) }
|
23
|
+
|
24
|
+
let(:config) { subject.config('smtp') }
|
25
|
+
|
26
|
+
it "contains the global settings" do
|
27
|
+
config[:address].should eql('smtp.gmail.com')
|
28
|
+
end
|
29
|
+
|
30
|
+
it "contains the global settings" do
|
31
|
+
config[:password].should eql('password.local')
|
32
|
+
end
|
33
|
+
|
34
|
+
it "overrides the global settings by the local settings" do
|
35
|
+
config[:user_name].should eql('user.local')
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should not require local settings" do
|
39
|
+
subject.config('test')[:local].should be_false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pipeline.rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- '@botanicus'
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: amq-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
description: Plugin pipeline infrastructure connected through RabbitMQ.. Asynchronous
|
28
|
+
and robust. Also contains configuration system.
|
29
|
+
email: james@101ideas.cz
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- example/app.rb
|
35
|
+
- example/config/amqp.json
|
36
|
+
- example/config/smtp.json
|
37
|
+
- example/config/smtp.local.json
|
38
|
+
- example/Gemfile
|
39
|
+
- example/Gemfile.lock
|
40
|
+
- example/README.md
|
41
|
+
- example/tasks.rb
|
42
|
+
- Gemfile
|
43
|
+
- Gemfile.lock
|
44
|
+
- lib/pipeline/client.rb
|
45
|
+
- lib/pipeline/plugin.rb
|
46
|
+
- lib/pipeline/tasks.rb
|
47
|
+
- lib/pipeline/version.rb
|
48
|
+
- LINCENSE
|
49
|
+
- pipeline.rb.gemspec
|
50
|
+
- README.md
|
51
|
+
- spec/data/app/config/amqp.json
|
52
|
+
- spec/data/app/config/smtp.json
|
53
|
+
- spec/data/app/config/smtp.local.json
|
54
|
+
- spec/data/app/config/test.json
|
55
|
+
- spec/plugin_spec.rb
|
56
|
+
- spec/spec_helper.rb
|
57
|
+
homepage: http://github.com/botanicus/pipeline.rb
|
58
|
+
licenses:
|
59
|
+
- MIT
|
60
|
+
metadata: {}
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options: []
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - '>='
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '0'
|
75
|
+
requirements: []
|
76
|
+
rubyforge_project:
|
77
|
+
rubygems_version: 2.0.3
|
78
|
+
signing_key:
|
79
|
+
specification_version: 4
|
80
|
+
summary: Plugin pipeline infrastructure connected through RabbitMQ.
|
81
|
+
test_files: []
|