requeus 0.0.2

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/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Ilia Ablamonov, Anatoliy Plastinin, Cloud Castle Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,12 @@
1
+ = requeus
2
+
3
+ Requeus is a library for proxying http requests via queue (currently supports Amazon SQS and RabbitMQ).
4
+ It consists of two parts:
5
+ * client for adding request to queue
6
+ * and background worker for processing queue
7
+
8
+ == Copyright
9
+
10
+ Copyright (c) 2011 Ilia Ablamonov, Anatoliy Plastinin, Cloud Castle Inc. See LICENSE.txt for
11
+ further details.
12
+
data/lib/requeus.rb ADDED
@@ -0,0 +1,23 @@
1
+ require 'thread'
2
+
3
+ %w(blob_store impl queue request server adapters).each do |file|
4
+ require "requeus/#{file}"
5
+ end
6
+
7
+ require 'requeus/railtie' if defined?(Rails)
8
+
9
+ module Requeus
10
+ class << self
11
+ def request queue, method, path, params = {}, headers = {}
12
+ Requeus::Impl.instance.request queue, method, path, params, headers
13
+ end
14
+
15
+ def start_workers
16
+ Requeus::Impl.instance.start_workers
17
+ end
18
+
19
+ def config_path= path;
20
+ Requeus::Impl.instance.config_path = path;
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,46 @@
1
+ require 'fileutils'
2
+
3
+ module Requeus
4
+ module Adapter
5
+ class Filesystem
6
+ def initialize opts
7
+ @path = opts['path']
8
+ ensure_path
9
+ end
10
+
11
+ def put file
12
+ uid = generate_id
13
+ FileUtils.copy file.path, path_for(uid)
14
+ FileUtils.chmod 0666, path_for(uid)
15
+ uid
16
+ end
17
+
18
+ def get uid
19
+ return nil unless File.exists?(path_for(uid))
20
+ File.new path_for(uid)
21
+ end
22
+
23
+ def delete uid
24
+ FileUtils.remove path_for(uid)
25
+ true
26
+ end
27
+
28
+ private
29
+
30
+ def path_for uid
31
+ File.join @path, uid
32
+ end
33
+
34
+ def ensure_path
35
+ FileUtils.mkdir_p(@path) unless File.exists?(@path)
36
+ raise "Path '#{@path}' is not writable" unless File.writable?(@path)
37
+ end
38
+
39
+ def generate_id
40
+ UUIDTools::UUID.timestamp_create().to_s
41
+ end
42
+
43
+ Requeus::BlobStore.adapters['filesystem'] = self
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,79 @@
1
+ require 'carrot'
2
+
3
+ #todo: schedule 'recover' action to mimic SQS behaviour
4
+
5
+ module Requeus
6
+ module Adapter
7
+ class Rabbit
8
+ def initialize opts
9
+ @opts = opts
10
+ end
11
+
12
+ def put queue, request
13
+ cmd cq(queue), :publish, request, :persistent => true
14
+ true
15
+ end
16
+
17
+ def get queue, limit = 1
18
+ result = []
19
+ requests = 0
20
+
21
+ while requests <= limit && r = pop_request(cq(queue))
22
+ result << r
23
+ requests += 1
24
+ end
25
+
26
+ result
27
+ end
28
+
29
+ def confirm queue, handle
30
+ cq(queue).delivery_tag = handle
31
+ cmd cq(queue), :ack
32
+ true
33
+ end
34
+
35
+ private
36
+
37
+ def cq name
38
+ client.queue(name, :durable => true)
39
+ end
40
+
41
+ def pop_request queue
42
+ request = cmd queue, :pop
43
+ [queue.delivery_tag, request] if request
44
+ end
45
+
46
+ def cmd queue, command, *args
47
+ retried = false
48
+ begin
49
+ queue.send(command, *args)
50
+ rescue Carrot::AMQP::Server::ServerDown => e
51
+ puts 'Reconnecting...'
52
+ unless retried
53
+ drop_client
54
+ retried = true
55
+ retry
56
+ else
57
+ raise e
58
+ end
59
+ end
60
+ end
61
+
62
+ def drop_client
63
+ Thread.current[:requeus_rabbit_client] = nil
64
+ end
65
+
66
+ def client
67
+ Thread.current[:requeus_rabbit_client] ||= Carrot.new(
68
+ :host => @opts['host'],
69
+ :port => @opts['port'].to_i,
70
+ :user => @opts['user'],
71
+ :pass => @opts['pass'],
72
+ :vhost => @opts['vhost']
73
+ )
74
+ end
75
+
76
+ Requeus::Server.adapters['rabbit'] = self
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,59 @@
1
+ require 'aws'
2
+
3
+ module Requeus
4
+ module Adapter
5
+ class S3 < Filesystem
6
+ def initialize options
7
+ @options = options
8
+ super 'path' => options['cache_path']
9
+ end
10
+
11
+ def put file
12
+ uid = generate_id
13
+ begin
14
+ bucket.put(uid, open(file.path))
15
+ rescue Aws::AwsError
16
+ raise "S3:Failed to upload local file '#{file}' as '#{uid}' to AWS/S3 bucket '#{bucket.name}'"
17
+ end
18
+ uid
19
+ end
20
+
21
+ def delete uid
22
+ bucket.delete_key uid
23
+ super uid
24
+ end
25
+
26
+ def get uid
27
+ key = bucket.key(uid)
28
+ raise "S3:File 's3://#{bucket.name}/#{uid}' doesn't exists" unless key.exists?
29
+ File.open(path_for(uid), 'w') {|f| f.write(key.data) }
30
+ super uid
31
+ end
32
+
33
+ private
34
+
35
+ def connection
36
+ @connection ||= Aws::S3.new(@options['access_key_id'], @options['secret_access_key'])
37
+ end
38
+
39
+ def bucket
40
+ @bucket ||= begin
41
+ bucket = connection.bucket(@options['bucket'])
42
+ bucket = connection.bucket(@options['bucket'], true) unless bucket.exists? #todo: permissions
43
+ bucket
44
+ end
45
+ end
46
+
47
+ Requeus::BlobStore.adapters['s3'] = self
48
+ end
49
+ end
50
+ end
51
+
52
+ class Aws::S3::Bucket
53
+ def exists?
54
+ location
55
+ true
56
+ rescue Aws::AwsError
57
+ false
58
+ end
59
+ end
@@ -0,0 +1,35 @@
1
+ module Requeus
2
+ module Adapter
3
+ class SQS
4
+ def initialize options = {}
5
+ @options = options
6
+ end
7
+
8
+ def put queue, request
9
+ get_queue(queue).send_message(request)
10
+ end
11
+
12
+ def get queue, limit = 1
13
+ get_queue(queue).receive_messages(limit).map do |message|
14
+ [message.receipt_handle, message.body]
15
+ end
16
+ end
17
+
18
+ def confirm queue, handle
19
+ connection.interface.delete_message(connection.interface.queue_url_by_name(queue), handle)
20
+ end
21
+
22
+ private
23
+
24
+ def get_queue queue
25
+ (@queues ||= {})[queue] ||= connection.queue(queue)
26
+ end
27
+
28
+ def connection
29
+ @connection ||= Aws::Sqs.new(@options['access_key_id'], @options['secret_access_key'])
30
+ end
31
+
32
+ Requeus::Server.adapters['sqs'] = self
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,3 @@
1
+ %w(filesystem rabbit s3 sqs).each do |file|
2
+ require "requeus/adapter/#{file}"
3
+ end
@@ -0,0 +1,21 @@
1
+ module Requeus
2
+ class BlobStore
3
+ def initialize name, conf
4
+ @name = name
5
+ @connection = self.class.adapters[conf['adapter']].new(conf)
6
+ end
7
+
8
+ delegate :put, :get, :delete,
9
+ :to => :connection
10
+
11
+ attr_reader :name
12
+
13
+ private
14
+
15
+ attr_reader :connection
16
+
17
+ def self.adapters
18
+ @@adapters ||= {}
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,46 @@
1
+ require 'singleton'
2
+
3
+ module Requeus
4
+ class Impl
5
+ include Singleton
6
+
7
+ def request queue, method, path, params, headers
8
+ r = Requeus::Request.new(method, path, params, headers).to_json
9
+ server_sequence.any? {|q| q.put(queues[queue].name, r)}
10
+ end
11
+
12
+ def start_workers
13
+ queues.values.map {|q| q.start_workers}.flatten.each(&:join)
14
+ end
15
+
16
+ def config_path= path
17
+ @config_path = path
18
+ end
19
+
20
+ def config
21
+ @config ||= YAML.load_file(@config_path)[ENV['REQUEUS_ENV'] || ENV['RAILS_ENV'] || 'development']
22
+ end
23
+
24
+ def queues
25
+ @queues ||= {}.tap do |queues|
26
+ config['queues'].each do |name, conf|
27
+ queues[name] = Requeus::Queue.new conf
28
+ end
29
+ end
30
+ end
31
+
32
+ def server_sequence
33
+ @server_sequence ||= config['servers']['sequence'].split.map do |name|
34
+ conf = @config['servers'][name]
35
+ Requeus::Server.new name, conf
36
+ end
37
+ end
38
+
39
+ def blob_sequence
40
+ @blob_sequence ||= config['blob']['sequence'].split.map do |name|
41
+ conf = @config['blob'][name]
42
+ Requeus::BlobStore.new name, conf
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,54 @@
1
+ module Requeus
2
+ class Queue
3
+ def initialize conf
4
+ @name = conf['name']
5
+ @endpoint = conf['endpoint']
6
+ @workers_count = conf['workers'].to_i
7
+ @interval = conf['interval'].to_f
8
+ end
9
+
10
+ attr_reader :name,
11
+ :endpoint
12
+
13
+ def start_workers
14
+ workers_queue = SizedQueue.new(@workers_count)
15
+
16
+ @workers_count.times.map do
17
+ Thread.new do
18
+ loop do
19
+ begin
20
+ server, queue, handle, request = workers_queue.pop
21
+
22
+ if request.do_request queue.endpoint
23
+ server.confirm queue.name, handle
24
+ request.delete_files
25
+ end
26
+ rescue Exception => e
27
+ puts e
28
+ puts e.backtrace.join("\n")
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ Requeus::Impl.instance.server_sequence.map do |s|
35
+ Thread.new(s) do |server|
36
+ loop do
37
+ begin
38
+ requests = server.get @name, workers_queue.num_waiting
39
+
40
+ if requests.empty?
41
+ sleep server.interval * @interval
42
+ else
43
+ requests.each {|handle, request| workers_queue << [server, self, handle, Requeus::Request.from_json(request)]}
44
+ end
45
+ rescue Exception => e
46
+ puts e
47
+ puts e.backtrace.join("\n")
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,16 @@
1
+ module Requeus
2
+ class Railtie < Rails::Railtie
3
+ rake_tasks do
4
+ load 'tasks/requeus.rake'
5
+ end
6
+
7
+ initializer "requeus.initialize" do
8
+ config_file = Rails.root.join("config", "requeus.yml")
9
+
10
+ if config_file.file?
11
+ Requeus.config_path = config_file
12
+ end
13
+ end
14
+ end
15
+ end
16
+
@@ -0,0 +1,121 @@
1
+ require 'tempfile'
2
+ require 'net/http'
3
+ require 'net/http/post/multipart'
4
+
5
+ # Stub for running outside Rails
6
+ module ActionDispatch; module Http; class UploadedFile; end; end; end
7
+
8
+ module Requeus
9
+ class Request
10
+ def initialize method, path, params, headers, file_uids = nil
11
+ @method = method
12
+ @path = path
13
+ @params = params.reject{|_, v| as_file(v)}
14
+ @headers = headers
15
+
16
+ if file_uids
17
+ @files = file_uids
18
+ else
19
+ @files = params.reject{|_, v| !as_file(v)}
20
+ @files.each {|k, v| @files[k] = upload_file(as_file(v)) if as_file(v)}
21
+ end
22
+ end
23
+
24
+ def self.from_json json
25
+ r = JSON.parse(json)
26
+ new r['method'], r['path'], r['params'], r['headers'], r['files']
27
+ end
28
+
29
+ def do_request endpoint
30
+ uri = URI.parse endpoint + @path
31
+
32
+ req_klass = case @method.upcase
33
+ when 'GET'
34
+ Net::HTTP::Get
35
+ when 'POST'
36
+ Net::HTTP::Post
37
+ when 'PUT'
38
+ Net::HTTP::Put
39
+ when 'DELETE'
40
+ Net::HTTP::Delete
41
+ end
42
+
43
+ res = Net::HTTP.start uri.host, uri.port do |http|
44
+ if @files.present?
45
+ params = @params.dup
46
+ @files.each do |k, uid|
47
+ params[k] = UploadIO.new(download_file(uid), "application/octet-stream")
48
+ end
49
+ req = req_klass::Multipart.new uri.path, params
50
+ else
51
+ req = req_klass.new uri.path
52
+ req.form_data = to_http_data(@params) if req_klass::REQUEST_HAS_BODY
53
+ end
54
+
55
+ @headers.each{|k,v| req.add_field(k, v)}
56
+
57
+ http.request req
58
+ end
59
+
60
+ if res.is_a? Net::HTTPOK
61
+ true
62
+ else
63
+ puts "Error #{res.code} returned for request:"
64
+ puts self.to_json
65
+ false
66
+ end
67
+ end
68
+
69
+ def delete_files
70
+ @files.each do |_, uid|
71
+ blob_sequence.any?{|bs| bs.delete uid}
72
+ end
73
+ end
74
+
75
+ private
76
+
77
+ def upload_file file
78
+ blob_sequence.each do |bs|
79
+ uid = bs.put file
80
+ return uid if uid
81
+ end
82
+ end
83
+
84
+ def download_file uid
85
+ blob_sequence.each do |bs|
86
+ file = bs.get uid
87
+ return file if file
88
+ end
89
+ end
90
+
91
+ def blob_sequence
92
+ Requeus::Impl.instance.blob_sequence
93
+ end
94
+
95
+ def as_file param
96
+ case param
97
+ when File, Tempfile
98
+ param
99
+ when ActionDispatch::Http::UploadedFile
100
+ param.tempfile
101
+ else
102
+ nil
103
+ end
104
+ end
105
+
106
+ #todo: make recursion
107
+ def to_http_data params
108
+ result = {}
109
+ params.each do |k, v|
110
+ if v.is_a?(Hash)
111
+ v.each do |k1, v1|
112
+ result["#{k.to_s}[#{k1.to_s}]"] = v1
113
+ end
114
+ else
115
+ result[k.to_s] = v
116
+ end
117
+ end
118
+ result
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,40 @@
1
+ module Requeus
2
+ class Server
3
+
4
+ private
5
+
6
+ def self.forward_to method_name, obj
7
+ class_eval <<-EOS
8
+ def #{method_name}(*args, &block)
9
+ #{obj}.send(#{method_name.inspect}, *args, &block)
10
+ end
11
+ EOS
12
+ end
13
+
14
+ public
15
+
16
+ forward_to :put, :connection
17
+ forward_to :get, :connection
18
+ forward_to :confirm, :connection
19
+
20
+ def initialize name, conf
21
+ @name = name
22
+ @connection = self.class.adapters[conf['adapter']].new(conf)
23
+ @interval = conf['interval'].to_f
24
+ end
25
+
26
+ # delegate :put, :get, :confirm,
27
+ # :to => :connection
28
+
29
+ attr_reader :name,
30
+ :interval
31
+
32
+ private
33
+
34
+ attr_reader :connection
35
+
36
+ def self.adapters
37
+ @@adapters ||= {}
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,26 @@
1
+ require 'daemons'
2
+
3
+ def requeus_main cmd
4
+ pwd = `pwd`.strip
5
+
6
+ opts = {
7
+ :dir_mode => :normal,
8
+ :dir => File.join(pwd, 'tmp/pids'),
9
+ :log_output => true,
10
+ :ARGV => [cmd]
11
+ }
12
+
13
+ Daemons.run_proc('requeus', opts) do
14
+ Requeus.config_path = File.join(pwd, 'config/requeus.yml')
15
+ Requeus.start_workers
16
+ end
17
+ end
18
+
19
+ namespace :requeus do
20
+ %w(start stop run).each do |cmd|
21
+ desc cmd
22
+ task cmd do
23
+ requeus_main cmd
24
+ end
25
+ end
26
+ end
data/requeus.gemspec ADDED
@@ -0,0 +1,76 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{requeus}
8
+ s.version = "0.0.2"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Ilia Ablamonov", "Anatoliy Plastinin", "Cloud Castle Inc."]
12
+ s.date = %q{2011-05-04}
13
+ s.description = %q{requeus gem is a library for proxying requests}
14
+ s.email = %q{antlypls@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ "LICENSE.txt",
21
+ "README.rdoc",
22
+ "lib/requeus.rb",
23
+ "lib/requeus/adapter/filesystem.rb",
24
+ "lib/requeus/adapter/rabbit.rb",
25
+ "lib/requeus/adapter/s3.rb",
26
+ "lib/requeus/adapter/sqs.rb",
27
+ "lib/requeus/adapters.rb",
28
+ "lib/requeus/blob_store.rb",
29
+ "lib/requeus/impl.rb",
30
+ "lib/requeus/queue.rb",
31
+ "lib/requeus/railtie.rb",
32
+ "lib/requeus/request.rb",
33
+ "lib/requeus/server.rb",
34
+ "lib/tasks/requeus.rake",
35
+ "requeus.gemspec"
36
+ ]
37
+ s.homepage = %q{http://github.com/antlypls/requeus}
38
+ s.licenses = ["MIT"]
39
+ s.require_paths = ["lib"]
40
+ s.rubygems_version = %q{1.4.2}
41
+ s.summary = %q{requeus}
42
+
43
+ if s.respond_to? :specification_version then
44
+ s.specification_version = 3
45
+
46
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
47
+ s.add_runtime_dependency(%q<carrot>, ["~> 0.8.1"])
48
+ s.add_runtime_dependency(%q<aws>, ["~> 2.3.34"])
49
+ s.add_runtime_dependency(%q<daemons>, ["~> 1.0.10"])
50
+ s.add_runtime_dependency(%q<multipart-post>, ["~> 1.1.0"])
51
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
52
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
53
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
54
+ s.add_development_dependency(%q<rcov>, [">= 0"])
55
+ else
56
+ s.add_dependency(%q<carrot>, ["~> 0.8.1"])
57
+ s.add_dependency(%q<aws>, ["~> 2.3.34"])
58
+ s.add_dependency(%q<daemons>, ["~> 1.0.10"])
59
+ s.add_dependency(%q<multipart-post>, ["~> 1.1.0"])
60
+ s.add_dependency(%q<shoulda>, [">= 0"])
61
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
62
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
63
+ s.add_dependency(%q<rcov>, [">= 0"])
64
+ end
65
+ else
66
+ s.add_dependency(%q<carrot>, ["~> 0.8.1"])
67
+ s.add_dependency(%q<aws>, ["~> 2.3.34"])
68
+ s.add_dependency(%q<daemons>, ["~> 1.0.10"])
69
+ s.add_dependency(%q<multipart-post>, ["~> 1.1.0"])
70
+ s.add_dependency(%q<shoulda>, [">= 0"])
71
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
72
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
73
+ s.add_dependency(%q<rcov>, [">= 0"])
74
+ end
75
+ end
76
+
metadata ADDED
@@ -0,0 +1,208 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: requeus
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - Ilia Ablamonov
14
+ - Anatoliy Plastinin
15
+ - Cloud Castle Inc.
16
+ autorequire:
17
+ bindir: bin
18
+ cert_chain: []
19
+
20
+ date: 2011-05-04 00:00:00 +04:00
21
+ default_executable:
22
+ dependencies:
23
+ - !ruby/object:Gem::Dependency
24
+ type: :runtime
25
+ version_requirements: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ hash: 61
31
+ segments:
32
+ - 0
33
+ - 8
34
+ - 1
35
+ version: 0.8.1
36
+ requirement: *id001
37
+ prerelease: false
38
+ name: carrot
39
+ - !ruby/object:Gem::Dependency
40
+ type: :runtime
41
+ version_requirements: &id002 !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ hash: 71
47
+ segments:
48
+ - 2
49
+ - 3
50
+ - 34
51
+ version: 2.3.34
52
+ requirement: *id002
53
+ prerelease: false
54
+ name: aws
55
+ - !ruby/object:Gem::Dependency
56
+ type: :runtime
57
+ version_requirements: &id003 !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ~>
61
+ - !ruby/object:Gem::Version
62
+ hash: 3
63
+ segments:
64
+ - 1
65
+ - 0
66
+ - 10
67
+ version: 1.0.10
68
+ requirement: *id003
69
+ prerelease: false
70
+ name: daemons
71
+ - !ruby/object:Gem::Dependency
72
+ type: :runtime
73
+ version_requirements: &id004 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ~>
77
+ - !ruby/object:Gem::Version
78
+ hash: 19
79
+ segments:
80
+ - 1
81
+ - 1
82
+ - 0
83
+ version: 1.1.0
84
+ requirement: *id004
85
+ prerelease: false
86
+ name: multipart-post
87
+ - !ruby/object:Gem::Dependency
88
+ type: :development
89
+ version_requirements: &id005 !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ hash: 3
95
+ segments:
96
+ - 0
97
+ version: "0"
98
+ requirement: *id005
99
+ prerelease: false
100
+ name: shoulda
101
+ - !ruby/object:Gem::Dependency
102
+ type: :development
103
+ version_requirements: &id006 !ruby/object:Gem::Requirement
104
+ none: false
105
+ requirements:
106
+ - - ~>
107
+ - !ruby/object:Gem::Version
108
+ hash: 23
109
+ segments:
110
+ - 1
111
+ - 0
112
+ - 0
113
+ version: 1.0.0
114
+ requirement: *id006
115
+ prerelease: false
116
+ name: bundler
117
+ - !ruby/object:Gem::Dependency
118
+ type: :development
119
+ version_requirements: &id007 !ruby/object:Gem::Requirement
120
+ none: false
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ hash: 7
125
+ segments:
126
+ - 1
127
+ - 5
128
+ - 2
129
+ version: 1.5.2
130
+ requirement: *id007
131
+ prerelease: false
132
+ name: jeweler
133
+ - !ruby/object:Gem::Dependency
134
+ type: :development
135
+ version_requirements: &id008 !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ hash: 3
141
+ segments:
142
+ - 0
143
+ version: "0"
144
+ requirement: *id008
145
+ prerelease: false
146
+ name: rcov
147
+ description: requeus gem is a library for proxying requests
148
+ email: antlypls@gmail.com
149
+ executables: []
150
+
151
+ extensions: []
152
+
153
+ extra_rdoc_files:
154
+ - LICENSE.txt
155
+ - README.rdoc
156
+ files:
157
+ - LICENSE.txt
158
+ - README.rdoc
159
+ - lib/requeus.rb
160
+ - lib/requeus/adapter/filesystem.rb
161
+ - lib/requeus/adapter/rabbit.rb
162
+ - lib/requeus/adapter/s3.rb
163
+ - lib/requeus/adapter/sqs.rb
164
+ - lib/requeus/adapters.rb
165
+ - lib/requeus/blob_store.rb
166
+ - lib/requeus/impl.rb
167
+ - lib/requeus/queue.rb
168
+ - lib/requeus/railtie.rb
169
+ - lib/requeus/request.rb
170
+ - lib/requeus/server.rb
171
+ - lib/tasks/requeus.rake
172
+ - requeus.gemspec
173
+ has_rdoc: true
174
+ homepage: http://github.com/antlypls/requeus
175
+ licenses:
176
+ - MIT
177
+ post_install_message:
178
+ rdoc_options: []
179
+
180
+ require_paths:
181
+ - lib
182
+ required_ruby_version: !ruby/object:Gem::Requirement
183
+ none: false
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ hash: 3
188
+ segments:
189
+ - 0
190
+ version: "0"
191
+ required_rubygems_version: !ruby/object:Gem::Requirement
192
+ none: false
193
+ requirements:
194
+ - - ">="
195
+ - !ruby/object:Gem::Version
196
+ hash: 3
197
+ segments:
198
+ - 0
199
+ version: "0"
200
+ requirements: []
201
+
202
+ rubyforge_project:
203
+ rubygems_version: 1.4.2
204
+ signing_key:
205
+ specification_version: 3
206
+ summary: requeus
207
+ test_files: []
208
+