lita-timing 0.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 +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +56 -0
- data/lib/lita-timing.rb +2 -0
- data/lib/lita/timing/rate_limit.rb +22 -0
- data/lib/lita/timing/sliding_window.rb +41 -0
- metadata +107 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 96f734b887a989426e7d3bfda449f1e050b164eb
|
4
|
+
data.tar.gz: 60797820ff5fb0aa13053a4da02a3bfdca2ef182
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 70952579da7d3d7ed7a09e90c495d8bf873517800269876894e92bfff7ada11ab3dc28e0115fc0d2c23905bd868e38db6567d882992e8e918abcc9181f0f5026
|
7
|
+
data.tar.gz: f054f0913f9cb4b957bc90801a8b2d30de070a11160d5e035ec5d0b52a2be4c8f91808448f4bda6d64601700d57519e51228b66e19bb5e6c12a8126f8d809b63
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2016 James Healy
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# lita-timing
|
2
|
+
|
3
|
+
A small collection of utility classes that make it easier to work with time, recurring
|
4
|
+
events and rate limits in lita.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this gem to your lita installation by including the following line in your Gemfile:
|
9
|
+
|
10
|
+
gem "lita-timing"
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
This gem is not a lita handler or plugin in its own right, but it is easily used
|
15
|
+
by other lita plugins.
|
16
|
+
|
17
|
+
### Rate Limits
|
18
|
+
|
19
|
+
lita comes with an "every" helper that executes a block of code at fixed
|
20
|
+
intervals. However the interval is only stored in memory, which means
|
21
|
+
long intervals will often be reset if the lita process restarts (like
|
22
|
+
during a deploy).
|
23
|
+
|
24
|
+
For handlers that want to execute code at fixed intervals, the RateLimit
|
25
|
+
class can be used in conjunction with the built in every() helper:
|
26
|
+
|
27
|
+
one_minute = 60
|
28
|
+
one_week = 60 + 60 + 24 + 7
|
29
|
+
every(one_minute) do
|
30
|
+
RateLimit.new("interval-name", redis).once_every(one_week) do
|
31
|
+
# weekly code in here
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
### Sliding Windows
|
36
|
+
|
37
|
+
Sometimes a handler wants to periodically execute a block of code with a start
|
38
|
+
and end time, and ensure that every minute of the day is handled by one of the
|
39
|
+
executions. The text-book use case is polling an external API for updates within
|
40
|
+
a time range.
|
41
|
+
|
42
|
+
The SlidingWindow class can help. For best results, use it in conjunction with the
|
43
|
+
built in every() helper.
|
44
|
+
|
45
|
+
Redis is used to persist the end of the last window that executed and ensure the
|
46
|
+
block doesn't execute again until that window is passed.
|
47
|
+
|
48
|
+
window = SlidingWindow.new("my-sliding-window", redis)
|
49
|
+
every(one_minute) do
|
50
|
+
window.advance(duration_minutes: 30) do |window_start, window_end|
|
51
|
+
puts "#{window_start} -> #{window_end}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
Call this as often as you like, and the block passed to advance() will
|
56
|
+
only execute if it's been 30 minutes since the last time it executed.
|
data/lib/lita-timing.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Lita
|
2
|
+
module Timing
|
3
|
+
class RateLimit
|
4
|
+
def initialize(name, redis)
|
5
|
+
@name, @redis = name, redis
|
6
|
+
end
|
7
|
+
|
8
|
+
def once_every(seconds, &block)
|
9
|
+
if last_time.nil? || last_time + seconds < Time.now
|
10
|
+
yield
|
11
|
+
@redis.set(@name, Time.now.to_i)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def last_time
|
16
|
+
value = @redis.get(@name)
|
17
|
+
value ? Time.at(value.to_i).utc : nil
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Lita
|
2
|
+
module Timing
|
3
|
+
class SlidingWindow
|
4
|
+
def initialize(name, redis)
|
5
|
+
@name, @redis = name, redis
|
6
|
+
|
7
|
+
initialise_last_time_if_not_set
|
8
|
+
end
|
9
|
+
|
10
|
+
def advance(duration_minutes: 30, buffer_minutes: 0, &block)
|
11
|
+
start_time = Time.now - mins_to_seconds(duration_minutes) - mins_to_seconds(buffer_minutes)
|
12
|
+
advance_to = start_time + mins_to_seconds(duration_minutes)
|
13
|
+
|
14
|
+
return unless start_time > last_time
|
15
|
+
|
16
|
+
yield last_time, advance_to
|
17
|
+
|
18
|
+
@redis.set(@name, advance_to.to_i)
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def mins_to_seconds(mins)
|
24
|
+
mins * 60
|
25
|
+
end
|
26
|
+
|
27
|
+
def last_time
|
28
|
+
Time.at(@redis.get(@name).to_i)
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialise_last_time_if_not_set
|
32
|
+
@redis.setnx(@name, two_weeks_ago.to_i)
|
33
|
+
end
|
34
|
+
|
35
|
+
def two_weeks_ago
|
36
|
+
::Time.now - (60 * 60 * 24 * 14)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
metadata
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lita-timing
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- James Healy
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-06-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rspec
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.4'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.4'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
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: rdoc
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: Provides utilities that help with repeating tasks and rate limits
|
70
|
+
email:
|
71
|
+
- james.healy@theconversation.edu.au
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files:
|
75
|
+
- README.md
|
76
|
+
- MIT-LICENSE
|
77
|
+
files:
|
78
|
+
- MIT-LICENSE
|
79
|
+
- README.md
|
80
|
+
- lib/lita-timing.rb
|
81
|
+
- lib/lita/timing/rate_limit.rb
|
82
|
+
- lib/lita/timing/sliding_window.rb
|
83
|
+
homepage: http://github.com/yob/lita-timing
|
84
|
+
licenses:
|
85
|
+
- MIT
|
86
|
+
metadata: {}
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: 1.9.3
|
96
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
requirements: []
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 2.5.1
|
104
|
+
signing_key:
|
105
|
+
specification_version: 4
|
106
|
+
summary: Utilities for time related tasks in lita
|
107
|
+
test_files: []
|