kronos-ruby 0.2.1 → 0.3.0.alpha.11

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: 138131adeba7fb2ccff6d4f4b83eb3fca66940c7
4
- data.tar.gz: 9f7c9106549b7c4ed245f9a7b8d9c00475716365
3
+ metadata.gz: d48ccce63684b70ad4e4c6f5ff2e2350a043ed7f
4
+ data.tar.gz: d5e32958a4d1c2e2c91341f2686f3bef9829427b
5
5
  SHA512:
6
- metadata.gz: bcf5c19cab28bc0b8d69a18358888f27f428e39af639cbc454a7fc2ff1d2f89b7a2debdc8cbcd35b4359816bebf47f131ea596b27ebee10874f0206c9be96946
7
- data.tar.gz: 811141eff3ac9afbc5ad8ce0b34981378543a6a7b2c29a04a617877c84fae6fa4e526b0c88caaf4f7611bb3b2bf91f1006becbd396111c9932e84b36e5417b8d
6
+ metadata.gz: b4c7ec7555173f715585f9c4d331c3df9199eb83c53dcf12a8634f43df067abd024a3f01d84c3df8b5534a4501b5402cd91fe40e8e3bc798b2de9eaa18d96b51
7
+ data.tar.gz: c2202ac1bf3e632842f3bbd49bfe3dc5e52cad0dae5f1a84981390ea27679ad9da3b34c89d4e09a4020d0a9709c163e2a90fc50a912d714b78985b041f1a51a7
@@ -4,6 +4,9 @@
4
4
 
5
5
  ### Unreleased
6
6
 
7
+ ### 0.3.0 [2017-09-27]
8
+ - [Added] Distributed lock capabilities
9
+
7
10
  ### 0.2.1 [2017-09-22]
8
11
  - [Added] Fields to ReportModel
9
12
  - [Fixed] Update Docs
data/README.md CHANGED
@@ -12,7 +12,7 @@ This project allows you to use a scheduler with well defined concepts of runners
12
12
  Add this line to your application's Gemfile:
13
13
 
14
14
  ```ruby
15
- gem 'kronos-ruby'
15
+ gem 'kronos-ruby', require: ['kronos']
16
16
  ```
17
17
 
18
18
  And then execute:
@@ -47,6 +47,15 @@ To view Krono's web dashboard, simply mount it into your Rack stack:
47
47
  mount Kronos::Web::App, at: '/kronos-dashboard'
48
48
  ```
49
49
 
50
+ If you want to protect Kronos dashboard, try using `Rack::Auth::Basic`:
51
+ ```ruby
52
+ protected_kronos = Rack::Auth::Basic.new(Kronos::Web::App) do |username, password|
53
+ # Check if username/password tuple is valid
54
+ end
55
+
56
+ mount protected_kronos, at: '/kronos-dashboard'
57
+ ```
58
+
50
59
  ## Developing
51
60
  - Clone this repository
52
61
  - Run `bin/setup` to install dependencies
@@ -4,6 +4,7 @@ require 'concurrent'
4
4
  require 'chronic'
5
5
  require 'erb'
6
6
  require 'ostruct'
7
+ require 'forwardable'
7
8
 
8
9
  require 'kronos/config_agent'
9
10
  require 'kronos/dependencies'
@@ -24,6 +24,7 @@ module Kronos
24
24
  def initialize(tasks, dependencies)
25
25
  @tasks = tasks
26
26
  @dependencies = dependencies
27
+ @lock_manager = LockManager.new(dependencies.storage)
27
28
  end
28
29
 
29
30
  def start
@@ -66,9 +67,10 @@ module Kronos
66
67
 
67
68
  # rubocop:disable RescueException
68
69
  def run_task(task)
69
- raw_execute_task(task)
70
+ task_id = task.id
71
+ @lock_manager.lock_and_execute(task_id) { raw_execute_task(task) }
70
72
  rescue ::Exception => error
71
- register_task_failure(task.id, error)
73
+ register_task_failure(task_id, error)
72
74
  end
73
75
  # rubocop:enable
74
76
 
@@ -109,3 +111,5 @@ module Kronos
109
111
  end
110
112
  end
111
113
  end
114
+
115
+ require 'kronos/runner/synchronous/lock_manager'
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kronos
4
+ module Runner
5
+ class Synchronous
6
+ class LockManager
7
+ extend Forwardable
8
+
9
+ def initialize(storage)
10
+ @storage = storage
11
+ end
12
+
13
+ def lock_and_execute(task_id)
14
+ return if locked_task?(task_id)
15
+ lock_id = lock_task(task_id)
16
+ return unless check_lock(task_id, lock_id)
17
+ yield
18
+ ensure
19
+ release_lock(task_id)
20
+ end
21
+
22
+ def_delegator :@storage, :locked_task?, :locked_task?
23
+ def_delegator :@storage, :lock_task, :lock_task
24
+ def_delegator :@storage, :check_lock, :check_lock
25
+ def_delegator :@storage, :release_lock, :release_lock
26
+ end
27
+ end
28
+ end
29
+ end
@@ -9,6 +9,7 @@ module Kronos
9
9
  def initialize
10
10
  @scheduled_tasks = []
11
11
  @reports = []
12
+ @locks = {}
12
13
  end
13
14
 
14
15
  def schedule(scheduled_task)
@@ -48,6 +49,24 @@ module Kronos
48
49
  def remove_reports_for(id)
49
50
  @reports.reject! { |report| report.task_id == id }
50
51
  end
52
+
53
+ def locked_task?(task_id)
54
+ @locks.key?(task_id)
55
+ end
56
+
57
+ def lock_task(task_id)
58
+ SecureRandom.uuid.tap do |lock_id|
59
+ @locks[task_id] = lock_id
60
+ end
61
+ end
62
+
63
+ def check_lock(task_id, lock_id)
64
+ @locks[task_id] == lock_id
65
+ end
66
+
67
+ def release_lock(task_id)
68
+ @locks.delete(task_id)
69
+ end
51
70
  end
52
71
  end
53
72
  end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mongoid'
4
+
5
+ module Kronos
6
+ module Storage
7
+ module Mongo
8
+ module Model
9
+ class LockModel
10
+ include Mongoid::Document
11
+ store_in collection: :kronos_locks
12
+
13
+ field :task_id, type: Symbol
14
+ field :value, type: String
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -2,13 +2,16 @@
2
2
 
3
3
  require 'kronos/storage/mongo/model/scheduled_task_model'
4
4
  require 'kronos/storage/mongo/model/report_model'
5
+ require 'kronos/storage/mongo/model/lock_model'
5
6
 
6
7
  module Kronos
7
8
  module Storage
8
9
  # :reek:UtilityFunction:
10
+ # :reek:TooManyMethods:
9
11
  class MongoDb
10
12
  SHEDULED_TASK_MODEL = Mongo::Model::ScheduledTaskModel
11
13
  REPORT_MODEL = Mongo::Model::ReportModel
14
+ LOCK_MODEL = Mongo::Model::LockModel
12
15
 
13
16
  def scheduled_tasks
14
17
  # Returns all current Kronos::ScheduledTask, resolved or pending
@@ -53,13 +56,31 @@ module Kronos
53
56
  query.exists? && query.first.next_run > Time.now
54
57
  end
55
58
 
59
+ def locked_task?(task_id)
60
+ LOCK_MODEL.where(task_id: task_id).exists?
61
+ end
62
+
63
+ def lock_task(task_id)
64
+ SecureRandom.uuid.tap do |lock_id|
65
+ LOCK_MODEL.create(task_id: task_id, value: lock_id)
66
+ end
67
+ end
68
+
69
+ def check_lock(task_id, lock_id)
70
+ LOCK_MODEL.where(task_id: task_id, value: lock_id).exists?
71
+ end
72
+
73
+ def release_lock(task_id)
74
+ LOCK_MODEL.where(task_id: task_id).destroy_all
75
+ end
76
+
56
77
  private
57
78
 
58
79
  def mount_report(report_model)
59
80
  case report_model.status
60
- when 0
81
+ when Kronos::Report::STATUSES[:success]
61
82
  mount_success_report(report_model)
62
- when 1
83
+ when Kronos::Report::STATUSES[:failure]
63
84
  mount_failure_report(report_model)
64
85
  end
65
86
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Kronos
4
- VERSION = '0.2.1'
4
+ VERSION = '0.3.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kronos-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0.alpha.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gabriel Teles
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-09-25 00:00:00.000000000 Z
11
+ date: 2017-09-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: concurrent-ruby
@@ -255,9 +255,11 @@ files:
255
255
  - lib/kronos/runner.rb
256
256
  - lib/kronos/runner/asynchronous.rb
257
257
  - lib/kronos/runner/synchronous.rb
258
+ - lib/kronos/runner/synchronous/lock_manager.rb
258
259
  - lib/kronos/scheduled_task.rb
259
260
  - lib/kronos/storage.rb
260
261
  - lib/kronos/storage/in_memory.rb
262
+ - lib/kronos/storage/mongo/model/lock_model.rb
261
263
  - lib/kronos/storage/mongo/model/report_model.rb
262
264
  - lib/kronos/storage/mongo/model/scheduled_task_model.rb
263
265
  - lib/kronos/storage/mongo_db.rb
@@ -281,12 +283,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
281
283
  version: '0'
282
284
  required_rubygems_version: !ruby/object:Gem::Requirement
283
285
  requirements:
284
- - - ">="
286
+ - - ">"
285
287
  - !ruby/object:Gem::Version
286
- version: '0'
288
+ version: 1.3.1
287
289
  requirements: []
288
290
  rubyforge_project:
289
- rubygems_version: 2.4.8
291
+ rubygems_version: 2.6.13
290
292
  signing_key:
291
293
  specification_version: 4
292
294
  summary: Persistent cron jobs manager