retained 0.2.3 → 0.3.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: 73e354c2a489016a3d1c873e021d8f1b58a18dd2
4
- data.tar.gz: 84dc43a781952b4a5b6d97584e1fff0d7ff77665
3
+ metadata.gz: ca84fa50ba4a030bab29edbe18ff45345aff78f7
4
+ data.tar.gz: ae826caf63c1b345aad1c1938320d3e410416393
5
5
  SHA512:
6
- metadata.gz: 2939b0bf01bfd76a12106ad70b87c57885b9a80d27b6cac0e7ae28fabebc02efec4e8fba4dab704421c68104f7280d06a147c89dc64106868a535bc237fdf75c
7
- data.tar.gz: de8476c725c0db2dfeb7335309a42e3524ddf857a1ec43efd6e7f573160f357adca06edb3636c0ac3f83539bffadcac91c4c2d614e631243196a945bc2e6279c
6
+ metadata.gz: ae5a327d375d7b3770ca897dfb76771842ef9fa39be8ee7915c920f57f2cb2b538800cba211f6c0fd5742c8babf7193b30ab27565dc064e1d93aab1c12304f34
7
+ data.tar.gz: ae0cffa2a5020e55a21878889b546ed733f3f3d0bf144a87658a7e6ade076a935227404db67c961a111595dabc294d690e1d5ba6b0a3903b224be8f9961694e2
data/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # 0.3.0
2
+
3
+ * BREAKING CHANGE: Removed dependency on redis-bitops, which
4
+ while conserving space resulted in significant degradation of
5
+ performance due to the additional overhead of tracking chunks
6
+ and additional bit operations.
7
+
1
8
  # 0.2.3
2
9
 
3
10
  * Updated to latest redis-bitops, which includes multiple fixes
data/Gemfile CHANGED
@@ -1,7 +1,6 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
3
  gem 'redis', '~> 3.1.0'
4
- gem 'redis-bitops', github: 'msaffitz/redis-bitops', ref: '2ebd12b5044046db67e7958eda0701257b3eb3f9'
5
4
  gem 'activesupport'
6
5
 
7
6
  group :development do
data/Gemfile.lock CHANGED
@@ -1,11 +1,3 @@
1
- GIT
2
- remote: git://github.com/msaffitz/redis-bitops.git
3
- revision: 2ebd12b5044046db67e7958eda0701257b3eb3f9
4
- ref: 2ebd12b5044046db67e7958eda0701257b3eb3f9
5
- specs:
6
- redis-bitops (0.2.1)
7
- redis
8
-
9
1
  GEM
10
2
  remote: http://rubygems.org/
11
3
  specs:
@@ -84,7 +76,6 @@ DEPENDENCIES
84
76
  minitest
85
77
  rdoc (~> 3.12)
86
78
  redis (~> 3.1.0)
87
- redis-bitops!
88
79
  simplecov
89
80
  timecop (~> 0.7.1)
90
81
  yard (~> 0.7)
@@ -1,5 +1,6 @@
1
- require 'redis/bitops'
1
+ require 'redis'
2
2
  require 'active_support/core_ext/time/calculations'
3
+ require 'securerandom'
3
4
  require 'retained/configuration'
4
5
 
5
6
  module Retained
@@ -18,29 +19,31 @@ module Retained
18
19
  # is provided.
19
20
  def retain(entity, group: 'default', period: Time.now)
20
21
  index = entity_index(entity, group)
21
- bitmap = config.redis_connection.sparse_bitmap(key_period(group, period))
22
- bitmap[index] = true
22
+ config.redis_connection.setbit key_period(group, period), index, 1
23
23
  end
24
24
 
25
25
  # Total active entities in the period, or now if no period,
26
26
  # is provided.
27
27
  def total_active(group: 'default', period: Time.now)
28
- bitmap = config.redis_connection.sparse_bitmap(key_period(group, period))
29
- bitmap.bitcount
28
+ config.redis_connection.bitcount key_period(group, period)
30
29
  end
31
30
 
32
31
  # Returns the total number of unique active entities between
33
32
  # the start and end periods (inclusive), or now if no stop
34
33
  # period is provided.
35
34
  def unique_active(group: 'default', start:, stop: Time.now)
36
- bitmaps = []
35
+ keys = []
37
36
  start = period_start(group, start)
38
37
  while (start <= stop)
39
- bitmaps << config.redis_connection.sparse_bitmap(key_period(group, start))
38
+ keys << key_period(group, start)
40
39
  start += seconds_in_reporting_interval(config.group(group).reporting_interval)
41
40
  end
42
- return 0 if bitmaps.length == 0
43
- bitmaps.inject { |uniques,bitmap| uniques | bitmap }.bitcount
41
+ return 0 if keys.length == 0
42
+
43
+ temp_bitmap do |key|
44
+ config.redis_connection.bitop 'OR', key, *keys
45
+ config.redis_connection.bitcount key
46
+ end
44
47
  end
45
48
 
46
49
  # Returns true if the entity was active in the given period,
@@ -51,9 +54,7 @@ module Retained
51
54
  group = groups if group == [] || !group
52
55
 
53
56
  group.to_a.each do |g|
54
- bitmap = config.redis_connection.sparse_bitmap(key_period(g, period))
55
- index = entity_index(entity, g)
56
- return bitmap[index] if bitmap[index]
57
+ return true if config.redis_connection.getbit(key_period(g, period), entity_index(entity, g)) == 1
57
58
  end
58
59
  false
59
60
  end
@@ -88,6 +89,15 @@ LUA
88
89
  end
89
90
 
90
91
  private
92
+ def temp_bitmap
93
+ temp_key = "#{config.prefix}:temp:#{SecureRandom.hex}"
94
+ begin
95
+ yield temp_key
96
+ ensure
97
+ config.redis_connection.del temp_key
98
+ end
99
+ end
100
+
91
101
  # Returns the time (UTC) that the period starts at for the given group
92
102
  def period_start(group, period)
93
103
  period.utc.send("beginning_of_#{config.group(group).reporting_interval}")
@@ -1,8 +1,8 @@
1
1
  module Retained
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 2
5
- PATCH = 3
4
+ MINOR = 3
5
+ PATCH = 0
6
6
  BUILD = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
data/retained.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: retained 0.2.3 ruby lib
5
+ # stub: retained 0.3.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "retained"
9
- s.version = "0.2.3"
9
+ s.version = "0.3.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["Mike Saffitz"]
14
- s.date = "2014-11-16"
14
+ s.date = "2015-01-23"
15
15
  s.description = "\n Easy tracking of activity and retention at scale in daily, hourly, or minute intervals\n using sparse Redis bitmaps.\n "
16
16
  s.email = "m@saffitz.com"
17
17
  s.extra_rdoc_files = [
@@ -48,7 +48,6 @@ Gem::Specification.new do |s|
48
48
 
49
49
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
50
50
  s.add_runtime_dependency(%q<redis>, ["~> 3.1.0"])
51
- s.add_runtime_dependency(%q<redis-bitops>, [">= 0"])
52
51
  s.add_runtime_dependency(%q<activesupport>, [">= 0"])
53
52
  s.add_development_dependency(%q<minitest>, [">= 0"])
54
53
  s.add_development_dependency(%q<yard>, ["~> 0.7"])
@@ -59,7 +58,6 @@ Gem::Specification.new do |s|
59
58
  s.add_development_dependency(%q<timecop>, ["~> 0.7.1"])
60
59
  else
61
60
  s.add_dependency(%q<redis>, ["~> 3.1.0"])
62
- s.add_dependency(%q<redis-bitops>, [">= 0"])
63
61
  s.add_dependency(%q<activesupport>, [">= 0"])
64
62
  s.add_dependency(%q<minitest>, [">= 0"])
65
63
  s.add_dependency(%q<yard>, ["~> 0.7"])
@@ -71,7 +69,6 @@ Gem::Specification.new do |s|
71
69
  end
72
70
  else
73
71
  s.add_dependency(%q<redis>, ["~> 3.1.0"])
74
- s.add_dependency(%q<redis-bitops>, [">= 0"])
75
72
  s.add_dependency(%q<activesupport>, [">= 0"])
76
73
  s.add_dependency(%q<minitest>, [">= 0"])
77
74
  s.add_dependency(%q<yard>, ["~> 0.7"])
data/test/tracker_spec.rb CHANGED
@@ -15,10 +15,10 @@ describe Retained::Tracker do
15
15
 
16
16
  it 'retain tracks using the default group in the current period' do
17
17
  Timecop.freeze(Time.new(2014, 8, 29, 9, 03, 35)) do
18
- tracker.retain('entity_a')
18
+ tracker.retain('entity_a')
19
19
  prefix = tracker.config.prefix
20
20
  group = tracker.config.default_group
21
- tracker.config.redis_connection.sparse_bitmap("#{prefix}:#{group}:1409328000")[0]
21
+ tracker.active?('entity_a').must_equal true
22
22
  end
23
23
  end
24
24
 
@@ -27,7 +27,7 @@ describe Retained::Tracker do
27
27
  tracker.retain('entity_a', group: 'group_a', period: period)
28
28
 
29
29
  prefix = tracker.config.prefix
30
- tracker.config.redis_connection.sparse_bitmap("#{prefix}:group_a:1409356800")[0]
30
+ tracker.active?('entity_a', period: period).must_equal true
31
31
  end
32
32
 
33
33
  it 'retains using the "default" group' do
@@ -40,7 +40,7 @@ describe Retained::Tracker do
40
40
  tracker.retain('entity_a', group: 'group_a')
41
41
 
42
42
  prefix = tracker.config.prefix
43
- tracker.config.redis_connection.sparse_bitmap("#{prefix}:group_a:1409328000")[0]
43
+ tracker.active?('entity_a', group: 'group_a', period: Time.now).must_equal true
44
44
  end
45
45
  end
46
46
 
@@ -162,4 +162,32 @@ describe Retained::Tracker do
162
162
  tracker.key_period('minute', Time.new(2014, 8, 30, 10, 35, 47, 5*3600)).must_equal 'retained:minute:1409376900'
163
163
  tracker.key_period('day', Time.new(2014, 8, 30, 10, 35, 47, -2*3600)).must_equal 'retained:day:1409356800'
164
164
  end
165
+
166
+ it 'temp_bitmap cleans up the temporary bitmap' do
167
+ tmp_key = nil
168
+ tracker.send(:temp_bitmap) do |key|
169
+ tmp_key = key
170
+ tracker.config.redis_connection.setbit key, 0, 1
171
+ end
172
+ tracker.config.redis_connection.exists(tmp_key).must_equal false
173
+ end
174
+
175
+ it 'temp_bitmap cleans up the temporary bitmap with exception raised' do
176
+ tmp_key = nil
177
+ begin
178
+ tracker.send(:temp_bitmap) do |key|
179
+ tmp_key = key
180
+ tracker.config.redis_connection.setbit key, 0, 1
181
+ raise 'exception'
182
+ end
183
+ rescue
184
+ end
185
+ tracker.config.redis_connection.exists(tmp_key).must_equal false
186
+ end
187
+
188
+ it 'temp_bitmap returns the value' do
189
+ tracker.send(:temp_bitmap) do |key|
190
+ 4
191
+ end.must_equal 4
192
+ end
165
193
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: retained
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Saffitz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-16 00:00:00.000000000 Z
11
+ date: 2015-01-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 3.1.0
27
- - !ruby/object:Gem::Dependency
28
- name: redis-bitops
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: activesupport
43
29
  requirement: !ruby/object:Gem::Requirement