time_scheduler 1.0.2 → 1.1.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
  SHA256:
3
- metadata.gz: 9dd3e563565d592dbc78bad3a0c306fa85817dad4b17a615147c04c0daca0fa0
4
- data.tar.gz: 324db4ac4818cf66de0f31922f5478892ce510caa791dd904158a2639256d91d
3
+ metadata.gz: 0e58dc40f89e8573c41d5817583a7146d359d70077761dbbe92fadd6eb8096b3
4
+ data.tar.gz: 73d28d42cea43c9b96fae6c65b3d032ad2f4c29c5e00396b245e40cf4f872229
5
5
  SHA512:
6
- metadata.gz: 125b52b655af7eedb23216fd870d19a1a52575afd112efff44636e299b134c31b45b31bb2056f8bc0596fdc6a18df538e3cbb2c97e9beba0fd7510c3159433a7
7
- data.tar.gz: 50f132d18ea8faa5cf0bdf7da4e1e65642b13182e0501c3bd1c5a4a071a970bf6395c48010d8648f031b89045cccab56d9ec69dde0290a9afe41b2d3e5aeb312
6
+ metadata.gz: 469f48427b2a4dc21d4ce6a52f6d744274befe725cad72f79e5996c459419b0c9c4f30d3dcabc5926e012e41f95df4197978c4b7d77b0767b21fee7428edbeef
7
+ data.tar.gz: 560d58d6fc0ad2e8f54e50df8ceacd0839f37c85a86dab3de68cb3d99660cc74d13d2d8f70494012cb51f12bed5c4dda994d30fb86ea1bf517ece3280cc48638
@@ -2,6 +2,15 @@
2
2
 
3
3
  Yet another library for single/periodical event scheduler.
4
4
 
5
+ == Features
6
+
7
+ * A thread based scheduler that runs once or periodically at a specified datetime.
8
+ * The condition is specified by a format such as crontab or by keyword argument.
9
+ * Time can be specified in less than 1 second. However, the behavior depends on the environment.
10
+ * Suspend/resume function.
11
+ * Function to change the datetime conditions during execution.
12
+ * Runs only once within the specified timelimit.
13
+
5
14
  == Installation
6
15
 
7
16
  Add this line to your application's Gemfile:
@@ -78,6 +87,28 @@ end
78
87
  sleep
79
88
  ----
80
89
 
90
+ === Example 3
91
+
92
+ [source,ruby]
93
+ ----
94
+ require "time_scheduler"
95
+
96
+ Scheduler = TimeScheduler.new
97
+
98
+ (0..4).each do
99
+ p [Time.now.iso8601(3), :cycle]
100
+ Scheduler.first_only( timeout: 10 ) do
101
+ p [Time.now.iso8601(3), :first]
102
+ end
103
+ Scheduler.last_only( timeout: 10 ) do
104
+ p [Time.now.iso8601(3), :last]
105
+ end
106
+ sleep 1
107
+ end
108
+
109
+ sleep
110
+ ----
111
+
81
112
  == Reference
82
113
 
83
114
  === Create a new TimeScheduler.
@@ -98,7 +129,8 @@ TimeScheduler.new
98
129
  [source,ruby]
99
130
  ----
100
131
  TimeScheduler#wait( topic = Time.now.iso8601(6),
101
- at: nil, cron: nil, year: nil, month: nil, day: nil, wday: nil, hour: nil, min: nil, sec: 0, msec: nil,
132
+ at: nil, cron: nil, year: nil, month: nil, day: nil, wday: nil,
133
+ hour: nil, min: nil, sec: 0, msec: nil,
102
134
  &block )
103
135
  ----
104
136
 
@@ -121,6 +153,7 @@ TimeScheduler#wait( topic = Time.now.iso8601(6),
121
153
  ** sec: second. 0..59. (default: 0)
122
154
  ** msec: millisecond. 0..999. (default: nil), If msec is assigned, then other parameters are ignored.
123
155
  In detail, it can use "*" as wildcard.
156
+ ** block: Contents to be executed at a datetime that match the condition.
124
157
 
125
158
  * Block Parameter:
126
159
  ** time: event time. time object.
@@ -190,6 +223,40 @@ TimeScheduler#resume
190
223
  * Parameter:
191
224
  ** none.
192
225
 
226
+ === Invoke the block only once at the beginning, and ignoring recalls within the time limit.
227
+
228
+ [source,ruby]
229
+ ----
230
+ TimeScheduler#first_only( ident = nil, timeout: 1, &block )
231
+ ----
232
+
233
+ * Result:
234
+ ** nil.
235
+
236
+ * Parameter:
237
+ ** ident: Additional Identifier.
238
+ ** timeout: Monitoring time limit (sec).
239
+
240
+ * Block Parameter:
241
+ ** none.
242
+
243
+ === When there is no recall within the time limit, invoke the block only once at the end.
244
+
245
+ [source,ruby]
246
+ ----
247
+ TimeScheduler#last_only( ident = nil, timeout: 1, &block )
248
+ ----
249
+
250
+ * Result:
251
+ ** nil.
252
+
253
+ * Parameter:
254
+ ** ident: Additional Identifier.
255
+ ** timeout: Monitoring time limit (sec).
256
+
257
+ * Block Parameter:
258
+ ** none.
259
+
193
260
  == Caution
194
261
 
195
262
  Because it is calculated in local time, it does not work as expected when switching to daylight saving time.
@@ -201,3 +268,5 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/arimay
201
268
  == License
202
269
 
203
270
  The gem is available as open source under the terms of the http://opensource.org/licenses/MIT[MIT License].
271
+
272
+ Copyright (c) ARIMA Yasuhiro <arima.yasuhiro@gmail.com>
@@ -2,6 +2,15 @@
2
2
 
3
3
  一度の/周期的なイベントスケジューラのライブラリのひとつ。
4
4
 
5
+ == 特徴
6
+
7
+ * 条件指定された日時に一度だけまたは周期的に動作するスレッドベースのスケジューラ.
8
+ * 条件は crontab のような書式や、キーワード引数で指定する.
9
+ * 時刻は1秒未満で指定することが可能. ただし、挙動は環境依存.
10
+ * 一時停止/再開機能.
11
+ * 実行中の日時条件変更機能.
12
+ * 指定された制限時間内に一度だけ実行する.
13
+
5
14
  == 導入
6
15
 
7
16
  アプリの Gemfile にこの行を追加
@@ -78,6 +87,28 @@ end
78
87
  sleep
79
88
  ----
80
89
 
90
+ === Example 3
91
+
92
+ [source,ruby]
93
+ ----
94
+ require "time_scheduler"
95
+
96
+ Scheduler = TimeScheduler.new
97
+
98
+ (0..4).each do
99
+ p [Time.now.iso8601(3), :cycle]
100
+ Scheduler.first_only( timeout: 10 ) do
101
+ p [Time.now.iso8601(3), :first]
102
+ end
103
+ Scheduler.last_only( timeout: 10 ) do
104
+ p [Time.now.iso8601(3), :last]
105
+ end
106
+ sleep 1
107
+ end
108
+
109
+ sleep
110
+ ----
111
+
81
112
  == リファレンス
82
113
 
83
114
  === 新たな TimeScheduler を作成する.
@@ -98,7 +129,8 @@ TimeScheduler.new
98
129
  [source,ruby]
99
130
  ----
100
131
  TimeScheduler#wait( topic = Time.now.iso8601(6),
101
- at: nil, cron: nil, year: nil, month: nil, day: nil, wday: nil, hour: nil, min: nil, sec: 0, msec: nil,
132
+ at: nil, cron: nil, year: nil, month: nil, day: nil, wday: nil,
133
+ hour: nil, min: nil, sec: 0, msec: nil,
102
134
  &block )
103
135
  ----
104
136
 
@@ -121,6 +153,7 @@ TimeScheduler#wait( topic = Time.now.iso8601(6),
121
153
  ** sec: 秒. 0..59. (default: 0)
122
154
  ** msec: ミリ秒. 0..999. (default: nil), ミリ秒が指定されたとき, 他のパラメータは無視される.
123
155
  詳細では, ワイルドカードとして "*" を使用できる.
156
+ ** block: 条件に適合する日時に実行する内容.
124
157
 
125
158
  * Block Parameter:
126
159
  ** time: イベント日時. Time オブジェクト.
@@ -190,6 +223,40 @@ TimeScheduler#resume
190
223
  * Parameter:
191
224
  ** なし.
192
225
 
226
+ === 最初に一度だけブロックを呼び出して、制限時間内の再呼び出しは無視する.
227
+
228
+ [source,ruby]
229
+ ----
230
+ TimeScheduler#first_only( ident = nil, timeout: 1, &block )
231
+ ----
232
+
233
+ * Result:
234
+ ** nil.
235
+
236
+ * Parameter:
237
+ ** ident: 追加識別子.
238
+ ** timeout: 監視時間制限(秒).
239
+
240
+ * Block Parameter:
241
+ ** なし.
242
+
243
+ === 制限時間内に再呼び出しがないとき、最後に一度だけブロックを呼び出す.
244
+
245
+ [source,ruby]
246
+ ----
247
+ TimeScheduler#last_only( ident = nil, timeout: 1, &block )
248
+ ----
249
+
250
+ * Result:
251
+ ** nil.
252
+
253
+ * Parameter:
254
+ ** ident: 追加識別子.
255
+ ** timeout: 監視時間制限(秒).
256
+
257
+ * Block Parameter:
258
+ ** なし.
259
+
193
260
  == 注意
194
261
 
195
262
  地域時刻で計算しているため、夏時間の切り替わりにおいて期待しない挙動となる.
@@ -201,3 +268,5 @@ TimeScheduler#resume
201
268
  == ライセンス
202
269
 
203
270
  この Gem は、 http://opensource.org/licenses/MIT[MITライセンス] の条件に基づいてオープンソースとして入手できる.
271
+
272
+ Copyright (c) ARIMA Yasuhiro <arima.yasuhiro@gmail.com>
data/Rakefile CHANGED
@@ -8,12 +8,12 @@ task :default => :spec
8
8
 
9
9
  class Bundler::GemHelper
10
10
 
11
- def git_archive( dir = "../#{Time.now.strftime("%Y%m%d")}" )
11
+ def git_archive( dir = "../zip" )
12
12
  FileUtils.mkdir_p dir
13
13
  dest_path = File.join(dir, "#{name}-#{version}.zip")
14
14
  cmnd = "git archive --format zip --prefix=#{name}/ HEAD > #{dest_path}"
15
15
 
16
- out, code = sh_with_status( cmnd )
16
+ _, code = sh_with_status( cmnd )
17
17
  raise "Couldn't archive gem," unless code == 0
18
18
 
19
19
  Bundler.ui.confirm "#{name} #{version} archived to #{dest_path}."
@@ -23,11 +23,11 @@ class Bundler::GemHelper
23
23
  ver = version.to_s
24
24
 
25
25
  cmnd = "git push origin #{ver} "
26
- out, code = sh_with_status( cmnd )
26
+ _, code = sh_with_status( cmnd )
27
27
  raise "Couldn't git push origin." unless code == 0
28
28
 
29
29
  cmnd = "git push "
30
- out, code = sh_with_status( cmnd )
30
+ _, code = sh_with_status( cmnd )
31
31
  raise "Couldn't git push." unless code == 0
32
32
 
33
33
  Bundler.ui.confirm "Git Push #{ver}."
@@ -43,15 +43,15 @@ class Bundler::GemHelper
43
43
  end
44
44
 
45
45
  cmnd = "git add #{version_pathname} "
46
- out, code = sh_with_status( cmnd )
46
+ _, code = sh_with_status( cmnd )
47
47
  raise "Couldn't git add," unless code == 0
48
48
 
49
49
  cmnd = "git commit -m '#{new_version}' "
50
- out, code = sh_with_status( cmnd )
50
+ _, code = sh_with_status( cmnd )
51
51
  raise "Couldn't git commit." unless code == 0
52
52
 
53
53
  cmnd = "git tag #{new_version} "
54
- out, code = sh_with_status( cmnd )
54
+ _, code = sh_with_status( cmnd )
55
55
  raise "Couldn't git tag." unless code == 0
56
56
 
57
57
  Bundler.ui.confirm "Update Tags to #{new_version}."
@@ -80,14 +80,14 @@ Bundler::GemHelper.new(Dir.pwd).instance_eval do
80
80
 
81
81
  desc "Update Version Minor"
82
82
  task 'minor' do
83
- major, minor, tiny = version.to_s.split('.')
83
+ major, minor, _tiny = version.to_s.split('.')
84
84
  new_version = [major, minor.to_i + 1, 0].join('.')
85
85
  update_version( new_version )
86
86
  end
87
87
 
88
88
  desc "Update Version Major"
89
89
  task 'major' do
90
- major, minor, tiny = version.to_s.split('.')
90
+ major, _minor, _tiny = version.to_s.split('.')
91
91
  new_version = [major.to_i + 1, 0, 0].join('.')
92
92
  update_version( new_version )
93
93
  end
@@ -179,7 +179,35 @@ class TimeScheduler
179
179
  end
180
180
  end
181
181
 
182
+ class Counter
183
+ def initialize
184
+ @count = 0
185
+ @mutex = Mutex.new
186
+ end
187
+
188
+ def incr
189
+ @mutex.synchronize do
190
+ @count += 1
191
+ end
192
+ end
193
+
194
+ def decr
195
+ @mutex.synchronize do
196
+ @count -= 1 if @count > 0
197
+ @count
198
+ end
199
+ end
200
+
201
+ def reset
202
+ @mutex.synchronize do
203
+ @count = 0
204
+ end
205
+ end
206
+ end
207
+
182
208
  def initialize
209
+ @first_counter = Hash.new{|h,k| h[k] = Counter.new }
210
+ @last_counter = Hash.new{|h,k| h[k] = Counter.new }
183
211
  end
184
212
 
185
213
  def scheduler
@@ -222,5 +250,25 @@ class TimeScheduler
222
250
  TimeScheduler::Schedule.resume
223
251
  end
224
252
 
253
+ def first_only( ident = nil, timeout: 1, &block )
254
+ key = [ caller[0], ident.to_s ].join(":")
255
+ count = @first_counter[key].incr
256
+ block.call if count == 1
257
+ ::Thread.start( key ) do |key|
258
+ ::Kernel.sleep timeout
259
+ @first_counter[key].decr
260
+ end
261
+ end
262
+
263
+ def last_only( ident = nil, timeout: 1, &block )
264
+ key = [ caller[0], ident.to_s ].join(":")
265
+ @last_counter[key].incr
266
+ ::Thread.start( key ) do |key|
267
+ ::Kernel.sleep timeout
268
+ count = @last_counter[key].decr
269
+ block.call if count == 0
270
+ end
271
+ end
272
+
225
273
  end
226
274
 
@@ -1,3 +1,3 @@
1
1
  class TimeScheduler
2
- VERSION = "1.0.2"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -0,0 +1,17 @@
1
+ require "time_scheduler"
2
+
3
+ Scheduler = TimeScheduler.new
4
+
5
+ (0..4).each do
6
+ p [Time.now.iso8601(3), :cycle]
7
+ Scheduler.first_only( timeout: 10 ) do
8
+ p [Time.now.iso8601(3), :first]
9
+ end
10
+ Scheduler.last_only( timeout: 10 ) do
11
+ p [Time.now.iso8601(3), :last]
12
+ end
13
+ sleep 1
14
+ end
15
+
16
+ Scheduler.wait( at: Time.now + 10 )
17
+ p [Time.now.iso8601(3), :quit]
@@ -11,9 +11,8 @@ Gem::Specification.new do |spec|
11
11
  spec.summary = %q{ Library for simple event scheduler. }
12
12
  spec.description = %q{ Yet another library for single/periodical event scheduler. }
13
13
  spec.homepage = "https://github.com/arimay/time_scheduler"
14
+ spec.license = "MIT"
14
15
 
15
- # Specify which files should be added to the gem when it is released.
16
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
17
16
  spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
18
17
  `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
19
18
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: time_scheduler
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - arimay
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-18 00:00:00.000000000 Z
11
+ date: 2020-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: time_cursor
@@ -88,9 +88,11 @@ files:
88
88
  - sample/base_e.rb
89
89
  - sample/base_f.rb
90
90
  - sample/base_g.rb
91
+ - sample/base_h.rb
91
92
  - time_scheduler.gemspec
92
93
  homepage: https://github.com/arimay/time_scheduler
93
- licenses: []
94
+ licenses:
95
+ - MIT
94
96
  metadata: {}
95
97
  post_install_message:
96
98
  rdoc_options: []