chrono_trigger 0.2.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: cbca0c2caa1b69582cd2e5e35bb6df578b9ae913d2da07f8e3b84d76c812ade7
4
+ data.tar.gz: 02c0808b8df6dc06be2aa7c8812f1cac72bfb53192c97acb0ba9ba6a48f5225e
5
+ SHA512:
6
+ metadata.gz: 016a3b4aacbf0c960de0c17885287eb4505da012d130eb6c0ea9a96cd4098d1848cc37af9072d4907816e3c25bc6d2f712ef0f449245cff598020cad6bea184d
7
+ data.tar.gz: dfb36735721ce71346ac77bbd0a031f91ffa98082850f89fc1d201a5dafe6de0875cfe36fa6c95f6b39b3233593b5e0006c3bc6792eb2d887991fc19806f74c6
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in cable_ready.gemspec
6
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,167 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ chrono_trigger (1.0.0)
5
+ concurrent-ruby (~> 1.1, >= 1.1.8)
6
+ concurrent-ruby-edge (~> 0.6, >= 0.6.0)
7
+ rails (~> 5.2)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ actioncable (5.2.5)
13
+ actionpack (= 5.2.5)
14
+ nio4r (~> 2.0)
15
+ websocket-driver (>= 0.6.1)
16
+ actionmailer (5.2.5)
17
+ actionpack (= 5.2.5)
18
+ actionview (= 5.2.5)
19
+ activejob (= 5.2.5)
20
+ mail (~> 2.5, >= 2.5.4)
21
+ rails-dom-testing (~> 2.0)
22
+ actionpack (5.2.5)
23
+ actionview (= 5.2.5)
24
+ activesupport (= 5.2.5)
25
+ rack (~> 2.0, >= 2.0.8)
26
+ rack-test (>= 0.6.3)
27
+ rails-dom-testing (~> 2.0)
28
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
29
+ actionview (5.2.5)
30
+ activesupport (= 5.2.5)
31
+ builder (~> 3.1)
32
+ erubi (~> 1.4)
33
+ rails-dom-testing (~> 2.0)
34
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
35
+ activejob (5.2.5)
36
+ activesupport (= 5.2.5)
37
+ globalid (>= 0.3.6)
38
+ activemodel (5.2.5)
39
+ activesupport (= 5.2.5)
40
+ activerecord (5.2.5)
41
+ activemodel (= 5.2.5)
42
+ activesupport (= 5.2.5)
43
+ arel (>= 9.0)
44
+ activestorage (5.2.5)
45
+ actionpack (= 5.2.5)
46
+ activerecord (= 5.2.5)
47
+ marcel (~> 1.0.0)
48
+ activesupport (5.2.5)
49
+ concurrent-ruby (~> 1.0, >= 1.0.2)
50
+ i18n (>= 0.7, < 2)
51
+ minitest (~> 5.1)
52
+ tzinfo (~> 1.1)
53
+ arel (9.0.0)
54
+ ast (2.4.2)
55
+ builder (3.2.4)
56
+ coderay (1.1.3)
57
+ concurrent-ruby (1.1.8)
58
+ concurrent-ruby-edge (0.6.0)
59
+ concurrent-ruby (~> 1.1.6)
60
+ crass (1.0.6)
61
+ erubi (1.10.0)
62
+ globalid (0.4.2)
63
+ activesupport (>= 4.2.0)
64
+ i18n (1.8.10)
65
+ concurrent-ruby (~> 1.0)
66
+ loofah (2.9.1)
67
+ crass (~> 1.0.2)
68
+ nokogiri (>= 1.5.9)
69
+ magic_frozen_string_literal (1.2.0)
70
+ mail (2.7.1)
71
+ mini_mime (>= 0.1.1)
72
+ marcel (1.0.1)
73
+ method_source (0.9.2)
74
+ mini_mime (1.1.0)
75
+ minitest (5.14.4)
76
+ nio4r (2.5.7)
77
+ nokogiri (1.11.3-x86_64-linux)
78
+ racc (~> 1.4)
79
+ parallel (1.20.1)
80
+ parser (3.0.0.0)
81
+ ast (~> 2.4.1)
82
+ pry (0.12.2)
83
+ coderay (~> 1.1.0)
84
+ method_source (~> 0.9.0)
85
+ pry-nav (0.3.0)
86
+ pry (>= 0.9.10, < 0.13.0)
87
+ racc (1.5.2)
88
+ rack (2.2.3)
89
+ rack-test (1.1.0)
90
+ rack (>= 1.0, < 3)
91
+ rails (5.2.5)
92
+ actioncable (= 5.2.5)
93
+ actionmailer (= 5.2.5)
94
+ actionpack (= 5.2.5)
95
+ actionview (= 5.2.5)
96
+ activejob (= 5.2.5)
97
+ activemodel (= 5.2.5)
98
+ activerecord (= 5.2.5)
99
+ activestorage (= 5.2.5)
100
+ activesupport (= 5.2.5)
101
+ bundler (>= 1.3.0)
102
+ railties (= 5.2.5)
103
+ sprockets-rails (>= 2.0.0)
104
+ rails-dom-testing (2.0.3)
105
+ activesupport (>= 4.2.0)
106
+ nokogiri (>= 1.6)
107
+ rails-html-sanitizer (1.3.0)
108
+ loofah (~> 2.3)
109
+ railties (5.2.5)
110
+ actionpack (= 5.2.5)
111
+ activesupport (= 5.2.5)
112
+ method_source
113
+ rake (>= 0.8.7)
114
+ thor (>= 0.19.0, < 2.0)
115
+ rainbow (3.0.0)
116
+ rake (13.0.3)
117
+ regexp_parser (2.1.1)
118
+ rexml (3.2.4)
119
+ rubocop (1.11.0)
120
+ parallel (~> 1.10)
121
+ parser (>= 3.0.0.0)
122
+ rainbow (>= 2.2.2, < 4.0)
123
+ regexp_parser (>= 1.8, < 3.0)
124
+ rexml
125
+ rubocop-ast (>= 1.2.0, < 2.0)
126
+ ruby-progressbar (~> 1.7)
127
+ unicode-display_width (>= 1.4.0, < 3.0)
128
+ rubocop-ast (1.4.1)
129
+ parser (>= 2.7.1.5)
130
+ rubocop-performance (1.10.1)
131
+ rubocop (>= 0.90.0, < 2.0)
132
+ rubocop-ast (>= 0.4.0)
133
+ ruby-progressbar (1.11.0)
134
+ sprockets (4.0.2)
135
+ concurrent-ruby (~> 1.0)
136
+ rack (> 1, < 3)
137
+ sprockets-rails (3.2.2)
138
+ actionpack (>= 4.0)
139
+ activesupport (>= 4.0)
140
+ sprockets (>= 3.0.0)
141
+ standard (1.0.4)
142
+ rubocop (= 1.11.0)
143
+ rubocop-performance (= 1.10.1)
144
+ standardrb (1.0.0)
145
+ standard
146
+ thor (1.1.0)
147
+ thread_safe (0.3.6)
148
+ tzinfo (1.2.9)
149
+ thread_safe (~> 0.1)
150
+ unicode-display_width (2.0.0)
151
+ websocket-driver (0.7.3)
152
+ websocket-extensions (>= 0.1.0)
153
+ websocket-extensions (0.1.5)
154
+
155
+ PLATFORMS
156
+ x86_64-linux
157
+
158
+ DEPENDENCIES
159
+ chrono_trigger!
160
+ magic_frozen_string_literal (~> 1.2.0)
161
+ pry (~> 0.12.2)
162
+ pry-nav (~> 0.3.0)
163
+ rake (~> 13.0, >= 13.0.3)
164
+ standardrb (~> 1.0.0)
165
+
166
+ BUNDLED WITH
167
+ 2.2.3
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 leastbad
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,2 @@
1
+ # Initial page
2
+
data/Rakefile CHANGED
@@ -1,26 +1,4 @@
1
- # %w[rubygems rake rake/clean fileutils newgem rubigen rake/testtask].each { |f| require f }
2
- # require File.dirname(__FILE__) + '/lib/chrono_trigger'
1
+ # frozen_string_literal: true
3
2
 
4
- require 'rake/testtask'
5
-
6
- Rake::TestTask.new do |t|
7
- t.libs << 'test'
8
- end
9
-
10
- desc "Run tests"
11
- task :default => :test
12
-
13
- begin
14
- require 'jeweler'
15
- Jeweler::Tasks.new do |s|
16
- s.name = "chrono_trigger"
17
- s.authors = ["Jon Ciccone"]
18
- s.date = "2013-01-10"
19
- s.summary = "Rails cron jobs."
20
- s.description = "This gem allows you to write, deploy, and maintain cron jobs withing the rails framework."
21
- s.email = "darful@gmail.com"
22
- s.homepage = "https://github.com/darful/chrono_trigger"
23
- end
24
- rescue LoadError
25
- puts "Jeweler not available. Install it with: gem install technicalpickles-jeweler -s http://gems.github.com"
26
- end
3
+ require "bundler/gem_tasks"
4
+ require "pry"
data/SUMMARY.md ADDED
@@ -0,0 +1,4 @@
1
+ # Table of contents
2
+
3
+ * [Initial page](README.md)
4
+
data/bin/console ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "chrono_trigger"
5
+ require "pry"
6
+
7
+ Pry.start
data/bin/loc ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env bash
2
+
3
+ cloc --exclude-dir=node_modules,test --include-ext=rb,js .
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
data/bin/standardize ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env bash
2
+
3
+ bundle exec magic_frozen_string_literal
4
+ bundle exec standardrb --fix
@@ -1,14 +1,30 @@
1
- $:.unshift(File.dirname(__FILE__)) unless
2
- $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
1
+ # frozen_string_literal: true
3
2
 
4
- if RUBY_VERSION =~ /1\.8\.6/
5
- require "activerecord"
6
- else
7
- require "active_record"
8
- end
9
-
10
- require 'active_support/all'
3
+ require "rails/engine"
4
+ require "active_support/all"
5
+ require "singleton"
6
+ require "concurrent-edge"
7
+ require "chrono_trigger/clock"
8
+ require "chrono_trigger/config"
9
+ require "chrono_trigger/event"
10
+ require "chrono_trigger/schedule"
11
+ require "chrono_trigger/timeline"
11
12
  require "chrono_trigger/version"
12
- require "chrono_trigger/shell"
13
- require "chrono_trigger/trigger"
14
- require "chrono_trigger/cron_entry"
13
+ require "chrono_trigger/worker"
14
+
15
+ module ChronoTrigger
16
+ class Engine < Rails::Engine
17
+ end
18
+
19
+ def self.config
20
+ ChronoTrigger::Config.instance
21
+ end
22
+
23
+ def self.schedule
24
+ ChronoTrigger::Schedule.instance
25
+ end
26
+
27
+ def self.configure
28
+ yield config
29
+ end
30
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChronoTrigger
4
+ class Clock
5
+ class << self
6
+ attr_reader :status, :ticks
7
+
8
+ def init
9
+ @ticks = 0
10
+ @status ||= :stopped
11
+ end
12
+
13
+ def start
14
+ init
15
+ if stopped?
16
+ last_tick = Time.zone.now
17
+ Rails.logger.info "ChronoTrigger: Clock started with a #{ChronoTrigger.config.interval}s interval"
18
+ ChronoTrigger.schedule.refresh
19
+ task = Concurrent::TimerTask.new(execution_interval: ChronoTrigger.config.interval) do |task|
20
+ if Time.zone.now - last_tick >= 1
21
+ last_tick += 1
22
+ @ticks += 1
23
+ ChronoTrigger.schedule.process_events
24
+ end
25
+ task.shutdown if stopped?
26
+ end
27
+ task.execute
28
+ end
29
+
30
+ @status = :started
31
+ end
32
+
33
+ def stop
34
+ if ticking?
35
+ Rails.logger.info "ChronoTrigger: Timer stopped"
36
+ @status = :stopped
37
+ end
38
+ @status
39
+ end
40
+
41
+ def ticking?
42
+ @status == :started
43
+ end
44
+
45
+ def stopped?
46
+ @status == :stopped
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChronoTrigger
4
+ class Config
5
+ include Singleton
6
+ attr_accessor :interval
7
+
8
+ def initialize
9
+ @interval = 0.1
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChronoTrigger
4
+ class Event
5
+ class << self
6
+ def schedule(*args)
7
+ id = SecureRandom.uuid
8
+ options = OpenStruct.new(
9
+ id: id,
10
+ scope: @scope,
11
+ repeats: @repeats || 1,
12
+ every: @every || 1.second,
13
+ at: @at,
14
+ before: @before,
15
+ after: @after
16
+ )
17
+ new(options, args)
18
+ id
19
+ end
20
+
21
+ def scope(value)
22
+ return self unless value
23
+ @scope = value if value.is_a?(String)
24
+ @scope = value.to_gid.to_s if value.is_a?(ActiveRecord::Base)
25
+ self
26
+ end
27
+
28
+ def repeats(value)
29
+ return self unless value
30
+ @repeats = value.count if value.is_a?(Enumerator)
31
+ @repeats = value if value.is_a?(Integer) || value == :forever
32
+ self
33
+ end
34
+
35
+ def every(value)
36
+ return self unless value
37
+ @every = value if value.is_a?(ActiveSupport::Duration)
38
+ @every = value.seconds if value.is_a?(Integer)
39
+ self
40
+ end
41
+
42
+ def at(value)
43
+ return self unless value
44
+ value = Time.zone.parse(value) if value.is_a?(String)
45
+ @at = moment_in_the_future(value) if value.is_a?(ActiveSupport::TimeWithZone)
46
+ puts @at.class
47
+ self
48
+ end
49
+
50
+ def before(value)
51
+ return self unless value
52
+ value = Time.zone.parse(value) if value.is_a?(String)
53
+ @before = moment_in_the_future(value) if value.is_a?(ActiveSupport::TimeWithZone)
54
+ self
55
+ end
56
+
57
+ def after(value)
58
+ return self unless value
59
+ value = Time.zone.parse(value) if value.is_a?(String)
60
+ @after = moment_in_the_future(value) if value.is_a?(ActiveSupport::TimeWithZone)
61
+ self
62
+ end
63
+
64
+ private
65
+
66
+ def moment_in_the_future(time_with_zone)
67
+ Time.zone.today + time_with_zone.hour.hours + time_with_zone.min.minutes + time_with_zone.sec.seconds
68
+ end
69
+ end
70
+
71
+ class LostInTimeError < StandardError
72
+ end
73
+
74
+ class TodayIsTomorrowsYesterday < StandardError
75
+ end
76
+
77
+ attr_reader :id, :scope, :args, :every, :before, :after, :purge
78
+ attr_accessor :repeats, :at
79
+
80
+ def initialize(options, args)
81
+ @id = options.id
82
+ @scope = options.scope
83
+ @repeats = options.repeats
84
+ @every = options.every
85
+ @at = options.at
86
+ @before = options.before
87
+ @after = options.after
88
+ @args = args
89
+ @purge = false
90
+ ChronoTrigger.schedule.add(self)
91
+ end
92
+
93
+ def ticks
94
+ ChronoTrigger::Clock.ticks
95
+ end
96
+
97
+ def purge!
98
+ @purge = true
99
+ end
100
+
101
+ def right_now
102
+ now = Time.zone.now
103
+ Time.zone.today + now.hour.hours + now.min.minutes + now.sec.seconds
104
+ end
105
+
106
+ def moment_in_the_future(time_with_zone)
107
+ raise(LostInTimeError, "Argument must be of type ActiveSupport::TimeWithZone eg. right_now + 1.second") unless time_with_zone.is_a?(ActiveSupport::TimeWithZone)
108
+ raise(TodayIsTomorrowsYesterday, "Time must be in the future eg. 1.second.from_now") unless time_with_zone.future?
109
+ Time.zone.today + time_with_zone.hour.hours + time_with_zone.min.minutes + time_with_zone.sec.seconds
110
+ end
111
+
112
+ private
113
+
114
+ def perform(args)
115
+ raise NotImplementedError
116
+ end
117
+ end
118
+ end