bluecollar-client 0.0.4
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/.gitignore +17 -0
- data/Gemfile +4 -0
- data/README.md +54 -0
- data/Rakefile +1 -0
- data/bluecollar-client.gemspec +28 -0
- data/lib/bluecollar-client/client.rb +63 -0
- data/lib/bluecollar-client/client_error.rb +5 -0
- data/lib/bluecollar-client/version.rb +3 -0
- data/lib/bluecollar-client.rb +5 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/units/client_spec.rb +114 -0
- metadata +177 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Bluecollar::Client
|
2
|
+
|
3
|
+
The `Bluecollar::Client` is a ruby interface to [bluecollar.core](https://github.com/techwhizbang/bluecollar).
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'bluecollar-client'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install bluecollar-client
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
`Bluecollar::Client` is intended to act as a ruby interface to `bluecollar.core`. It basically pushes job messages to Redis that are picked up and processed by `bluecollar.core`.
|
22
|
+
|
23
|
+
In order to start using `Bluecollar::Client`:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
require "bluecollar-client"
|
27
|
+
|
28
|
+
# to configure client
|
29
|
+
Bluecollar::Client.configure(redis_key_prefix: "optional_prefix",
|
30
|
+
redis_hostname: "hostname",
|
31
|
+
redis_port: 6379,
|
32
|
+
redis_db: 6,
|
33
|
+
redis_timeout: 5000)
|
34
|
+
|
35
|
+
# create async job
|
36
|
+
Bluecollar::Client.instance.async_job_for(worker_name, args_hash)
|
37
|
+
```
|
38
|
+
|
39
|
+
|
40
|
+
## Contributing
|
41
|
+
|
42
|
+
1. Fork it
|
43
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
44
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
45
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
46
|
+
5. Create new Pull Request
|
47
|
+
|
48
|
+
## License
|
49
|
+
|
50
|
+
Copyright (c) 2013 Denny Quesada
|
51
|
+
|
52
|
+
Distributed under the Eclipse Public License.
|
53
|
+
http://www.eclipse.org/legal/epl-v10.html
|
54
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'bluecollar-client/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "bluecollar-client"
|
8
|
+
spec.version = Bluecollar::VERSION
|
9
|
+
spec.authors = ["Denny Quesada"]
|
10
|
+
spec.email = ["denny.quesada@bookrenter.com"]
|
11
|
+
spec.description = %q{Bluecollar client written in Ruby}
|
12
|
+
spec.summary = %q{Bluecollar client written in Ruby}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "EPL"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency "redis"
|
22
|
+
spec.add_runtime_dependency %q<json>
|
23
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
24
|
+
spec.add_development_dependency "rake"
|
25
|
+
spec.add_development_dependency %q<rspec>, ["~> 2.11.0"]
|
26
|
+
spec.add_development_dependency %q<pry>
|
27
|
+
spec.add_development_dependency %q<faker>
|
28
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Bluecollar
|
2
|
+
class Client
|
3
|
+
|
4
|
+
attr_accessor :redis_key_prefix, :redis_hostname, :redis_port, :redis_db, :redis_timeout
|
5
|
+
|
6
|
+
class << self
|
7
|
+
|
8
|
+
attr_reader :configuration, :logger, :instance
|
9
|
+
|
10
|
+
def configure(options = {})
|
11
|
+
@instance = nil
|
12
|
+
|
13
|
+
@logger = options[:logger] || Logger.new("/dev/null")
|
14
|
+
|
15
|
+
@configuration = {}
|
16
|
+
@configuration[:redis_key_prefix] = options[:redis_key_prefix] || "bluecollar"
|
17
|
+
@configuration[:redis_hostname] = options[:redis_hostname] || "127.0.0.1"
|
18
|
+
@configuration[:redis_port] = (options[:redis_port] || 6379).to_i
|
19
|
+
@configuration[:redis_db] = options[:redis_db].to_i
|
20
|
+
@configuration[:redis_timeout] = (options[:redis_timeout] || 5000).to_i
|
21
|
+
end
|
22
|
+
|
23
|
+
def instance
|
24
|
+
@instance ||= new(@configuration)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def async_job_for(worker_name, args)
|
29
|
+
redis_connection.lpush processing_queue, redis_payload(worker_name, args)
|
30
|
+
rescue Redis::BaseError => e
|
31
|
+
Bluecollar::Client.logger.warn("Error while adding #{worker_name}: #{args.inspect} to queue.\n#{e}:#{e.message}\nBacktrace:\n\t#{e.backtrace.join("\n\t")}")
|
32
|
+
raise Bluecollar::ClientError.new("Error while adding #{worker_name}: #{args.inspect} to queue.\n#{e}:#{e.message}\nBacktrace:\n\t#{e.backtrace.join("\n\t")}")
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def initialize(options)
|
38
|
+
options.each { |k,v| send("#{k}=".to_sym, v) }
|
39
|
+
end
|
40
|
+
|
41
|
+
def redis_payload(worker_name, args)
|
42
|
+
raise ArgumentError.new("args must be an Array.") unless args.is_a? Array
|
43
|
+
|
44
|
+
begin
|
45
|
+
payload = { worker: worker_name, args: args }
|
46
|
+
JSON.dump(payload)
|
47
|
+
rescue
|
48
|
+
raise Bluecollar::ClientError.new("Error while creating JSON payload for #{worker_name}: #{args.inpsect}.\n#{e}:#{e.message}\nBacktrace:\n\t#{e.backtrace.join("\n\t")}")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def processing_queue
|
53
|
+
@processing_queue ||= "#{redis_key_prefix}:queues:master"
|
54
|
+
end
|
55
|
+
|
56
|
+
def redis_connection
|
57
|
+
@redis_connection ||= Redis.new(host: redis_hostname,
|
58
|
+
port: redis_port,
|
59
|
+
db: redis_db,
|
60
|
+
timeout: redis_timeout)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,5 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require 'json'
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + "/bluecollar-client/version")
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + "/bluecollar-client/client_error")
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + "/bluecollar-client/client")
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Bluecollar::Client do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
Bluecollar::Client.configure
|
7
|
+
end
|
8
|
+
|
9
|
+
describe ".initialize" do
|
10
|
+
context "with configuration data" do
|
11
|
+
before do
|
12
|
+
Bluecollar::Client.configure
|
13
|
+
end
|
14
|
+
|
15
|
+
subject { Bluecollar::Client.instance }
|
16
|
+
|
17
|
+
its(:redis_key_prefix) { should == "bluecollar" }
|
18
|
+
its(:redis_hostname) { should == "127.0.0.1" }
|
19
|
+
its(:redis_port) { should == 6379 }
|
20
|
+
its(:redis_db) { should == 0 }
|
21
|
+
its(:redis_timeout) { should == 5000 }
|
22
|
+
end
|
23
|
+
|
24
|
+
context "with configuration data" do
|
25
|
+
before do
|
26
|
+
Bluecollar::Client.configure(redis_key_prefix: "test_prefix",
|
27
|
+
redis_hostname: "test_hostname",
|
28
|
+
redis_port: 4567,
|
29
|
+
redis_db: 99,
|
30
|
+
redis_timeout: 1000)
|
31
|
+
end
|
32
|
+
|
33
|
+
subject { Bluecollar::Client.instance }
|
34
|
+
|
35
|
+
its(:redis_key_prefix) { should == "test_prefix" }
|
36
|
+
its(:redis_hostname) { should == "test_hostname" }
|
37
|
+
its(:redis_port) { should == 4567 }
|
38
|
+
its(:redis_db) { should == 99 }
|
39
|
+
its(:redis_timeout) { should == 1000 }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#processing_queue" do
|
44
|
+
|
45
|
+
subject { Bluecollar::Client.instance.send(:processing_queue) }
|
46
|
+
|
47
|
+
context "when redis_key_prefix is set" do
|
48
|
+
before do
|
49
|
+
Bluecollar::Client.configure(redis_key_prefix: "test_prefix")
|
50
|
+
end
|
51
|
+
|
52
|
+
it { should == "test_prefix:queues:master" }
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when no prefix is provided" do
|
56
|
+
it { should == "bluecollar:queues:master" }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "#redis_connection" do
|
61
|
+
subject { Bluecollar::Client.instance.send(:redis_connection) }
|
62
|
+
|
63
|
+
it { should be_a Redis }
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#redis_payload" do
|
67
|
+
context "with valid arguments" do
|
68
|
+
subject { JSON.parse Bluecollar::Client.instance.send(:redis_payload, 'lazy_worker', [{arg1:"first"}]) }
|
69
|
+
|
70
|
+
it "should have the expected worker" do
|
71
|
+
subject['worker'].should eq("lazy_worker")
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should have the expected args" do
|
75
|
+
subject['args'].first['arg1'].should eq("first")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "with a args argument that is not an Array" do
|
80
|
+
subject { JSON.parse Bluecollar::Client.instance.send(:redis_payload, 'lazy_worker', {arg1:"first"}) }
|
81
|
+
|
82
|
+
it "should raise an error" do
|
83
|
+
expect { subject }.to raise_error(ArgumentError)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "#async_job_for" do
|
89
|
+
subject { Bluecollar::Client.instance }
|
90
|
+
|
91
|
+
it "should push the data to the right queue" do
|
92
|
+
payload = subject.send(:redis_payload, 'lazy_worker', [{arg1:"first"}])
|
93
|
+
queue = subject.send :processing_queue
|
94
|
+
mock = double('redis')
|
95
|
+
Bluecollar::Client.any_instance.stub(:redis_connection){ mock }
|
96
|
+
mock.should_receive(:lpush).with(queue, payload)
|
97
|
+
subject.async_job_for('lazy_worker', [{arg1:"first"}])
|
98
|
+
end
|
99
|
+
|
100
|
+
context "when a BaseError is raised" do
|
101
|
+
before do
|
102
|
+
mock = double('redis')
|
103
|
+
Bluecollar::Client.any_instance.stub(:redis_connection){ mock }
|
104
|
+
mock.should_receive(:lpush) { raise Redis::BaseError.new("BaseError") }
|
105
|
+
end
|
106
|
+
|
107
|
+
subject { Bluecollar::Client.instance.async_job_for('lazy_worker', [{arg1:"first"}]) }
|
108
|
+
|
109
|
+
it "should raise an error" do
|
110
|
+
expect { subject }.to raise_error(Bluecollar::ClientError)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
metadata
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bluecollar-client
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.4
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Denny Quesada
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-08-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: redis
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: json
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: bundler
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.3'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.3'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rspec
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ~>
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: 2.11.0
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ~>
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 2.11.0
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: pry
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: faker
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
description: Bluecollar client written in Ruby
|
127
|
+
email:
|
128
|
+
- denny.quesada@bookrenter.com
|
129
|
+
executables: []
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- .gitignore
|
134
|
+
- Gemfile
|
135
|
+
- README.md
|
136
|
+
- Rakefile
|
137
|
+
- bluecollar-client.gemspec
|
138
|
+
- lib/bluecollar-client.rb
|
139
|
+
- lib/bluecollar-client/client.rb
|
140
|
+
- lib/bluecollar-client/client_error.rb
|
141
|
+
- lib/bluecollar-client/version.rb
|
142
|
+
- spec/spec_helper.rb
|
143
|
+
- spec/units/client_spec.rb
|
144
|
+
homepage: ''
|
145
|
+
licenses:
|
146
|
+
- EPL
|
147
|
+
post_install_message:
|
148
|
+
rdoc_options: []
|
149
|
+
require_paths:
|
150
|
+
- lib
|
151
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
152
|
+
none: false
|
153
|
+
requirements:
|
154
|
+
- - ! '>='
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '0'
|
157
|
+
segments:
|
158
|
+
- 0
|
159
|
+
hash: -3735982979290534258
|
160
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ! '>='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
segments:
|
167
|
+
- 0
|
168
|
+
hash: -3735982979290534258
|
169
|
+
requirements: []
|
170
|
+
rubyforge_project:
|
171
|
+
rubygems_version: 1.8.25
|
172
|
+
signing_key:
|
173
|
+
specification_version: 3
|
174
|
+
summary: Bluecollar client written in Ruby
|
175
|
+
test_files:
|
176
|
+
- spec/spec_helper.rb
|
177
|
+
- spec/units/client_spec.rb
|