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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5b51288be65c487cc7ef84a0911f9e2848e443ff
4
- data.tar.gz: 329f36f92c8a6f877caeb401a036a609774c7f02
3
+ metadata.gz: e0ccff09799aceb6f771f22a6d9d981ee0edcfcd
4
+ data.tar.gz: 015acd74815a762ef5f837e0388e268613519952
5
5
  SHA512:
6
- metadata.gz: a89e7b82c415166c5b17752b3af454c2a08d1ebbf3d66af68d4ad6035262d2d06894680725b595aede27fb49fa31cf344c94a17b8601c23ebc21c14684832af4
7
- data.tar.gz: bfe056cb38d460e6516539cf26093185d275edb52bfdcf9f61e7e316b324c4450f83f8b66f7997f6b5a3923a92e79bde7260457a61da9db04e283d970f8c9191
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
- 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.
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.
@@ -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
- self.update_attribute(:execute_at, self.interval.seconds.from_now)
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
@@ -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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Arask
2
- VERSION = '0.1.2'
2
+ VERSION = '1.0.0'
3
3
  end
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 :time_cache; end
8
+ class << self; attr_accessor :jobs_touched, :exception_email, :exception_email_from; end
6
9
 
7
10
  def self.setup
8
- @jobs_touched = []
9
- yield Arask
11
+ Arask.jobs_touched = []
12
+ yield Setup
10
13
  begin
11
- AraskJob.all.where.not(id: @jobs_touched).delete_all
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:integer'
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.1.2
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-13 00:00:00.000000000 Z
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.0
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: 5.1.0
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