arask 0.1.2 → 1.0.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
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