afterparty 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: 1cd702bf393ba9846ebeea3e8195dd7f76914488
4
- data.tar.gz: a7f24532f757b22660d31720ccd0bec948ba7545
5
- !binary "U0hBNTEy":
6
- metadata.gz: 86e634284043827e87dcdc3fce39e5be359a3592077dca1427041faa9f1fd147e9d1ed374b6241643836617b5393da9822fca6d985db39d5c6431fa53d5667b1
7
- data.tar.gz: c49dbbed658e44ab6a7eb1cc55d0528621a6eb17612744e7f733a00cf91770d0c398d360f1628b7c20cf44310f1657f515c41b773d6f61263479470698493ec2
2
+ SHA1:
3
+ metadata.gz: f2a6ac0e585c1d786ce00d1cd91863f5bead9af4
4
+ data.tar.gz: c276f1d73253a5ab5189689ce72cc39e8e1db8fa
5
+ SHA512:
6
+ metadata.gz: 24e8c2dbe66ebee04fab02fdfff9e9430588b1df9d23b71ec1e76e6c6b9002ae80afb5679f3f5ad91252c1a3710758a070b9afaa669866fcc964529c828f4a0a
7
+ data.tar.gz: 1c7cff779dd6172e921ccfd8f7015bc84e6a720709356e3bbc363089112f3116f659c7b670cc43f858b70b719d16d3675872b37c57103c1743c2957b0f40690d
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ *.sqlite3
data/Gemfile CHANGED
@@ -9,4 +9,7 @@ gem 'guard-rspec'
9
9
  gem 'ruby_gntp'
10
10
  gem 'redis'
11
11
  gem 'sqlite3'
12
- gem 'genspec'
12
+ gem 'genspec'
13
+ gem 'fileutils'
14
+ gem 'simplecov'
15
+ gem 'coveralls', require: false
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Afterparty
2
2
 
3
3
  [![Build Status](https://travis-ci.org/hstove/afterparty.png?branch=master)](https://travis-ci.org/hstove/afterparty)
4
+ [![Code Climate](https://codeclimate.com/github/hstove/afterparty.png)](https://codeclimate.com/github/hstove/afterparty)
5
+ [![Coverage Status](https://coveralls.io/repos/hstove/afterparty/badge.png)](https://coveralls.io/r/hstove/afterparty)
4
6
 
5
7
  A Rails 3 & 4 compatible queue with support for executing jobs in the future and persistence with ActiveRecord.
6
8
 
@@ -2,8 +2,4 @@ Afterparty::Engine.routes.draw do
2
2
  get "/" => "afterparty/dashboard#index", as: :dashboard
3
3
  get "/run" => "afterparty/dashboard#run", as: :run_job
4
4
  get "/delete" => "afterparty/dashboard#destroy", as: :destroy_job
5
- end
6
-
7
- Rails.application.routes.draw do
8
- mount Afterparty::Engine, at: "afterparty", as: "afterparty_engine"
9
5
  end
@@ -5,21 +5,6 @@ Dir[File.expand_path('../afterparty/*', __FILE__)].each { |f| require f }
5
5
 
6
6
 
7
7
  module Afterparty
8
- def self.clear namespace=:default
9
- redis_call namespace, :del
10
- end
11
-
12
- def self.redis_call namespace, command, *args
13
- @@redis.send(command, redis_queue_name(namespace), *args)
14
- end
15
-
16
- def self.redis_queue_name namespace=:default
17
- "afterparty_#{namespace}_queue"
18
- end
19
-
20
- def self.queues
21
- # @@redis.smembers "afterparty_queues"
22
- end
23
8
 
24
9
  # return timestamp of :execute_at or current time
25
10
  def self.queue_time job
@@ -30,30 +15,21 @@ module Afterparty
30
15
  def self.job_valid? job
31
16
  job.respond_to?(:execute_at) && !job.execute_at.nil?
32
17
  end
33
-
18
+
34
19
  def self.load(raw)
35
20
  begin
36
- # postgres converts it to utf-8
37
- # raw.encode!("ascii")
38
21
  begin
39
- # job = Marshal.load(raw)
40
- # job = Marshal.load(job) if String === job
41
22
  return YAML.load(raw)
42
23
  rescue ArgumentError => e
43
24
  # lots of yaml load errors are because something that hasn't been
44
25
  # required. recursively require on these errors
45
26
  # Invoke the autoloader and try again if object's class is undefined
46
27
  if e.message =~ /undefined class\/module (.*)$/
47
- # puts "autoloading #{$1}"
48
28
  $1.constantize rescue return nil
49
29
  end
50
30
  return load(raw)
51
31
  end
52
32
  rescue Exception => e
53
- puts e
54
- puts "Exception while unmarshaling a job:"
55
- puts e.message
56
- puts e.backtrace
57
33
  return nil
58
34
  end
59
35
  end
@@ -5,7 +5,7 @@ class AfterpartyJob < ::ActiveRecord::Base
5
5
 
6
6
  validates_presence_of :job_dump, :execute_at, :queue
7
7
 
8
- scope :namespaced, lambda { |name| where(queue: name) }
8
+ scope :namespaced, lambda { |name| where(queue: name) if name }
9
9
  scope :incomplete, -> { where(completed: false).order("execute_at") }
10
10
  scope :valid, -> { incomplete.where(execute_at: 10.years.ago..DateTime.now) }
11
11
  scope :completed, -> { where(completed: true).order("execute_at desc") }
@@ -13,7 +13,6 @@ module Afterparty
13
13
  @job_id = job.afterparty_job_id if @job.respond_to? :afterparty_job_id
14
14
  @queue_name = job.afterparty_queue if @job.respond_to? :afterparty_queue
15
15
  rescue Exception => e
16
- ap "Error during load: #{e.message}"
17
16
  @job = nil
18
17
  end
19
18
  @raw = _raw
@@ -27,10 +26,5 @@ module Afterparty
27
26
  nil
28
27
  end
29
28
  end
30
-
31
- def raw_string
32
- ic = Iconv.new('UTF-8//IGNORE', 'UTF-8')
33
- ic.iconv(@raw.dup + ' ')[0..-2]
34
- end
35
29
  end
36
30
  end
@@ -1,41 +1,37 @@
1
1
  module Afterparty
2
- class MailerJob
3
- attr_accessor :execute_at, :mail, :clazz, :method, :args
4
- def initialize clazz, method, *args
5
- # @mail = UserMailer.welcome_email(User.find(1))
6
- @clazz = UserMailer
2
+
3
+ module JobDescribers
4
+ attr_accessor :object, :method, :args, :execute_at
5
+
6
+ def initialize object, method, *args
7
+ @object = object
7
8
  @method = method
8
9
  @args = args
9
10
  end
10
-
11
- def run
12
- @mail = @clazz.send @method, *@args
13
- @mail.deliver
14
- end
15
11
 
16
12
  def description
17
- desc = "Mailer: #{(@clazz || "nil")}."
18
- desc << "Method: #{(@method || nil)}."
19
- desc << "Args: #{(@args || nil)}"
13
+ desc = "Object: #{(@object || "nil")}."
14
+ desc << "Method: #{(@method || "nil")}."
15
+ desc << "Args: #{(@args || "nil")}"
20
16
  end
17
+ alias_method :inspect, :description
21
18
  end
22
19
 
23
- class BasicJob
24
- attr_accessor :object, :method, :args
25
- def initialize object, method, *args
26
- @object = object
27
- @method = method
28
- @args = args
29
- end
20
+ class MailerJob
21
+ include JobDescribers
30
22
 
31
23
  def run
32
- @object.send(:method, *@args)
24
+ @mail = @object.send @method, *@args
25
+ @mail.deliver
33
26
  end
27
+ end
34
28
 
35
- def description
36
- desc = "Object: #{(@object || "nil")}."
37
- desc << "Method: #{(@method || nil)}."
38
- desc << "Args: #{(@args || nil)}"
29
+ class BasicJob
30
+ include JobDescribers
31
+
32
+ def run
33
+ @object.send(@method, *@args)
39
34
  end
40
35
  end
36
+
41
37
  end
@@ -4,38 +4,20 @@ module Afterparty
4
4
  include Afterparty::QueueHelpers
5
5
 
6
6
  def push job
7
- # @mutex.synchronize do
8
- return nil if job.nil?
9
- queue_name = @temp_namespace || @options[:namespace]
10
- AfterpartyJob.make_with_job job, queue_name
11
- # end
7
+ return nil if job.nil?
8
+ AfterpartyJob.make_with_job job, @options[:namespace]
12
9
  end
13
10
  alias :<< :push
14
11
  alias :eng :push
15
12
 
16
13
  def pop
17
- # @mutex.synchronize do
18
- while true do
19
- unless (_job = AfterpartyJob.valid.first).nil?
20
- _job.save
21
- return _job
22
- end
23
- sleep(@options[:sleep])
14
+ while true do
15
+ unless (_job = next_valid_job).nil?
16
+ _job.save
17
+ return _job
24
18
  end
25
- # end
26
- end
27
- end
28
-
29
- class TestQueue < Queue
30
- attr_accessor :completed_jobs
31
-
32
- def initialize opts={}
33
- super
34
- @completed_jobs = []
35
- @exceptions = []
36
- end
37
- def handle_exception job, exception
38
- @exceptions << [job, exception]
19
+ sleep(@options[:sleep])
20
+ end
39
21
  end
40
22
  end
41
23
  end
@@ -1,5 +1,6 @@
1
1
  module Afterparty
2
2
  module QueueHelpers
3
+ attr_reader :options
3
4
 
4
5
  def initialize options = {}
5
6
  @options = options
@@ -9,12 +10,7 @@ module Afterparty
9
10
  self
10
11
  end
11
12
 
12
- def [] namespace
13
- @temp_namespace = namespace
14
- end
15
-
16
13
  def clear
17
- # redis_call :del
18
14
  AfterpartyJob.namespaced(@options[:namespace]).destroy_all
19
15
  end
20
16
 
@@ -22,10 +18,6 @@ module Afterparty
22
18
  AfterpartyJob.namespaced(@options[:namespace]).incomplete
23
19
  end
24
20
 
25
- def jobs_with_scores
26
- hash_from_scores(redis_call(:zrange, 0, -1, {withscores: true}))
27
- end
28
-
29
21
  def valid_jobs
30
22
  AfterpartyJob.namespaced(@options[:namespace]).valid
31
23
  end
@@ -50,11 +42,6 @@ module Afterparty
50
42
  AfterpartyJob.namespaced(@options[:namespace]).completed
51
43
  end
52
44
 
53
- def completed_with_scores
54
- @temp_namespace = "completed"
55
- hash_from_scores(redis_call(:zrange, -20, -1, withscores: true)).reverse
56
- end
57
-
58
45
  def run(job)
59
46
  real_job = job.reify
60
47
  if real_job
@@ -92,18 +79,5 @@ module Afterparty
92
79
  raise 'Must set queue.config_login to use dashboard' if @login_block.nil?
93
80
  @login_block.call(username, password)
94
81
  end
95
-
96
-
97
- private
98
-
99
- # returns true if job has an :execute_at value
100
- def job_valid? job
101
- job.respond_to?(:execute_at) && !job.execute_at.nil?
102
- end
103
-
104
- # return timestamp of :execute_at or current time
105
- def queue_time job
106
- time = job_valid?(job) ? job.execute_at.to_i : Time.now.to_i
107
- end
108
82
  end
109
83
  end
@@ -1,3 +1,3 @@
1
1
  module Afterparty
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -4,7 +4,6 @@ module Afterparty
4
4
 
5
5
  def consume
6
6
  @stopped = false
7
- # puts "starting worker with namespace [#{@options[:namespace]}]."
8
7
  @thread = Thread.new {
9
8
  consume_sync
10
9
  }
@@ -21,7 +20,7 @@ module Afterparty
21
20
  while !@stopped
22
21
  job = next_valid_job
23
22
  if job
24
- puts "Executing job: #{job.id}"
23
+ puts "Executing job: #{job.id}" if job.respond_to? :id
25
24
  run job
26
25
  else
27
26
  sleep(@options[:sleep])
@@ -5,5 +5,6 @@ class AfterpartyGenerator < Rails::Generators::Base
5
5
  def install
6
6
  copy_file "jobs_migration.rb", "db/migrate/#{Time.now.strftime('%Y%m%d%H%M%S')}_create_afterparty_jobs.rb"
7
7
  copy_file "initializer.rb", "config/initializers/afterparty.rb"
8
+ route "mount Afterparty::Engine, at: \"afterparty\", as: \"afterparty_engine\""
8
9
  end
9
10
  end
@@ -2,5 +2,5 @@ queue = Rails.configuration.queue = Afterparty::Queue.new
2
2
 
3
3
  queue.config_login do |username, password|
4
4
  # change this to something more secure!
5
- user == "admin" && password == "password"
5
+ username == "admin" && password == "password"
6
6
  end
@@ -0,0 +1,34 @@
1
+ require "spec_helper"
2
+
3
+ describe Afterparty do
4
+ describe "#load" do
5
+ it "should constantize any missing Classes while loading" do
6
+ obj = TestJob.new
7
+ dump = YAML.dump(obj)
8
+ YAML.stub(:load) do
9
+ YAML.unstub(:load)
10
+ raise ArgumentError, "undefined class/module TestJob"
11
+ end
12
+ String.any_instance.should_receive(:constantize).once
13
+ Afterparty.load(dump).should_not be_nil
14
+ end
15
+
16
+ it "returns nil when an exception is raised in YAML.load" do
17
+ YAML.stub(:load){ raise Exception }
18
+ Afterparty.load("anything").should be_nil
19
+ end
20
+ end
21
+
22
+ describe "#job_valid?" do
23
+ it "returns false unless job responds to #execute_at" do
24
+ job = {}
25
+ Afterparty.job_valid?(job).should be_false
26
+ end
27
+
28
+ it "returns false if #execute_at returns nil" do
29
+ job = TestJob.new
30
+ job.execute_at = nil
31
+ Afterparty.job_valid?(job).should be_false
32
+ end
33
+ end
34
+ end
@@ -1,10 +1,15 @@
1
1
  require 'spec_helper'
2
2
  describe :afterparty do
3
+ within_source_root do
4
+ FileUtils.mkdir_p "config"
5
+ FileUtils.touch "config/routes.rb"
6
+ end
3
7
  it "works" do
4
8
  subject.should generate(:copy_file, "jobs_migration.rb")
5
9
  subject.should generate("config/initializers/afterparty.rb") do |content|
6
10
  content.should include("Afterparty::Queue.new")
7
11
  content.should include("queue.config_login do |username, password|")
8
12
  end
13
+ subject.should generate(:route, "mount Afterparty::Engine, at: \"afterparty\", as: \"afterparty_engine\"")
9
14
  end
10
15
  end
@@ -0,0 +1,57 @@
1
+ require "spec_helper"
2
+
3
+ describe Afterparty::MailerJob do
4
+ class Mailer
5
+ def self.mail
6
+ self.new
7
+ end
8
+
9
+ def deliver
10
+ true
11
+ end
12
+ end
13
+
14
+ let(:job){ Afterparty::MailerJob.new Mailer, :mail }
15
+
16
+ it "initializes and sets the right attributes" do
17
+ job.args.should eq([])
18
+ job.object.should eq(Mailer)
19
+ job.method.should eq(:mail)
20
+ end
21
+
22
+ describe "description" do
23
+ it "describes correctly" do
24
+ description = "Object: Mailer.Method: mail.Args: []"
25
+ job.description.should eq(description)
26
+ end
27
+ end
28
+
29
+ it "calls #delivers on the mailer in when ran" do
30
+ Mailer.any_instance.should_receive(:deliver).once
31
+ job.run
32
+ end
33
+
34
+ end
35
+
36
+ describe Afterparty::BasicJob do
37
+ class Person
38
+ def say_hello name
39
+ "hello #{name}!"
40
+ end
41
+ end
42
+
43
+ ran = false
44
+ let(:job){ Afterparty::BasicJob.new(Person.new, :say_hello, "hank") }
45
+
46
+ it "initializes and sets the right attributes" do
47
+ job.args.should eq(["hank"])
48
+ job.object.should be_a(Person)
49
+ job.method.should eq(:say_hello)
50
+ end
51
+
52
+ it "sends the given method to @object with @args" do
53
+ Person.any_instance.should_receive(:say_hello).with("hank").once
54
+ job.run
55
+ end
56
+
57
+ end
@@ -0,0 +1,22 @@
1
+ require "spec_helper"
2
+
3
+ describe Afterparty::JobContainer do
4
+ it "initializes correctly" do
5
+ job = TestJob.new
6
+ raw = YAML.dump(job)
7
+ container = Afterparty::JobContainer.new raw, Time.now.to_i
8
+ container.job.should be_a(TestJob)
9
+
10
+ container.job_class.should eq(TestJob)
11
+ end
12
+
13
+ it "sets job to nil if an error is thrown in YAML.load" do
14
+ Afterparty.stub(:load){ raise }
15
+ job = TestJob.new
16
+ raw = YAML.dump(job)
17
+ container = Afterparty::JobContainer.new raw, Time.now.to_i
18
+ container.job.should be_nil
19
+
20
+ container.job_class.should be_nil
21
+ end
22
+ end
@@ -53,4 +53,39 @@ describe Afterparty::QueueHelpers do
53
53
  @q.authenticate("userbad","pass").should == false
54
54
  @q.authenticate("user","passbad").should == false
55
55
  end
56
+
57
+ it "saves errors if a job can't reify" do
58
+ job = AfterpartyJob.make_with_job test_job
59
+ job.stub(:reify) { nil }
60
+ @q.run job
61
+ job.has_error.should be_true
62
+ job.error_message.should eq("Error marshaling job.")
63
+ end
64
+
65
+ it "handles exceptions when running a job" do
66
+ job = AfterpartyJob.make_with_job test_job
67
+ job.stub(:reify).and_raise(Exception, "message")
68
+ @q.should_receive(:handle_exception)
69
+ @q.run job
70
+ end
71
+
72
+ it "saves error data about a job when handling exceptions" do
73
+ job = AfterpartyJob.make_with_job test_job
74
+ job.stub(:reify).and_raise(Exception, "message")
75
+ @q.options[:logger].should_receive(:error)
76
+ @q.run job
77
+ job.completed.should be_true
78
+ job.completed_at.should be < DateTime.now
79
+ job.has_error.should be_true
80
+ job.error_message.should eq("message")
81
+ job.error_backtrace.should_not be_nil
82
+ end
83
+
84
+ it "returns the last completed job" do
85
+ job = AfterpartyJob.make_with_job test_job
86
+ job.completed = true
87
+ job.save
88
+ @q.last_completed.should eq(job)
89
+ @q.completed.should eq([job])
90
+ end
56
91
  end
@@ -46,4 +46,16 @@ describe Afterparty::Queue do
46
46
  (inner = wrapper.reify).name.should == "testy"
47
47
  wrapper.queue.should == "tester"
48
48
  end
49
+
50
+ it "should sleep if no jobs are valid on #pop" do
51
+ sleep_called = false
52
+ job = nil
53
+ @q.clear
54
+ @q.stub(:sleep) {
55
+ sleep_called = true
56
+ job = AfterpartyJob.make_with_job test_job
57
+ }
58
+ @q.pop
59
+ sleep_called.should be_true
60
+ end
49
61
  end
@@ -1,3 +1,14 @@
1
+ require 'simplecov'
2
+ require 'coveralls'
3
+
4
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
5
+ SimpleCov::Formatter::HTMLFormatter,
6
+ Coveralls::SimpleCov::Formatter
7
+ ]
8
+ SimpleCov.start do
9
+ add_filter "/spec/"
10
+ end
11
+
1
12
  require 'rubygems'
2
13
  require 'bundler/setup'
3
14
  require 'awesome_print'
@@ -5,6 +16,7 @@ require 'redis'
5
16
  require 'afterparty' # and any other gems you need
6
17
  require 'helpers'
7
18
  require 'genspec'
19
+ require 'fileutils'
8
20
 
9
21
  RSpec.configure do |config|
10
22
  # some (optional) config here
@@ -22,4 +34,4 @@ def clean_database!
22
34
  ActiveRecord::Base.connection.execute "DELETE FROM afterparty_jobs"
23
35
  end
24
36
 
25
- clean_database!
37
+ clean_database!
@@ -0,0 +1,48 @@
1
+ require "spec_helper"
2
+
3
+ describe Afterparty::Worker do
4
+ let(:worker) { Afterparty::Worker.new({sleep: 0.25}) }
5
+ after do
6
+ worker.stop
7
+ end
8
+
9
+ describe "consume" do
10
+ it "calls a new thread" do
11
+ Thread.should_receive(:new).once
12
+ worker.consume
13
+ end
14
+
15
+ it "calls consume_sync on itself" do
16
+ worker.should_receive(:consume_sync).once
17
+ worker.consume
18
+ sleep 0.25
19
+ end
20
+ end
21
+
22
+ describe "consume_sync" do
23
+ it "runs the next_valid_job" do
24
+ worker.instance_variable_set "@stopped", false
25
+ job = TestJob.new
26
+ worker.stub(:next_valid_job) {
27
+ worker.unstub(:next_valid_job)
28
+ worker.instance_variable_set "@stopped", true
29
+ job
30
+ }
31
+ worker.should_receive(:run).with(job)
32
+ worker.consume_sync
33
+ worker.stop
34
+ end
35
+
36
+ it "sleeps if there are no valid jobs" do
37
+ worker.instance_variable_set "@stopped", false
38
+ worker.stub(:next_valid_job) {
39
+ worker.unstub(:next_valid_job)
40
+ worker.instance_variable_set "@stopped", true
41
+ nil
42
+ }
43
+ worker.should_receive(:sleep).with(0.25)
44
+ worker.consume_sync
45
+ worker.stop
46
+ end
47
+ end
48
+ end
metadata CHANGED
@@ -1,41 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: afterparty
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hank Stoever
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-05-21 00:00:00.000000000 Z
11
+ date: 2013-11-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ! '>='
17
+ - - '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ! '>='
24
+ - - '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: iconv
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ! '>='
31
+ - - '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ! '>='
38
+ - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
@@ -56,14 +56,14 @@ dependencies:
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ! '>='
59
+ - - '>='
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ! '>='
66
+ - - '>='
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  description: Rails 4 compatible queue with support for executing jobs later.
@@ -82,7 +82,6 @@ files:
82
82
  - README.md
83
83
  - Rakefile
84
84
  - afterparty.gemspec
85
- - afterparty_test.sqlite3
86
85
  - app/assets/javascripts/afterparty.js.coffee
87
86
  - app/assets/stylesheets/afterparty.css.sass
88
87
  - app/controllers/afterparty/dashboard_controller.rb
@@ -97,7 +96,6 @@ files:
97
96
  - lib/afterparty/jobs.rb
98
97
  - lib/afterparty/queue.rb
99
98
  - lib/afterparty/queue_helpers.rb
100
- - lib/afterparty/threaded_queue_consumer.rb
101
99
  - lib/afterparty/version.rb
102
100
  - lib/afterparty/worker.rb
103
101
  - lib/generators/afterparty_generator.rb
@@ -105,14 +103,18 @@ files:
105
103
  - lib/generators/templates/jobs_migration.rb
106
104
  - lib/tasks/tasks.rake
107
105
  - spec/afterparty_job_spec.rb
106
+ - spec/afterparty_spec.rb
108
107
  - spec/database.yml
109
108
  - spec/generators/afterparty_generator_spec.rb
109
+ - spec/helper_jobs_spec.rb
110
110
  - spec/helpers.rb
111
+ - spec/job_container_spec.rb
111
112
  - spec/queue_functional_spec.rb
112
113
  - spec/queue_helpers_spec.rb
113
114
  - spec/queue_spec.rb
114
115
  - spec/schema.rb
115
116
  - spec/spec_helper.rb
117
+ - spec/worker_spec.rb
116
118
  homepage: ''
117
119
  licenses:
118
120
  - MIT
@@ -123,28 +125,31 @@ require_paths:
123
125
  - lib
124
126
  required_ruby_version: !ruby/object:Gem::Requirement
125
127
  requirements:
126
- - - ! '>='
128
+ - - '>='
127
129
  - !ruby/object:Gem::Version
128
130
  version: '0'
129
131
  required_rubygems_version: !ruby/object:Gem::Requirement
130
132
  requirements:
131
- - - ! '>='
133
+ - - '>='
132
134
  - !ruby/object:Gem::Version
133
135
  version: '0'
134
136
  requirements: []
135
137
  rubyforge_project:
136
- rubygems_version: 2.0.3
138
+ rubygems_version: 2.0.6
137
139
  signing_key:
138
140
  specification_version: 4
139
141
  summary: Rails 4 compatible queue with support for executing jobs later.
140
142
  test_files:
141
143
  - spec/afterparty_job_spec.rb
144
+ - spec/afterparty_spec.rb
142
145
  - spec/database.yml
143
146
  - spec/generators/afterparty_generator_spec.rb
147
+ - spec/helper_jobs_spec.rb
144
148
  - spec/helpers.rb
149
+ - spec/job_container_spec.rb
145
150
  - spec/queue_functional_spec.rb
146
151
  - spec/queue_helpers_spec.rb
147
152
  - spec/queue_spec.rb
148
153
  - spec/schema.rb
149
154
  - spec/spec_helper.rb
150
- has_rdoc:
155
+ - spec/worker_spec.rb
Binary file
@@ -1,58 +0,0 @@
1
- module Afterparty
2
-
3
- # inspired by the rails 4 implementation:
4
- # https://github.com/rails/rails/blob/jobs/activesupport/lib/active_support/queueing.rb
5
-
6
- # The threaded consumer will run jobs in a background thread in
7
- # development mode or in a VM where running jobs on a thread in
8
- # production mode makes sense.
9
- #
10
- # When the process exits, the consumer pushes a nil onto the
11
- # queue and joins the thread, which will ensure that all jobs
12
- # are executed before the process finally dies.
13
- class ThreadedQueueConsumer
14
- attr_accessor :logger, :thread
15
-
16
- def initialize(queue, options = {})
17
- @queue = queue
18
- @logger = options[:logger]
19
- @fallback_logger = Logger.new($stderr)
20
- end
21
-
22
- def start
23
- @thread = Thread.new { consume }
24
- self
25
- end
26
-
27
- def shutdown
28
- @queue.push nil
29
- @thread.join
30
- end
31
-
32
- def drain
33
- while job = @queue.pop(true)
34
- job.run
35
- end
36
- rescue ThreadError
37
- end
38
-
39
- def consume
40
- while job = @queue.pop
41
- if @queue.respond_to? :completed_jobs
42
- @queue.completed_jobs << job
43
- end
44
- run job
45
- end
46
- end
47
-
48
- def run(job)
49
- job.run
50
- rescue Exception => exception
51
- handle_exception job, exception
52
- end
53
-
54
- def handle_exception(job, exception)
55
- (logger || @fallback_logger).error "Job Error: #{job.inspect}\n#{exception.message}\n#{exception.backtrace.join("\n")}"
56
- end
57
- end
58
- end