stagger 0.1.1 → 0.2.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
  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: