stagger 0.1.1 → 0.2.0

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: aea07a97eb08adfb0b987354b8146f2178595f7a
4
- data.tar.gz: e2afd6e33044f41c77075429e71f0cb447c3a42f
3
+ metadata.gz: f219ca29cb8639825bccec42c9f37267e80609d0
4
+ data.tar.gz: 5d61f7cdecbe5ead509e5d933959cc071215d4de
5
5
  SHA512:
6
- metadata.gz: 543a5bc36e6b6c59224d3cd8f14075e4874d88ab7bbfe99989ec8114ffcd9cdd8ad4fc9d5924e72fd14efbcf264890e2cb723e6306285797d4dd0bd000fd542c
7
- data.tar.gz: d0942f54379748f62cb77dc54e8e72347ba3467631195d3ea86f4681e8f4696ef1a50e547197f9a06142f997dbfcda1e66c8533c1477f0d5c6959adbb53c8de2
6
+ metadata.gz: a8607c7cc1731e7dbf0d90d4de769ab7339b494a14a518cb2ffe186a5cb605e1f702be938a39ac118a9a96c9edead217c827b4f90931f649f8099ada01e8f9e2
7
+ data.tar.gz: 7343e17149e12f843eb5be374cd7fb64b99f1355ee3180ebdebce24b7b99deef18d9b4dc16dab25f81c43cdc1e91f489984e03e3b59682a8366a393b20046610
data/.hound.yml ADDED
@@ -0,0 +1,2 @@
1
+ ruby:
2
+ enabled: true
data/README.md CHANGED
@@ -9,7 +9,10 @@ days.
9
9
  On the surface, this tasks seems simple, but when you have a lot of
10
10
  tasks,
11
11
  that should be scheduled across business days, that span several weeks,
12
- it gets complicated. Stagger has good test coverage, I covered all cases
12
+ it gets complicated. When you have both plain ruby `Time` and
13
+ `ActiveSupport::TimeWithZone`, it gets even more hairy.
14
+
15
+ Stagger has good test coverage, I covered all cases
13
16
  I could think of with specs.
14
17
 
15
18
  Stagger has no runtime dependencies.
@@ -24,12 +27,22 @@ emails = get_emails()
24
27
  schedule = Stagger.distribute(emails, 14)
25
28
  ```
26
29
 
27
- Schedule one item to be sent as soon as possible but on business day only:
30
+ Schedule one item to be sent as soon as possible but on a business day only:
28
31
 
29
32
  ```ruby
30
33
  email = get_email() # only one email
31
34
  schedule = Stagger.distribute([email], 1) # i.e. distribute across 1
32
35
  business day
36
+
37
+ Schedule one item to be sent after a delay of 5 minutes, but on a business day only:
38
+
39
+ ```ruby
40
+ email = get_email() # only one email
41
+ # specify delay in seconds
42
+ schedule = Stagger.distribute([email], 1, delay: 5 * 60) # i.e. distribute across 1
43
+ business day
44
+ ```
45
+
33
46
  ```
34
47
 
35
48
  Schedule 1000 emails to be sent across next 30 business days:
@@ -59,9 +72,20 @@ But when `ActiveSupport` is available, it returns instances of rails'
59
72
  In other words, you don't need to do anything when using this gem with
60
73
  Rails.
61
74
 
75
+ ## Options
76
+
77
+ ### Delay
78
+
79
+ Specified in seconds, default is 0.
80
+ Will make the first and subsequent items to be shifted ahead in time.
81
+ Useful to make for scenarios when first item w/out an initial delay will
82
+ have been in the past by the time the processing logic will pick it up.
83
+ If the delay makes the first item to be scheduled on a weekend, it will
84
+ be sent on Monday at 00 hours.
85
+
62
86
  ## Plans
63
87
 
64
- Plans to add support for holidays / initial delay and working hours in the future.**
88
+ Plans to add support for holidays and working hours in the future.**
65
89
 
66
90
 
67
91
  ## Installation
data/lib/stagger.rb CHANGED
@@ -3,9 +3,14 @@ require "stagger/version"
3
3
  module Stagger
4
4
  SECONDS_IN_DAY = 86_400
5
5
  class << self
6
- def distribute(items, number_of_days)
6
+ # Evenly distributes items acros business days
7
+ # @param [Array, items] items to stagger
8
+ # @param [Integer, number_of_days] number of business days to distribute within
9
+ # @param [Integer, delay] number of seconds to delay the staggering
10
+ # @return [Array] array of arrays, where first subarray element is a scheduled DateTime, second is the staggered item
11
+ def distribute(items, number_of_days, delay: 0)
7
12
  return [] if Array(items).empty? || number_of_days.to_i < 1
8
- time = get_starting_time
13
+ time = get_starting_time(delay)
9
14
  period_in_seconds = get_period_in_seconds(items.size, number_of_days, time)
10
15
  items.reduce [] do |arr, item|
11
16
  if business_day?(time)
@@ -29,8 +34,8 @@ module Stagger
29
34
  end
30
35
  end
31
36
 
32
- def get_starting_time
33
- tc = current_time
37
+ def get_starting_time(delay)
38
+ tc = current_time + delay
34
39
  if tc.saturday?
35
40
  at_beginning_of_day(tc) + SECONDS_IN_DAY * 2
36
41
  elsif tc.sunday?
@@ -1,3 +1,3 @@
1
1
  module Stagger
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
data/spec/stagger_spec.rb CHANGED
@@ -47,6 +47,24 @@ RSpec.describe Stagger do
47
47
  end
48
48
  end
49
49
 
50
+ it 'schedules to run after a delay if today is a business day' do
51
+ t = Time.local(2014, 6, 27, 18) # 6pm, Friday
52
+ Timecop.freeze(t) do
53
+ # stagger after a delay of 5 minutes
54
+ pair = Stagger.distribute([1], 1, delay: 300).first
55
+ expect(pair.last).to eq Time.local(2014, 6, 27, 18, 5)
56
+ end
57
+ end
58
+
59
+ it 'schedules to run after a big delay that spans over the weekend' do
60
+ t = Time.local(2014, 6, 27, 18) # 6pm, Friday
61
+ Timecop.freeze(t) do
62
+ # stagger after a delay of 72 hours
63
+ pair = Stagger.distribute([1], 1, delay: 72 * 60 * 60).first
64
+ expect(pair.last).to eq Time.local(2014, 6, 30, 18)
65
+ end
66
+ end
67
+
50
68
  it 'schedules immediately if today is a business day and number of days > 1' do
51
69
  # a dumb test, actually, but I need to cover it
52
70
  t = Time.local(2014, 6, 27, 18) # 6pm, Friday
@@ -56,6 +74,33 @@ RSpec.describe Stagger do
56
74
  end
57
75
  end
58
76
 
77
+ it 'schedules to run after a delay if today is a business day and number of days > 1' do
78
+ t = Time.local(2014, 6, 27, 18) # 6pm, Friday
79
+ Timecop.freeze(t) do
80
+ # stagger after a delay of 5 minutes
81
+ pair = Stagger.distribute([1], 2, delay: 300).first
82
+ expect(pair.last).to eq Time.local(2014, 6, 27, 18, 5)
83
+ end
84
+ end
85
+
86
+ it 'schedules to run on Monday business day if delay will schedule the first item run on Saturday' do
87
+ t = Time.local(2014, 6, 27, 18) # 6pm, Friday
88
+ Timecop.freeze(t) do
89
+ # stagger after a delay of 7 hours
90
+ pair = Stagger.distribute([1], 1, delay: 7 * 60 * 60).first
91
+ expect(pair.last).to eq Time.local(2014, 6, 30) # Midnight, Monday
92
+ end
93
+ end
94
+
95
+ it 'schedules to run on Monday business day if delay will schedule the first item run on Sunday' do
96
+ t = Time.local(2014, 6, 27, 18) # 6pm, Friday
97
+ Timecop.freeze(t) do
98
+ # stagger after a delay of 31 hours (1 in the morning of Sunday)
99
+ pair = Stagger.distribute([1], 1, delay: 31 * 60 * 60).first
100
+ expect(pair.last).to eq Time.local(2014, 6, 30) # Midnight, Monday
101
+ end
102
+ end
103
+
59
104
  it 'schedules to run on Monday (00:00) if today is Sunday' do
60
105
  t = Time.local(2014, 6, 29, 14) # - 2pm, Sunday
61
106
  Timecop.freeze(t) do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stagger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Valentin Vasilyev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-01 00:00:00.000000000 Z
11
+ date: 2014-10-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -116,6 +116,7 @@ extensions: []
116
116
  extra_rdoc_files: []
117
117
  files:
118
118
  - ".gitignore"
119
+ - ".hound.yml"
119
120
  - ".rspec"
120
121
  - ".travis.yml"
121
122
  - Gemfile
@@ -147,11 +148,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
148
  version: '0'
148
149
  requirements: []
149
150
  rubyforge_project:
150
- rubygems_version: 2.3.0
151
+ rubygems_version: 2.2.2
151
152
  signing_key:
152
153
  specification_version: 4
153
154
  summary: Gem evenly distributes items across business days
154
155
  test_files:
155
156
  - spec/spec_helper.rb
156
157
  - spec/stagger_spec.rb
157
- has_rdoc: