arask 0.1.2 → 1.0.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.
- checksums.yaml +4 -4
- data/README.md +21 -4
- data/lib/arask/arask_job.rb +22 -2
- data/lib/arask/initialize.rb +4 -0
- data/lib/arask/run_jobs.rb +17 -0
- data/lib/arask/setup.rb +51 -0
- data/lib/arask/version.rb +1 -1
- data/lib/arask.rb +7 -53
- data/lib/generators/arask/install_generator.rb +1 -1
- metadata +51 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0ccff09799aceb6f771f22a6d9d981ee0edcfcd
|
4
|
+
data.tar.gz: 015acd74815a762ef5f837e0388e268613519952
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b599908a948826e65cbfc794a1c94ca245199a47a75dad79711fe5880c8a9f912265b4b07342d84017ee7646612bdb701653d94bbe2600151f24df28910e476e
|
7
|
+
data.tar.gz: d8a2fc39027e99da66b37be2fe442449f8c8257f6d61cd27a6752c3f7ebe924135237316a99fdf810f3816528f5c20b02e07c3944000155b4633bb9229201fe0
|
data/README.md
CHANGED
@@ -1,19 +1,33 @@
|
|
1
1
|
# Arask
|
2
2
|
Automatic RAils taSKs (with minimal setup).
|
3
3
|
|
4
|
-
|
4
|
+
No need to setup anything outside of Rails. If Rails is running, so is Arask.
|
5
|
+
|
6
|
+
Use cron syntax or simply define the interval.
|
5
7
|
|
6
8
|
## Usage
|
7
9
|
After installation, you can edit config/initializers/arask.rb with your tasks.
|
8
10
|
|
9
|
-
### Examples
|
11
|
+
### Examples of jobs in the initializer
|
10
12
|
```ruby
|
11
13
|
arask.create script: 'puts "IM ALIVE!"', interval: :daily, run_first_time: true
|
12
14
|
arask.create script: 'Attachment.process_new', interval: 5.hours if Rails.env.production?
|
15
|
+
arask.create task: 'send:logs', cron: '0 2 * * *' # At 02:00 every day
|
16
|
+
arask.create task: 'update:cache', cron: '*/5 * * * *' # Every 5 minutes
|
13
17
|
# Run rake task:
|
14
18
|
arask.create task: 'my:awesome_task', interval: :hourly
|
19
|
+
# On exceptions, send email
|
20
|
+
arask.on_exception email: 'errors@example.com'
|
15
21
|
```
|
16
22
|
|
23
|
+
### About cron
|
24
|
+
Arask uses [fugit](https://github.com/floraison/fugit) to parse cron and get next execution time. It follows normal cron syntax. You can test your cron at https://crontab.guru/.
|
25
|
+
|
26
|
+
Not supported is `@reboot`.
|
27
|
+
|
28
|
+
### About interval
|
29
|
+
The interval starts when the task has started running. If a task with the interval `:hourly` is run at 08:37PM, then it will run the next time at 09:37PM.
|
30
|
+
|
17
31
|
## Installation
|
18
32
|
Add this line to your application's Gemfile:
|
19
33
|
```ruby
|
@@ -27,11 +41,14 @@ $ rails generate arask:install
|
|
27
41
|
$ rails db:migrate
|
28
42
|
```
|
29
43
|
|
30
|
-
Setup your tasks in config/initializers/arask.rb.
|
44
|
+
Setup your tasks in config/initializers/arask.rb. Initially it looks [like this](lib/arask/initialize.rb).
|
31
45
|
|
32
46
|
## Todos
|
33
|
-
* Be able to setup error handling. For instance in initializer: `arask.on_fail email: 'gr34test_dev@example.com'`
|
34
47
|
* Have a "try again" feature. For instance `arask.create script: 'raise "I failed"', interval: :daily, fail_retry: 5.minutes, retry_at_most: 2`
|
48
|
+
* Tests
|
49
|
+
|
50
|
+
## Setup for Heroku
|
51
|
+
None. But if you use a hobby dyno and it falls to sleep, so will Arask. As soon as the dyno wakes up, Arask will run any pending jobs.
|
35
52
|
|
36
53
|
## Caveats
|
37
54
|
If you reload a database dump, your jobs could be run again.
|
data/lib/arask/arask_job.rb
CHANGED
@@ -2,18 +2,38 @@ module Arask
|
|
2
2
|
require 'rake'
|
3
3
|
|
4
4
|
class AraskJob < ActiveRecord::Base
|
5
|
+
after_create :calculate_new_execute_at
|
6
|
+
|
5
7
|
def run
|
6
|
-
|
8
|
+
calculate_new_execute_at
|
7
9
|
begin
|
8
10
|
if self.job.start_with?('Rake::Task')
|
9
11
|
Rake.load_rakefile Rails.root.join( 'Rakefile' )
|
10
12
|
end
|
11
13
|
eval(self.job)
|
12
14
|
rescue Exception => e
|
13
|
-
# TODO: Alert broken job
|
14
15
|
puts 'Arask: Job failed'
|
15
16
|
p self
|
16
17
|
puts e.message
|
18
|
+
|
19
|
+
unless Arask.exception_email.nil?
|
20
|
+
ActionMailer::Base.mail(
|
21
|
+
from: Arask.exception_email_from,
|
22
|
+
to: Arask.exception_email,
|
23
|
+
subject: "Arask failed",
|
24
|
+
body: "Job: #{self.inspect}\n\nException:\n#{e.message}"
|
25
|
+
).deliver
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def calculate_new_execute_at
|
32
|
+
if self.interval.start_with?('cron: ')
|
33
|
+
cron = Fugit::Cron.parse(self.interval.split(' ', 2)[1])
|
34
|
+
self.update_attribute(:execute_at, cron.next_time.to_t)
|
35
|
+
else
|
36
|
+
self.update_attribute(:execute_at, self.interval.to_i.seconds.from_now)
|
17
37
|
end
|
18
38
|
end
|
19
39
|
end
|
data/lib/arask/initialize.rb
CHANGED
@@ -2,6 +2,10 @@ Arask.setup do |arask|
|
|
2
2
|
# Examples
|
3
3
|
#arask.create script: 'puts "IM ALIVE!"', interval: :daily, run_first_time: true
|
4
4
|
#arask.create script: 'Attachment.process_new', interval: 5.hours if Rails.env.production?
|
5
|
+
#arask.create task: 'send:logs', cron: '0 2 * * *' # At 02:00 every day
|
6
|
+
#arask.create task: 'update:cache', cron: '*/5 * * * *' # Every 5 minutes
|
5
7
|
# Run rake task:
|
6
8
|
#arask.create task: 'my:awesome_task', interval: :hourly
|
9
|
+
# On exceptions, send email
|
10
|
+
#arask.on_exception email: 'errors@example.com'
|
7
11
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Arask
|
2
|
+
class RunJobs < ActiveJob::Base
|
3
|
+
queue_as :default
|
4
|
+
|
5
|
+
def perform
|
6
|
+
begin
|
7
|
+
AraskJob.transaction do
|
8
|
+
AraskJob.where('execute_at < ?', DateTime.now).lock.each do |job|
|
9
|
+
job.run
|
10
|
+
end
|
11
|
+
end
|
12
|
+
rescue
|
13
|
+
end
|
14
|
+
Arask.queue_self
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/arask/setup.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Arask
|
2
|
+
class Setup
|
3
|
+
def self.on_exception(email: nil, from: 'robot@server')
|
4
|
+
Arask.exception_email = email
|
5
|
+
Arask.exception_email_from = from
|
6
|
+
puts "Arask could not parse parameter for on_exception!" unless email.class == String
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.create(script: nil, task: nil, interval: nil, cron: nil, run_first_time: false)
|
10
|
+
unless interval.nil?
|
11
|
+
case interval
|
12
|
+
when :hourly
|
13
|
+
interval = 1.hour
|
14
|
+
when :daily
|
15
|
+
interval = 1.day
|
16
|
+
when :monthly
|
17
|
+
interval = 1.month
|
18
|
+
end
|
19
|
+
interval = interval.to_s.to_i
|
20
|
+
end
|
21
|
+
unless cron.nil?
|
22
|
+
interval = 'cron: ' + cron
|
23
|
+
end
|
24
|
+
if interval.nil?
|
25
|
+
puts 'Arask: You did not specify either cron: or interval:! When should the task run?'
|
26
|
+
return
|
27
|
+
end
|
28
|
+
unless task.nil?
|
29
|
+
script = "Rake::Task['#{task}'].invoke"
|
30
|
+
end
|
31
|
+
if script.nil?
|
32
|
+
puts 'Arask: You did not specify a script or task to run!'
|
33
|
+
return
|
34
|
+
end
|
35
|
+
begin
|
36
|
+
job = AraskJob.where(job: script, interval: interval).first
|
37
|
+
if job
|
38
|
+
Arask.jobs_touched << job.id
|
39
|
+
else
|
40
|
+
job = AraskJob.create(job: script, interval: interval)
|
41
|
+
Arask.jobs_touched << job.id
|
42
|
+
if run_first_time===true
|
43
|
+
job.run
|
44
|
+
end
|
45
|
+
end
|
46
|
+
rescue ActiveRecord::StatementInvalid => e
|
47
|
+
puts 'Could not create arask job! Looks like the database is not migrated? Remember to run `rails generate arask:install` and `rails db:migrate`'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/arask/version.rb
CHANGED
data/lib/arask.rb
CHANGED
@@ -1,14 +1,17 @@
|
|
1
1
|
require "arask/railtie"
|
2
2
|
require "arask/arask_job"
|
3
|
+
require "arask/run_jobs"
|
4
|
+
require "arask/setup"
|
5
|
+
require 'fugit' # To parse cron
|
3
6
|
|
4
7
|
module Arask
|
5
|
-
class << self; attr_accessor :
|
8
|
+
class << self; attr_accessor :jobs_touched, :exception_email, :exception_email_from; end
|
6
9
|
|
7
10
|
def self.setup
|
8
|
-
|
9
|
-
yield
|
11
|
+
Arask.jobs_touched = []
|
12
|
+
yield Setup
|
10
13
|
begin
|
11
|
-
AraskJob.all.where.not(id:
|
14
|
+
AraskJob.all.where.not(id: Arask.jobs_touched).delete_all
|
12
15
|
Arask.queue_self
|
13
16
|
rescue
|
14
17
|
end
|
@@ -24,53 +27,4 @@ module Arask
|
|
24
27
|
end
|
25
28
|
end
|
26
29
|
|
27
|
-
def self.create(script: nil, task: nil, interval:, run_first_time: false)
|
28
|
-
case interval
|
29
|
-
when :hourly
|
30
|
-
interval = 1.hour
|
31
|
-
when :daily
|
32
|
-
interval = 1.day
|
33
|
-
when :monthly
|
34
|
-
interval = 1.month
|
35
|
-
end
|
36
|
-
interval = interval.to_s.to_i
|
37
|
-
unless task.nil?
|
38
|
-
script = "Rake::Task['#{task}'].invoke"
|
39
|
-
end
|
40
|
-
if script.nil?
|
41
|
-
puts 'Arask: You did not specify a script or task to run!'
|
42
|
-
return
|
43
|
-
end
|
44
|
-
begin
|
45
|
-
job = AraskJob.where(job: script, interval: interval).first
|
46
|
-
if job
|
47
|
-
@jobs_touched << job.id
|
48
|
-
else
|
49
|
-
job = AraskJob.create(job: script, interval: interval, execute_at: interval.seconds.from_now)
|
50
|
-
@jobs_touched << job.id
|
51
|
-
if run_first_time===true
|
52
|
-
job.run
|
53
|
-
end
|
54
|
-
end
|
55
|
-
rescue ActiveRecord::StatementInvalid => e
|
56
|
-
puts 'Could not create arask job! Looks like the database is not migrated? Remember to run `rails generate arask:install` and `rails db:migrate`'
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
|
61
|
-
class RunJobs < ActiveJob::Base
|
62
|
-
queue_as :default
|
63
|
-
|
64
|
-
def perform
|
65
|
-
begin
|
66
|
-
AraskJob.transaction do
|
67
|
-
AraskJob.where('execute_at < ?', DateTime.now).lock.each do |job|
|
68
|
-
job.run
|
69
|
-
end
|
70
|
-
end
|
71
|
-
rescue
|
72
|
-
end
|
73
|
-
Arask.queue_self
|
74
|
-
end
|
75
|
-
end
|
76
30
|
end
|
@@ -8,6 +8,6 @@ class Arask::InstallGenerator < Rails::Generators::Base
|
|
8
8
|
Arask::InstallGenerator.source_root File.expand_path('../../arask', __FILE__)
|
9
9
|
copy_file '../../arask/initialize.rb', 'config/initializers/arask.rb'
|
10
10
|
|
11
|
-
generate 'migration', 'create_arask_jobs job:string execute_at:datetime:index interval:
|
11
|
+
generate 'migration', 'create_arask_jobs job:string execute_at:datetime:index interval:string'
|
12
12
|
end
|
13
13
|
end
|
metadata
CHANGED
@@ -1,30 +1,73 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: arask
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Esben Damgaard
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-06-
|
11
|
+
date: 2018-06-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 5.1
|
19
|
+
version: '5.1'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: fugit
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.1'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: sqlite3
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
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: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
22
64
|
version_requirements: !ruby/object:Gem::Requirement
|
23
65
|
requirements:
|
24
66
|
- - ">="
|
25
67
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
27
|
-
description: With minimal setup, be able to regularly run tasks.
|
68
|
+
version: '0'
|
69
|
+
description: With minimal setup, be able to regularly run tasks in Rails. Either user
|
70
|
+
cron syntax or simply define an interval.
|
28
71
|
email:
|
29
72
|
- ebbe@hvemder.dk
|
30
73
|
executables: []
|
@@ -38,6 +81,8 @@ files:
|
|
38
81
|
- lib/arask/arask_job.rb
|
39
82
|
- lib/arask/initialize.rb
|
40
83
|
- lib/arask/railtie.rb
|
84
|
+
- lib/arask/run_jobs.rb
|
85
|
+
- lib/arask/setup.rb
|
41
86
|
- lib/arask/version.rb
|
42
87
|
- lib/generators/arask/install_generator.rb
|
43
88
|
homepage: http://github.com/Ebbe/arask
|