tasque 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +50 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +64 -0
- data/lib/generators/tasque/install_generator.rb +25 -0
- data/lib/generators/tasque/templates/create_tasque_tasks.erb +28 -0
- data/lib/generators/tasque/templates/tasque.erb +27 -0
- data/lib/tasque.rb +10 -0
- data/lib/tasque/configuration.rb +65 -0
- data/lib/tasque/processor.rb +82 -0
- data/lib/tasque/task.rb +139 -0
- data/lib/tasque/task_error.rb +11 -0
- data/lib/tasque/version.rb +3 -0
- data/tasque.gemspec +24 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: fe02e8efd7f9659a71065ff03456285a77c3738a
|
4
|
+
data.tar.gz: 0148d4b75800c0249624d34a50af1902857ad804
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5446b19a1112207b663a3d91045da3c32f24d3fd4affd5d4adda441a22c412c27dc258a5f18a38f83e1409418c4cf9d8047b50c18fc7ba0f16c6cca96343b9a3
|
7
|
+
data.tar.gz: 6af7d2e232ef54594ee8a0f9971693bbcd22666cbcc251fa0b7b3cebc3c9bdd9b30ac15079f0b10c5b74ee713b11dab0c4ae993f29aae6fb5dd8a9948d37536d
|
data/.gitignore
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
/.config
|
4
|
+
/coverage/
|
5
|
+
/InstalledFiles
|
6
|
+
/pkg/
|
7
|
+
/spec/reports/
|
8
|
+
/spec/examples.txt
|
9
|
+
/test/tmp/
|
10
|
+
/test/version_tmp/
|
11
|
+
/tmp/
|
12
|
+
|
13
|
+
# Used by dotenv library to load environment variables.
|
14
|
+
# .env
|
15
|
+
|
16
|
+
## Specific to RubyMotion:
|
17
|
+
.dat*
|
18
|
+
.repl_history
|
19
|
+
build/
|
20
|
+
*.bridgesupport
|
21
|
+
build-iPhoneOS/
|
22
|
+
build-iPhoneSimulator/
|
23
|
+
|
24
|
+
## Specific to RubyMotion (use of CocoaPods):
|
25
|
+
#
|
26
|
+
# We recommend against adding the Pods directory to your .gitignore. However
|
27
|
+
# you should judge for yourself, the pros and cons are mentioned at:
|
28
|
+
# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
|
29
|
+
#
|
30
|
+
# vendor/Pods/
|
31
|
+
|
32
|
+
## Documentation cache and generated files:
|
33
|
+
/.yardoc/
|
34
|
+
/_yardoc/
|
35
|
+
/doc/
|
36
|
+
/rdoc/
|
37
|
+
|
38
|
+
## Environment normalization:
|
39
|
+
/.bundle/
|
40
|
+
/vendor/bundle
|
41
|
+
/lib/bundler/man/
|
42
|
+
|
43
|
+
# for a library or gem, you might want to ignore these files since the code is
|
44
|
+
# intended to run in multiple environments; otherwise, check them in:
|
45
|
+
# Gemfile.lock
|
46
|
+
# .ruby-version
|
47
|
+
# .ruby-gemset
|
48
|
+
|
49
|
+
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
50
|
+
.rvmrc
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2018 Gropher
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# tasque
|
2
|
+
|
3
|
+
ActiveRecord based task queue. Task processing queue with states, history and priorities. Works with your favorite database.
|
4
|
+
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's `Gemfile`:
|
9
|
+
|
10
|
+
gem 'tasque'
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it manually:
|
17
|
+
|
18
|
+
$ gem install tasque
|
19
|
+
|
20
|
+
Then you need to generate initializer and migration:
|
21
|
+
|
22
|
+
$ rails g tasque:install
|
23
|
+
|
24
|
+
Don't forget to run migrations:
|
25
|
+
|
26
|
+
$ rake db:migrate
|
27
|
+
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
Create a simple task:
|
32
|
+
|
33
|
+
Tasque::Task.create! task: 'test', params: { text: 'This is the test!' }
|
34
|
+
|
35
|
+
Or a task with priority:
|
36
|
+
|
37
|
+
Tasque::Task.create! task: 'test', priority: 9000, params: { text: 'I will be processed first!!!' }
|
38
|
+
|
39
|
+
Or add a tag to find this task easily:
|
40
|
+
|
41
|
+
Tasque::Task.create! task: 'test', tag: 'user_123', params: { text: 'This task is property of User #123!' }
|
42
|
+
|
43
|
+
Now to process the task:
|
44
|
+
|
45
|
+
# create task processor
|
46
|
+
processor = Tasque::Processor.new
|
47
|
+
|
48
|
+
# register a handler for test tasks
|
49
|
+
processor.add_handler('test') do |task|
|
50
|
+
puts "Got task ##{task.id}. Task says: '#{task.params['text']}'"
|
51
|
+
{ log: 'got task, printed text' } # returning task result
|
52
|
+
end
|
53
|
+
|
54
|
+
# start processor and wait
|
55
|
+
processor.start
|
56
|
+
|
57
|
+
|
58
|
+
## Contributing
|
59
|
+
|
60
|
+
1. Fork it
|
61
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
62
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
63
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
64
|
+
5. Create new Pull Request
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
|
4
|
+
module Tasque
|
5
|
+
class InstallGenerator < ::Rails::Generators::Base
|
6
|
+
include Rails::Generators::Migration
|
7
|
+
|
8
|
+
desc 'Create a sample Tasque initializer and migration'
|
9
|
+
source_root File.expand_path('../templates', __FILE__)
|
10
|
+
|
11
|
+
def self.next_migration_number(path)
|
12
|
+
unless @prev_migration_nr
|
13
|
+
@prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
14
|
+
else
|
15
|
+
@prev_migration_nr += 1
|
16
|
+
end
|
17
|
+
@prev_migration_nr.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_initializer
|
21
|
+
template 'tasque.erb', 'config/initializers/tasque.rb'
|
22
|
+
migration_template "create_tasque_tasks.erb", "db/migrate/create_tasque_tasks.rb"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class CreateTasqueTasks < ActiveRecord::Migration[4.2]
|
2
|
+
def change
|
3
|
+
create_table :tasque_tasks do |t|
|
4
|
+
t.string :tag
|
5
|
+
t.string :task
|
6
|
+
t.text :params
|
7
|
+
t.text :result
|
8
|
+
t.string :worker
|
9
|
+
t.integer :priority, default: 0
|
10
|
+
t.integer :attempts, default: 0
|
11
|
+
t.integer :progress, default: 0
|
12
|
+
t.string :status, default: 'new'
|
13
|
+
|
14
|
+
t.datetime :started_at
|
15
|
+
t.datetime :finished_at
|
16
|
+
|
17
|
+
t.timestamps
|
18
|
+
end
|
19
|
+
|
20
|
+
add_index :tasque_tasks, [:status, :task]
|
21
|
+
add_index :tasque_tasks, :status
|
22
|
+
add_index :tasque_tasks, :tag
|
23
|
+
add_index :tasque_tasks, :task
|
24
|
+
add_index :tasque_tasks, :worker
|
25
|
+
add_index :tasque_tasks, :priority
|
26
|
+
add_index :tasque_tasks, :attempts
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
TASQUE_ROOT = Rails.root
|
2
|
+
|
3
|
+
Tasque.configure do |config|
|
4
|
+
config.logger = Rails.logger
|
5
|
+
|
6
|
+
# Which database from database.yml we use
|
7
|
+
config.environment = Rails.env
|
8
|
+
|
9
|
+
# This option need only if you want to receive tasks
|
10
|
+
# config.worker = 'example'
|
11
|
+
|
12
|
+
# How often should processor check for a new tasks
|
13
|
+
# config.check_interval = 10 # seconds
|
14
|
+
|
15
|
+
# How often should task progress be reported
|
16
|
+
# config.progress_interval = 5 # seconds
|
17
|
+
|
18
|
+
# This option tells processor to fetch only tasks with priority value greater than or equal to minimum_priority
|
19
|
+
# config.minimum_priority = 123
|
20
|
+
|
21
|
+
# Send task state updates and progress notifications via Insque
|
22
|
+
# config.notify = true
|
23
|
+
|
24
|
+
# Send worker heartbeat via Insque
|
25
|
+
# config.heartbeat = true
|
26
|
+
# config.heartbeat_interval = 30 # seconds
|
27
|
+
end
|
data/lib/tasque.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Tasque
|
4
|
+
class << self
|
5
|
+
attr_accessor :config
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.configure
|
9
|
+
self.config ||= Configuration.new
|
10
|
+
yield(config) if block_given?
|
11
|
+
self.database_connection
|
12
|
+
return self.config
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.database_connection()
|
16
|
+
raise 'No configuration. Use Tasque.configure' if self.config.nil?
|
17
|
+
@database ||= begin
|
18
|
+
if !defined?(Rails) && !ActiveRecord::Base.connected?
|
19
|
+
ActiveRecord::Base.logger = self.config.logger
|
20
|
+
db = self.config.database[self.config.environment.to_s]
|
21
|
+
db = self.config.database if db.nil?
|
22
|
+
ActiveRecord::Base.establish_connection(db)
|
23
|
+
ActiveRecord::Base.connection
|
24
|
+
end
|
25
|
+
ActiveRecord::Base
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.root
|
30
|
+
defined?(TASQUE_ROOT) ? TASQUE_ROOT : Dir.pwd
|
31
|
+
end
|
32
|
+
|
33
|
+
class Configuration
|
34
|
+
attr_accessor :database
|
35
|
+
attr_accessor :database_file
|
36
|
+
attr_accessor :environment
|
37
|
+
attr_accessor :logger
|
38
|
+
attr_accessor :check_interval
|
39
|
+
attr_accessor :progress_interval
|
40
|
+
attr_accessor :minimum_priority
|
41
|
+
attr_accessor :worker
|
42
|
+
attr_accessor :heartbeat
|
43
|
+
attr_accessor :heartbeat_interval
|
44
|
+
attr_accessor :notify
|
45
|
+
|
46
|
+
def initialize
|
47
|
+
self.environment = :development
|
48
|
+
self.database_file = ::File.expand_path('config/database.yml', Tasque.root)
|
49
|
+
self.check_interval = 10 # seconds
|
50
|
+
self.worker = "default"
|
51
|
+
self.progress_interval = 5 # seconds
|
52
|
+
self.heartbeat = false
|
53
|
+
self.heartbeat_interval = 10 # seconds
|
54
|
+
self.notify = false
|
55
|
+
end
|
56
|
+
|
57
|
+
def database_file=(path)
|
58
|
+
if File.exists?(path)
|
59
|
+
@database = YAML.load(File.read(path)) || {}
|
60
|
+
@database_file = path
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'timers'
|
2
|
+
|
3
|
+
module Tasque
|
4
|
+
class Processor
|
5
|
+
attr_reader :timers
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@timers = Timers::Group.new
|
9
|
+
@last_task = false
|
10
|
+
@current_task = nil
|
11
|
+
@handlers = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_handler type, &block
|
15
|
+
@handlers[type.to_sym] = Proc.new do |task|
|
16
|
+
@current_task = task
|
17
|
+
task.process
|
18
|
+
begin
|
19
|
+
task.result = block.call task
|
20
|
+
rescue Tasque::TaskError => e
|
21
|
+
task.error = {
|
22
|
+
task_error: e.task_error
|
23
|
+
}
|
24
|
+
rescue Exception => e
|
25
|
+
task.error = {
|
26
|
+
exception: e.message,
|
27
|
+
backtrace: e.backtrace
|
28
|
+
}
|
29
|
+
end
|
30
|
+
task.error? ? task.failure : task.complete
|
31
|
+
@current_task = nil
|
32
|
+
end
|
33
|
+
@timers.every(check_interval) do
|
34
|
+
begin
|
35
|
+
has_task = Tasque::Task.fetch(type) do |task|
|
36
|
+
@handlers[type.to_sym].call(task)
|
37
|
+
end
|
38
|
+
end while has_task
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def start
|
43
|
+
shutdown = ->(signo) {
|
44
|
+
if @last_task
|
45
|
+
unless @current_task.nil?
|
46
|
+
@current_task.failure
|
47
|
+
@current_task.reprocess
|
48
|
+
end
|
49
|
+
exit!
|
50
|
+
end
|
51
|
+
@last_task = true
|
52
|
+
}
|
53
|
+
trap("SIGINT", shutdown)
|
54
|
+
trap("SIGTERM", shutdown)
|
55
|
+
if Tasque.config.heartbeat && defined?(Insque)
|
56
|
+
heartbeat_thread = Thread.new do
|
57
|
+
heartbeat_timers = Timers::Group.new
|
58
|
+
heartbeat_timers.every(Tasque.config.heartbeat_interval) do
|
59
|
+
message = {
|
60
|
+
worker: Tasque.config.worker,
|
61
|
+
busy: !@current_job.nil?
|
62
|
+
}
|
63
|
+
Insque.broadcast :heartbeat, message
|
64
|
+
end
|
65
|
+
loop do
|
66
|
+
heartbeat_timers.wait
|
67
|
+
end
|
68
|
+
end
|
69
|
+
heartbeat_thread.abort_on_exception = true
|
70
|
+
end
|
71
|
+
loop do
|
72
|
+
break if @last_task
|
73
|
+
@timers.wait
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
def check_interval
|
79
|
+
Tasque.config.check_interval
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/tasque/task.rb
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'state_machine/core'
|
2
|
+
|
3
|
+
module Tasque
|
4
|
+
class Task < ActiveRecord::Base
|
5
|
+
extend StateMachine::MacroMethods
|
6
|
+
|
7
|
+
MAX_ATTEMPTS=3
|
8
|
+
|
9
|
+
self.table_name = :tasque_tasks
|
10
|
+
|
11
|
+
serialize :params, JSON
|
12
|
+
serialize :result, JSON
|
13
|
+
|
14
|
+
scope :with_task, ->(task) { where(task: task).order priority: :desc }
|
15
|
+
scope :minimum_priority, ->(priority) { priority.nil? ? nil : where('priority >= ?', priority) }
|
16
|
+
scope :to_process, -> { where status: %w(new reprocessed) }
|
17
|
+
scope :with_error, -> { where status: 'error' }
|
18
|
+
scope :to_reprocess, -> { with_error.where 'attempts < ?', MAX_ATTEMPTS }
|
19
|
+
scope :finished_in, ->(interval) { where('finished_at > ?', interval.ago) }
|
20
|
+
|
21
|
+
validates :task, presence: true
|
22
|
+
validates :attempts, numericality: { only_integer: true, greater_than_or_equal_to: 0 }
|
23
|
+
validates :progress, numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: 100 }
|
24
|
+
validates :priority, numericality: { only_integer: true }
|
25
|
+
|
26
|
+
class << self
|
27
|
+
def fetch(type, &block)
|
28
|
+
task = nil
|
29
|
+
transaction do
|
30
|
+
minimum_priority = Tasque.config.minimum_priority
|
31
|
+
task = self.with_task(type).to_process.minimum_priority(minimum_priority).lock(true).first
|
32
|
+
if task and task.can_pickup?
|
33
|
+
task.pickup
|
34
|
+
else
|
35
|
+
task = nil
|
36
|
+
end
|
37
|
+
end
|
38
|
+
yield(task) if task
|
39
|
+
!!task
|
40
|
+
end
|
41
|
+
|
42
|
+
def monitoring
|
43
|
+
{
|
44
|
+
queue: Tasque::Task.to_process.count,
|
45
|
+
errors: Tasque::Task.with_error.finished_in(1.hour).count
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def autoreprocess(reprocess_limit = nil)
|
50
|
+
Tasque::Task.to_reprocess.limit(reprocess_limit.to_i).each do |task|
|
51
|
+
task.reprocess
|
52
|
+
end.count
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
state_machine :status, initial: :new do
|
57
|
+
after_transition on: :pickup do |task|
|
58
|
+
task.update_column :worker, Tasque.config.worker
|
59
|
+
end
|
60
|
+
|
61
|
+
after_transition on: :process do |task|
|
62
|
+
task.update_column :started_at, Time.now
|
63
|
+
end
|
64
|
+
|
65
|
+
after_transition on: :complete do |task|
|
66
|
+
task.update_columns progress: 100, finished_at: Time.now
|
67
|
+
end
|
68
|
+
|
69
|
+
after_transition on: :failure do |task|
|
70
|
+
task.update_columns attempts: (task.attempts + 1), result: { error: task.error }, progress: 0
|
71
|
+
end
|
72
|
+
|
73
|
+
after_transition on: :reprocess do |task|
|
74
|
+
task.update_columns started_at: nil, result: nil, progress: 0
|
75
|
+
end
|
76
|
+
|
77
|
+
after_transition do: :notify
|
78
|
+
|
79
|
+
|
80
|
+
event :pickup do
|
81
|
+
transition [:new, :reprocessed] => :starting
|
82
|
+
end
|
83
|
+
|
84
|
+
event :process do
|
85
|
+
transition :starting => :processing
|
86
|
+
end
|
87
|
+
|
88
|
+
event :complete do
|
89
|
+
transition :processing => :complete
|
90
|
+
end
|
91
|
+
|
92
|
+
event :failure do
|
93
|
+
transition :processing => :error
|
94
|
+
end
|
95
|
+
|
96
|
+
event :reprocess do
|
97
|
+
transition [:processing, :complete, :error] => :reprocessed
|
98
|
+
end
|
99
|
+
|
100
|
+
event :cancel do
|
101
|
+
transition any - [:processing] => :canceled
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
state :processing do
|
106
|
+
def progress!(val)
|
107
|
+
val = 0 if val < 0
|
108
|
+
val = 100 if val > 100
|
109
|
+
return if (Time.now.to_i - @last_progress_at.to_i) < Tasque.config.progress_interval || val == @last_progress_val
|
110
|
+
self.update_columns progress: val, updated_at: Time.now
|
111
|
+
@last_progress_at = Time.now
|
112
|
+
@last_progress_val = val
|
113
|
+
notify
|
114
|
+
end
|
115
|
+
|
116
|
+
def error!(task_error)
|
117
|
+
raise Tasque::TaskError.new(self, task_error)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
state :processing, :error do
|
122
|
+
attr_accessor :error
|
123
|
+
|
124
|
+
def error?
|
125
|
+
!@error.nil?
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
def notify
|
132
|
+
if Tasque.config.notify && defined?(Insque)
|
133
|
+
Insque.broadcast :task_update, self
|
134
|
+
end
|
135
|
+
rescue Exception => e
|
136
|
+
logger.error "Notify error: #{e.message}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
data/tasque.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'tasque/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "tasque"
|
8
|
+
gem.version = Tasque::VERSION
|
9
|
+
gem.authors = ["Yuri Gomozov"]
|
10
|
+
gem.email = ["grophen@gmail.com"]
|
11
|
+
gem.description = %q{Task processing queue with states, history and priorities. Works with your favorite database. }
|
12
|
+
gem.summary = %q{ActiveRecord based task queue}
|
13
|
+
gem.homepage = "https://github.com/Gropher/tasque"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_dependency("activerecord")
|
21
|
+
gem.add_dependency("timers")
|
22
|
+
gem.add_dependency("state_machine")
|
23
|
+
gem.add_dependency("json")
|
24
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tasque
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Yuri Gomozov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-04-13 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activerecord
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: timers
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: state_machine
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: json
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: 'Task processing queue with states, history and priorities. Works with
|
70
|
+
your favorite database. '
|
71
|
+
email:
|
72
|
+
- grophen@gmail.com
|
73
|
+
executables: []
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- ".gitignore"
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE
|
80
|
+
- README.md
|
81
|
+
- lib/generators/tasque/install_generator.rb
|
82
|
+
- lib/generators/tasque/templates/create_tasque_tasks.erb
|
83
|
+
- lib/generators/tasque/templates/tasque.erb
|
84
|
+
- lib/tasque.rb
|
85
|
+
- lib/tasque/configuration.rb
|
86
|
+
- lib/tasque/processor.rb
|
87
|
+
- lib/tasque/task.rb
|
88
|
+
- lib/tasque/task_error.rb
|
89
|
+
- lib/tasque/version.rb
|
90
|
+
- tasque.gemspec
|
91
|
+
homepage: https://github.com/Gropher/tasque
|
92
|
+
licenses: []
|
93
|
+
metadata: {}
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 2.5.1
|
111
|
+
signing_key:
|
112
|
+
specification_version: 4
|
113
|
+
summary: ActiveRecord based task queue
|
114
|
+
test_files: []
|