queued 0.0.1
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 +5 -0
- data/.rspec +1 -0
- data/.rvmrc +1 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +54 -0
- data/Rakefile +13 -0
- data/lib/queued/active_record_integration.rb +26 -0
- data/lib/queued/queueing_proxy.rb +29 -0
- data/lib/queued/railtie.rb +11 -0
- data/lib/queued/version.rb +3 -0
- data/lib/queued.rb +7 -0
- data/queued.gemspec +26 -0
- data/spec/active_record_integration_spec.rb +38 -0
- data/spec/queueing_proxy_spec.rb +49 -0
- data/spec/spec_helper.rb +38 -0
- metadata +145 -0
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour --format documentation --backtrace
|
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm ree@queued
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2011 Rob Ares
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person ob-
|
4
|
+
taining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without restric-
|
6
|
+
tion, including without limitation the rights to use, copy, modi-
|
7
|
+
fy, merge, publish, distribute, sublicense, and/or sell copies of
|
8
|
+
the Software, and to permit persons to whom the Software is fur-
|
9
|
+
nished to do so, subject to 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
|
16
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONIN-
|
17
|
+
FRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
19
|
+
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
Queued
|
2
|
+
============
|
3
|
+
|
4
|
+
Provides a high-level abstraction of [Resque](https://github.com/defunkt/resque) jobs
|
5
|
+
that map cleanly to [ActiveRecord (Rails)](https://github.com/rails/rails) instances.
|
6
|
+
|
7
|
+
Normally, Resque jobs are seperate classes that model job specific functionality. This
|
8
|
+
requires seperate tests, etc. Queued's approach is to just treat any instance method as
|
9
|
+
a something that can be invoked as a job by Resque.
|
10
|
+
|
11
|
+
What It Does
|
12
|
+
--------------
|
13
|
+
|
14
|
+
Queued patches a smart proxy into your AR instances that allow you to acces the functionality
|
15
|
+
by calling `.queued` or `.qd`. From there any instance method may be called and invoked
|
16
|
+
asynchronously.
|
17
|
+
|
18
|
+
Caveats
|
19
|
+
--------------
|
20
|
+
* A record must be saved and reachable by an `id` accessor.
|
21
|
+
* Assumes a Rails application with Resque setup.
|
22
|
+
* does not handle Singleton methods (yet).
|
23
|
+
* defaults the queue name to the instance class name. the `queued` method accepts an override.
|
24
|
+
* Be sensible when calling methods and passing large objects to them. These arguments must be marshalled as json to be enqueued by resque. It is a best practice (in Resque as well) to pass simple parameters.
|
25
|
+
|
26
|
+
Install
|
27
|
+
--------------
|
28
|
+
|
29
|
+
`gem "queued", "0.0.1"`
|
30
|
+
|
31
|
+
Usage
|
32
|
+
--------------
|
33
|
+
|
34
|
+
Basic Example:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
record = Thing.find(42)
|
38
|
+
record.queued.do_long_running_operation(:times => 50)
|
39
|
+
```
|
40
|
+
|
41
|
+
To Target a Specific Resque Queue:
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
record = Thing.find(42)
|
45
|
+
record.queued(:archive).truncate!
|
46
|
+
```
|
47
|
+
|
48
|
+
Additionally, the `.queued` method is aliased to `.qd` for brevity.
|
49
|
+
|
50
|
+
Contributing
|
51
|
+
--------------
|
52
|
+
Fork it. Patches or pull requests are welcome.
|
53
|
+
|
54
|
+
[License](https://github.com/rares/queued/blob/master/LICENSE)
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Queued
|
2
|
+
|
3
|
+
module ActiveRecordIntegration
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
alias :qd :queued
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
|
12
|
+
def perform(id, method, *args)
|
13
|
+
find(id).__send__(method, *args)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module InstanceMethods
|
18
|
+
|
19
|
+
def queued(queue_name = nil)
|
20
|
+
::Queued::QueueingProxy.new(self, queue_name)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "resque"
|
2
|
+
|
3
|
+
module Queued
|
4
|
+
|
5
|
+
class QueueingProxy
|
6
|
+
attr_reader :queue_name, :target
|
7
|
+
|
8
|
+
def initialize(target, queue_name = nil)
|
9
|
+
@target = target
|
10
|
+
@queue_name = (queue_name || @target.class.name.tableize).to_sym
|
11
|
+
end
|
12
|
+
|
13
|
+
def method_missing(method, *args)
|
14
|
+
unless target.respond_to?(method)
|
15
|
+
raise NoMethodError.new "Can't be invoked", method, *args
|
16
|
+
end
|
17
|
+
|
18
|
+
Resque::Job.create(queue_name,
|
19
|
+
target.class,
|
20
|
+
target.id,
|
21
|
+
method.to_sym,
|
22
|
+
*args)
|
23
|
+
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/lib/queued.rb
ADDED
data/queued.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "queued/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "queued"
|
7
|
+
s.version = Queued::VERSION
|
8
|
+
s.authors = ["Rob Ares"]
|
9
|
+
s.email = ["rob.ares@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/rares/queued"
|
11
|
+
s.summary = %q{Call any ActiveRecord instance method as though it was a Resque job}
|
12
|
+
s.description = %q{}
|
13
|
+
|
14
|
+
s.rubyforge_project = "queued"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {spec}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_runtime_dependency("activerecord", ["~> 3.0"])
|
22
|
+
s.add_runtime_dependency("resque", ["<= 1.17.1"])
|
23
|
+
|
24
|
+
s.add_development_dependency("rspec-rails", ["= 2.6.1"])
|
25
|
+
s.add_development_dependency("sqlite3-ruby", ["= 1.2.5"])
|
26
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/spec_helper"
|
2
|
+
|
3
|
+
describe Queued::ActiveRecordIntegration do
|
4
|
+
subject { thing }
|
5
|
+
|
6
|
+
its(:queued) { should be_instance_of(Queued::QueueingProxy) }
|
7
|
+
its(:queued) { should be_respond_to(:present?) }
|
8
|
+
its(:qd) { should_not be_nil }
|
9
|
+
|
10
|
+
context "perform" do
|
11
|
+
|
12
|
+
it "looks up the record" do
|
13
|
+
lambda { Thing.perform(subject.id, :id) }.should_not
|
14
|
+
raise_error(ActiveRecord::RecordNotFound)
|
15
|
+
end
|
16
|
+
|
17
|
+
it "fails if the record does not exists" do
|
18
|
+
lambda { Thing.perform(0, :id) }.should
|
19
|
+
raise_error(ActiveRecord::RecordNotFound)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "executes the passed method" do
|
23
|
+
Thing.perform(subject.id, :id).should eql(subject.id)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "executes the passed method with arguments" do
|
27
|
+
Thing.perform(subject.id, :update_attribute, :name, "Derp").should eql(true)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "fails when the method does not exist" do
|
31
|
+
lambda { Thing.perform(subject.id, :derp_it!) }.should
|
32
|
+
raise_error(NoMethodError)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/spec_helper"
|
2
|
+
|
3
|
+
describe Queued::QueueingProxy do
|
4
|
+
subject { thing }
|
5
|
+
|
6
|
+
it "returns a wrapped instance" do
|
7
|
+
described_class.new(subject).should_not be_nil
|
8
|
+
end
|
9
|
+
|
10
|
+
it "makes the target object accessable" do
|
11
|
+
described_class.new(subject).target.should eql(subject)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "makes the queue name accessable" do
|
15
|
+
described_class.new(subject, :fast).queue_name.should eql(:fast)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "default the queue name to that of the table" do
|
19
|
+
described_class.new(subject).queue_name.should eql(:things)
|
20
|
+
end
|
21
|
+
|
22
|
+
context "method_missing" do
|
23
|
+
|
24
|
+
it "raises when the queued method does not exist" do
|
25
|
+
lambda { described_class.new(subject).herp_it! }.should
|
26
|
+
raise_error(NoMethodError)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "returns nil" do
|
30
|
+
Resque::Job.should_receive(:create).once
|
31
|
+
|
32
|
+
described_class.new(subject).save.should eql(nil)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "enqueues a job containing the passed method" do
|
36
|
+
proxy = described_class.new(subject)
|
37
|
+
|
38
|
+
Resque::Job.should_receive(:create).with(proxy.queue_name,
|
39
|
+
subject.class,
|
40
|
+
subject.id,
|
41
|
+
:save,
|
42
|
+
false).once
|
43
|
+
|
44
|
+
proxy.save(false)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__)))
|
2
|
+
$LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
|
3
|
+
|
4
|
+
require "active_record/railtie"
|
5
|
+
|
6
|
+
require "queued"
|
7
|
+
|
8
|
+
# railties don't fire unless controllers are around, lame
|
9
|
+
ActiveRecord::Base.__send__ :include, ::Queued::ActiveRecordIntegration
|
10
|
+
|
11
|
+
ActiveRecord::Base.establish_connection(
|
12
|
+
:adapter => "sqlite3",
|
13
|
+
:database => ":memory:")
|
14
|
+
ActiveRecord::Migration.verbose = false
|
15
|
+
|
16
|
+
ActiveRecord::Schema.define do
|
17
|
+
create_table :things, :force => true do |t|
|
18
|
+
t.string :name
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Thing < ActiveRecord::Base; end
|
23
|
+
|
24
|
+
require "rspec/rails"
|
25
|
+
|
26
|
+
module Helpers
|
27
|
+
|
28
|
+
def thing
|
29
|
+
Thing.create(:name => "Herglebergle Snartbirk")
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
RSpec.configure do |config|
|
35
|
+
config.mock_with :rspec
|
36
|
+
config.fail_fast = true
|
37
|
+
config.include Helpers
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,145 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: queued
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Rob Ares
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-07-07 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: activerecord
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 7
|
30
|
+
segments:
|
31
|
+
- 3
|
32
|
+
- 0
|
33
|
+
version: "3.0"
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: resque
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - <=
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 81
|
45
|
+
segments:
|
46
|
+
- 1
|
47
|
+
- 17
|
48
|
+
- 1
|
49
|
+
version: 1.17.1
|
50
|
+
type: :runtime
|
51
|
+
version_requirements: *id002
|
52
|
+
- !ruby/object:Gem::Dependency
|
53
|
+
name: rspec-rails
|
54
|
+
prerelease: false
|
55
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - "="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 21
|
61
|
+
segments:
|
62
|
+
- 2
|
63
|
+
- 6
|
64
|
+
- 1
|
65
|
+
version: 2.6.1
|
66
|
+
type: :development
|
67
|
+
version_requirements: *id003
|
68
|
+
- !ruby/object:Gem::Dependency
|
69
|
+
name: sqlite3-ruby
|
70
|
+
prerelease: false
|
71
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - "="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
hash: 21
|
77
|
+
segments:
|
78
|
+
- 1
|
79
|
+
- 2
|
80
|
+
- 5
|
81
|
+
version: 1.2.5
|
82
|
+
type: :development
|
83
|
+
version_requirements: *id004
|
84
|
+
description: ""
|
85
|
+
email:
|
86
|
+
- rob.ares@gmail.com
|
87
|
+
executables: []
|
88
|
+
|
89
|
+
extensions: []
|
90
|
+
|
91
|
+
extra_rdoc_files: []
|
92
|
+
|
93
|
+
files:
|
94
|
+
- .gitignore
|
95
|
+
- .rspec
|
96
|
+
- .rvmrc
|
97
|
+
- Gemfile
|
98
|
+
- LICENSE
|
99
|
+
- README.md
|
100
|
+
- Rakefile
|
101
|
+
- lib/queued.rb
|
102
|
+
- lib/queued/active_record_integration.rb
|
103
|
+
- lib/queued/queueing_proxy.rb
|
104
|
+
- lib/queued/railtie.rb
|
105
|
+
- lib/queued/version.rb
|
106
|
+
- queued.gemspec
|
107
|
+
- spec/active_record_integration_spec.rb
|
108
|
+
- spec/queueing_proxy_spec.rb
|
109
|
+
- spec/spec_helper.rb
|
110
|
+
has_rdoc: true
|
111
|
+
homepage: https://github.com/rares/queued
|
112
|
+
licenses: []
|
113
|
+
|
114
|
+
post_install_message:
|
115
|
+
rdoc_options: []
|
116
|
+
|
117
|
+
require_paths:
|
118
|
+
- lib
|
119
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
+
none: false
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
hash: 3
|
125
|
+
segments:
|
126
|
+
- 0
|
127
|
+
version: "0"
|
128
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
hash: 3
|
134
|
+
segments:
|
135
|
+
- 0
|
136
|
+
version: "0"
|
137
|
+
requirements: []
|
138
|
+
|
139
|
+
rubyforge_project: queued
|
140
|
+
rubygems_version: 1.4.1
|
141
|
+
signing_key:
|
142
|
+
specification_version: 3
|
143
|
+
summary: Call any ActiveRecord instance method as though it was a Resque job
|
144
|
+
test_files: []
|
145
|
+
|