kronos-ruby 0.2.1 → 0.3.0.alpha.11

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: 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