bluecollar-client 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in bluecollar-client.gemspec
4
+ gemspec
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
+ module Bluecollar
2
+ class ClientError < StandardError
3
+
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module Bluecollar
2
+ VERSION = "0.0.4"
3
+ 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")
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+ require 'redis'
4
+ require 'rake'
5
+ require 'time'
6
+
7
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/bluecollar-client")
@@ -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