delayed_job_sqs 0.1.0

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 ADDED
@@ -0,0 +1,11 @@
1
+ *.swp
2
+ *.tmproj
3
+ .DS_Store
4
+ *.esproj/
5
+ .idea/
6
+ /coverage
7
+ /rdoc
8
+ /pkg
9
+ .rvmrc
10
+ .bundle/config
11
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ #gem 'aws-sdk', '>= 1.12.0'
6
+ #gem 'delayed_job', '>= 3.0.0'
7
+
8
+ #group :development do
9
+ # gem 'rspec', '>= 2.0'
10
+ #end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2013 LeanDog, Inc. and other contributors
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.md ADDED
@@ -0,0 +1,86 @@
1
+ This is an [Amazon SQS](http://aws.amazon.com/sqs/) backend for [delayed_job](http://github.com/collectiveidea/delayed_job)
2
+
3
+ # Getting Started
4
+
5
+ ## Get credentials
6
+
7
+ To start using delayed_job_sqs, you need to sign up for an AWS account and setup your credentials.
8
+
9
+ 1. Go to https://portal.aws.amazon.com/gp/aws/developer/registration/index.html and sign up.
10
+ 2. Get your AWS Access Key Id & Secret Access Key for your account.
11
+ 3. Either `require 'aws-sdk'` and call `AWS.config()` prior to `require 'delayed_job_sqs'`, or create an aws.yml that will get loaded with your app. You will need to configure Delayed::Worker below to pass in the YAML file location:
12
+
13
+ ```yaml
14
+ [aws]
15
+ access_key_id: <your access key>
16
+ secret_access_key: <your secret key>
17
+ ```
18
+
19
+ Or if using Rails, create config/initializers/aws-sdk.rb and put the following into the file:
20
+
21
+ ```ruby
22
+ AWS.config({
23
+ access_key_id: '<your access key>',
24
+ secret_access_key: '<your secret key>',
25
+ })
26
+ ```
27
+
28
+ ## Installation
29
+
30
+ Add the gems to your `Gemfile:`
31
+
32
+ ```ruby
33
+ gem 'delayed_job'
34
+ gem 'delayed_job_sqs'
35
+ ```
36
+
37
+ Optionally: Add an initializer (`config/initializers/delayed_job.rb`):
38
+
39
+ ```ruby
40
+ Delayed::Worker.configure do |config|
41
+ # optional params:
42
+ config.aws_config = '~/stuff/things/aws.yml' # Specify the file location of the AWS configuration YAML if you're not using Rails and you want to use a YAML file instead of calling AWS.config
43
+ config.default_queue_name = 'default' # Specify an alternative default queue name
44
+ config.delay_seconds = # Sets the default delay in seconds for messages sent to the queue.
45
+ config.message_retention_period = 345600 # The number of seconds Amazon SQS retains a message. Must be an integer from 3600 (1 hour) to 1209600 (14 days). The default for this attribute is 345600 (4 days).
46
+ config.visibility_timeout = 30 # The length of time (in seconds) that a message received from a queue will be invisible to other receiving components when they ask to receive messages. Valid values: integers from 0 to 43200 (12 hours).
47
+ config.wait_time_seconds = # How many seconds to wait for a response
48
+ end
49
+ ```
50
+
51
+ ## Usage
52
+
53
+ That's it. Use [delayed_job as normal](http://github.com/collectiveidea/delayed_job).
54
+
55
+ Example:
56
+
57
+ ```ruby
58
+ class User
59
+ def background_stuff
60
+ puts "I run in the background"
61
+ end
62
+ end
63
+ ```
64
+
65
+ Then in one of your controllers:
66
+
67
+ ```ruby
68
+ user = User.new
69
+ user.delay.background_stuff
70
+ ```
71
+
72
+ ## Start worker process
73
+
74
+ rake jobs:work
75
+
76
+ If you want to process a specific queue that's not in your initializer or called `default`, use the `QUEUE` or `QUEUES` environment variable:
77
+
78
+ QUEUE=tracking rake jobs:work
79
+
80
+ That will start pulling jobs off the default queue and processing them. The gem will also handle multiple named queues if you have configured `rake` or `scripts/delayed_job` accordingly however be sure to name the queue when putting objects on the queue:
81
+
82
+ ```ruby
83
+ user = User.new
84
+ user.delay(queue: 'bestest_queue').background_stuff
85
+ ```
86
+
data/Rakefile ADDED
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+
6
+ begin
7
+ Bundler.setup(:default, :development)
8
+ rescue Bundler::BundlerError => e
9
+ $stderr.puts e.message
10
+ $stderr.puts "Run `bundle install` to install missing gems"
11
+ exit e.status_code
12
+ end
13
+
14
+ require 'rake'
15
+
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'delayed/backend/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.require_paths = ["lib"]
8
+ s.name = "delayed_job_sqs"
9
+ s.version = Delayed::Backend::Sqs.version
10
+ s.authors = ["Eric Hankinson"]
11
+ s.email = ["eric.hankinson@gmail.com"]
12
+ s.description = "Amazon SQS backend for delayed_job"
13
+ s.summary = "Amazon SQS backend for delayed_job"
14
+ s.homepage = "https://github.com/kumichou/delayed_job_sqs"
15
+ s.license = "MIT"
16
+
17
+ s.files = `git ls-files`.split($/)
18
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
19
+
20
+ s.add_dependency("aws-sdk", "1.11.1")
21
+ s.add_dependency("delayed_job", ">= 3.0.0")
22
+
23
+ s.add_development_dependency "rspec"
24
+ end
25
+
@@ -0,0 +1,70 @@
1
+ module Delayed
2
+ module Backend
3
+ module Sqs
4
+ module Actions
5
+ def field(name, options = {})
6
+ default = options[:default] || nil
7
+ define_method name do
8
+ @attributes ||= {}
9
+ @attributes[name.to_sym] || default
10
+ end
11
+
12
+ define_method "#{name}=" do |value|
13
+ @attributes ||= {}
14
+ @attributes[name.to_sym] = value
15
+ end
16
+ end
17
+
18
+ def before_fork
19
+ end
20
+
21
+ def after_fork
22
+ end
23
+
24
+ def db_time_now
25
+ Time.now.utc
26
+ end
27
+
28
+ def find_available(worker_name, limit = 5, max_run_time = Worker.max_run_time)
29
+ Delayed::Worker.queues.each_with_index do |queue, index|
30
+ message = sqs.queues.named(queue_name(index)).receive_message
31
+ return [Delayed::Backend::Sqs::Job.new(message)] if message
32
+ end
33
+ []
34
+ end
35
+
36
+ def delete_all
37
+ deleted = 0
38
+
39
+ Delayed::Worker.queues.each_with_index do |queue, index|
40
+ loop do
41
+ msgs = sqs.queues.named(queue_name(index)).receive_message({ :limit => 10})
42
+ break if msgs.blank?
43
+ msgs.each do |msg|
44
+ msg.delete
45
+ deleted += 1
46
+ end
47
+ end
48
+ end
49
+
50
+ puts "Messages removed: #{deleted}"
51
+ end
52
+
53
+ # No need to check locks
54
+ def clear_locks!(*args)
55
+ true
56
+ end
57
+
58
+ private
59
+
60
+ def sqs
61
+ ::Delayed::Worker.sqs
62
+ end
63
+
64
+ def queue_name(index)
65
+ Delayed::Worker.queues[index]
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,120 @@
1
+
2
+ module Delayed
3
+ module Backend
4
+ module Sqs
5
+ class Job
6
+ include ::DelayedJobSqs::Document
7
+ include Delayed::Backend::Base
8
+ extend Delayed::Backend::Sqs::Actions
9
+
10
+ field :priority, :type => Integer, :default => 0
11
+ field :attempts, :type => Integer, :default => 0
12
+ field :handler, :type => String
13
+ field :run_at, :type => Time
14
+ field :locked_at, :type => Time
15
+ field :locked_by, :type => String
16
+ field :failed_at, :type => Time
17
+ field :last_error, :type => String
18
+ field :queue, :type => String
19
+
20
+ def initialize(data = {})
21
+ puts "[init] Delayed::Backend::Sqs"
22
+ @msg = nil
23
+
24
+ if data.is_a?(AWS::SQS::ReceivedMessage)
25
+ @msg = data
26
+ data = JSON.load(data.body)
27
+ end
28
+
29
+ data.symbolize_keys!
30
+ payload_obj = data.delete(:payload_object) || data.delete(:handler)
31
+
32
+ @queue_name = data[:queue] || Delayed::Worker.default_queue_name
33
+ @delay = data[:delay] || Delayed::Worker.delay
34
+ @timeout = data[:timeout] || Delayed::Worker.timeout
35
+ @expires_in = data[:expires_in] || Delayed::Worker.expires_in
36
+ @attributes = data
37
+ self.payload_object = payload_obj
38
+ end
39
+
40
+ def payload_object
41
+ @payload_object ||= YAML.load(self.handler)
42
+ rescue TypeError, LoadError, NameError, ArgumentError => e
43
+ raise DeserializationError,
44
+ "Job failed to load: #{e.message}. Handler: #{handler.inspect}"
45
+ end
46
+
47
+ def payload_object=(object)
48
+ if object.is_a? String
49
+ @payload_object = YAML.load(object)
50
+ self.handler = object
51
+ else
52
+ @payload_object = object
53
+ self.handler = object.to_yaml
54
+ end
55
+ end
56
+
57
+ def save
58
+ puts "[SAVE] #{@attributes.inspect}"
59
+
60
+ if @attributes[:handler].blank?
61
+ raise "Handler missing!"
62
+ end
63
+ payload = JSON.dump(@attributes)
64
+
65
+ @msg.delete if @msg
66
+
67
+ sqs.queues.named(queue_name).send_message(payload, :delay_seconds => @delay)
68
+ true
69
+ end
70
+
71
+ def save!
72
+ save
73
+ end
74
+
75
+ def destroy
76
+ if @msg
77
+ puts "job destroyed! #{@msg.id}"
78
+ @msg.delete
79
+ end
80
+ end
81
+
82
+ def fail!
83
+ destroy
84
+ # v2: move to separate queue
85
+ end
86
+
87
+ def update_attributes(attributes)
88
+ attributes.symbolize_keys!
89
+ @attributes.merge attributes
90
+ save
91
+ end
92
+
93
+ # No need to check locks
94
+ def lock_exclusively!(*args)
95
+ true
96
+ end
97
+
98
+ # No need to check locks
99
+ def unlock(*args)
100
+ true
101
+ end
102
+
103
+ def reload(*args)
104
+ # reset
105
+ super
106
+ end
107
+
108
+ private
109
+
110
+ def queue_name
111
+ @queue_name
112
+ end
113
+
114
+ def sqs
115
+ ::Delayed::Worker.sqs
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,3 @@
1
+ class SqsConfig
2
+ attr_accessor :project_id, :default_queue_name, :delay_seconds, :visibility_timeout, :message_retention_period, :aws_config
3
+ end
@@ -0,0 +1,11 @@
1
+ module Delayed
2
+ module Backend
3
+ module Sqs
4
+ @@version = nil
5
+
6
+ def self.version
7
+ @@version ||= "0.1.0"
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,62 @@
1
+ require_relative 'sqs_config'
2
+
3
+ module Delayed
4
+ class Worker
5
+
6
+ class << self
7
+ attr_accessor :config, :sqs, :delay, :timeout, :expires_in, :aws_config
8
+
9
+ def configure
10
+ yield(config)
11
+
12
+ self.default_queue_name = if !config.default_queue_name.nil? && config.default_queue_name.length != 0
13
+ config.default_queue_name
14
+ else
15
+ 'default'
16
+ end
17
+ self.delay = config.delay_seconds || 0
18
+ self.timeout = config.visibility_timeout || 5.minutes
19
+ self.expires_in = config.message_retention_period || 4.days
20
+ end
21
+
22
+ def config
23
+ @config ||= SqsConfig.new
24
+ end
25
+ end
26
+ end
27
+
28
+ module Backend
29
+ module Sqs
30
+ if Object.const_defined?(:Rails) and Rails.const_defined?(:Railtie)
31
+ class Railtie < Rails::Railtie
32
+
33
+ # configure our gem after Rails completely boots so that we have
34
+ # access to any config/initializers that were run
35
+ config.after_initialize do
36
+ AWS::Rails.setup
37
+
38
+ Delayed::Worker.sqs = AWS::SQS.new
39
+ Delayed::Worker.configure {}
40
+ end
41
+ end
42
+ else
43
+ path = Pathname.new(Delayed::Worker.config.aws_config)
44
+
45
+ if File.exists?(path)
46
+ cfg = YAML::load(File.read(path))
47
+
48
+ unless cfg.keys[0]
49
+ raise "AWS Yaml configuration file is missing a section"
50
+ end
51
+
52
+ AWS.config(cfg.keys[0])
53
+ end
54
+
55
+ Delayed::Worker.sqs = AWS::SQS.new
56
+ Delayed::Worker.configure {}
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+
3
+ module DelayedJobSqs
4
+ module Document
5
+ end
6
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: utf-8
2
+ require 'aws-sdk'
3
+ require 'delayed_job'
4
+ require 'active_support'
5
+
6
+ module ActiveSupport
7
+ Inflector.inflections do |inflect|
8
+ inflect.irregular('sqs', 'sqs')
9
+ end
10
+ end
11
+
12
+ require_relative 'delayed/serialization/sqs'
13
+ require_relative 'delayed/backend/actions'
14
+ require_relative 'delayed/backend/sqs_config'
15
+ require_relative 'delayed/backend/worker'
16
+ require_relative 'delayed/backend/version'
17
+ require_relative 'delayed/backend/sqs'
18
+
19
+ Delayed::Worker.backend = :sqs
20
+
data/spec/.gitkeep ADDED
File without changes
metadata ADDED
@@ -0,0 +1,109 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: delayed_job_sqs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Eric Hankinson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-07-22 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: aws-sdk
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - '='
20
+ - !ruby/object:Gem::Version
21
+ version: 1.11.1
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: 1.11.1
30
+ - !ruby/object:Gem::Dependency
31
+ name: delayed_job
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 3.0.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: 3.0.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
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: '0'
62
+ description: Amazon SQS backend for delayed_job
63
+ email:
64
+ - eric.hankinson@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - .gitignore
70
+ - Gemfile
71
+ - LICENSE
72
+ - README.md
73
+ - Rakefile
74
+ - delayed_job_sqs.gemspec
75
+ - lib/delayed/backend/actions.rb
76
+ - lib/delayed/backend/sqs.rb
77
+ - lib/delayed/backend/sqs_config.rb
78
+ - lib/delayed/backend/version.rb
79
+ - lib/delayed/backend/worker.rb
80
+ - lib/delayed/serialization/sqs.rb
81
+ - lib/delayed_job_sqs.rb
82
+ - spec/.gitkeep
83
+ homepage: https://github.com/kumichou/delayed_job_sqs
84
+ licenses:
85
+ - MIT
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ! '>='
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 1.8.25
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Amazon SQS backend for delayed_job
108
+ test_files:
109
+ - spec/.gitkeep