readthis 0.8.1 → 1.2.1

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.
@@ -1,4 +1,4 @@
1
- require 'readthis/cache'
1
+ require 'readthis'
2
2
 
3
3
  RSpec.describe Readthis::Cache do
4
4
  let(:cache) { Readthis::Cache.new }
@@ -8,18 +8,6 @@ RSpec.describe Readthis::Cache do
8
8
  end
9
9
 
10
10
  describe '#initialize' do
11
- it 'accepts and persists a namespace' do
12
- cache = Readthis::Cache.new(namespace: 'kash')
13
-
14
- expect(cache.namespace).to eq('kash')
15
- end
16
-
17
- it 'accepts and persists an expiration' do
18
- cache = Readthis::Cache.new(expires_in: 10)
19
-
20
- expect(cache.expires_in).to eq(10)
21
- end
22
-
23
11
  it 'makes options available' do
24
12
  cache = Readthis::Cache.new(namespace: 'cache', expires_in: 1)
25
13
 
@@ -60,11 +48,16 @@ RSpec.describe Readthis::Cache do
60
48
  end
61
49
 
62
50
  it 'uses a custom expiration' do
63
- cache.write('some-key', 'some-value', expires_in: 1)
51
+ cache = Readthis::Cache.new(namespace: 'cache', expires_in: 86_400)
52
+
53
+ cache.write('some-key', 'some-value')
54
+ cache.write('other-key', 'other-value', expires_in: 1)
64
55
 
65
56
  expect(cache.read('some-key')).not_to be_nil
57
+ expect(cache.read('other-key')).not_to be_nil
66
58
  sleep 1.01
67
- expect(cache.read('some-key')).to be_nil
59
+ expect(cache.read('some-key')).not_to be_nil
60
+ expect(cache.read('other-key')).to be_nil
68
61
  end
69
62
 
70
63
  it 'expands non-string keys' do
@@ -82,19 +75,52 @@ RSpec.describe Readthis::Cache do
82
75
  end
83
76
  end
84
77
 
78
+ describe 'serializers' do
79
+ after do
80
+ Readthis.serializers.reset!
81
+ end
82
+
83
+ it 'uses globally configured serializers' do
84
+ custom = Class.new do
85
+ def self.dump(value)
86
+ value
87
+ end
88
+
89
+ def self.load(value)
90
+ value
91
+ end
92
+ end
93
+
94
+ Readthis.serializers << custom
95
+
96
+ cache.write('customized', 'some value', marshal: custom)
97
+
98
+ expect(cache.read('customized')).to eq('some value')
99
+ end
100
+ end
101
+
85
102
  describe 'compression' do
86
- it 'round trips entries when compression is enabled' do
103
+ it 'roundtrips entries when compression is enabled' do
87
104
  com_cache = Readthis::Cache.new(compress: true, compression_threshold: 8)
88
105
  raw_cache = Readthis::Cache.new
89
106
  value = 'enough text that it should be compressed'
90
107
 
91
108
  com_cache.write('compressed', value)
92
109
 
93
- expect(raw_cache.read('compressed')).not_to eq(value)
94
110
  expect(com_cache.read('compressed')).to eq(value)
111
+ expect(raw_cache.read('compressed')).to eq(value)
112
+ end
113
+
114
+ it 'roundtrips entries with option overrides' do
115
+ cache = Readthis::Cache.new(compress: false)
116
+ value = 'enough text that it should be compressed'
117
+
118
+ cache.write('comp-round', value, marshal: JSON, compress: true, threshold: 8)
119
+
120
+ expect(cache.read('comp-round')).to eq(value)
95
121
  end
96
122
 
97
- it 'round trips bulk entries when compression is enabled' do
123
+ it 'roundtrips bulk entries when compression is enabled' do
98
124
  cache = Readthis::Cache.new(compress: true, compression_threshold: 8)
99
125
  value = 'also enough text to compress'
100
126
 
@@ -135,6 +161,21 @@ RSpec.describe Readthis::Cache do
135
161
 
136
162
  expect(cache.read('short-key')).to eq('other stuff')
137
163
  end
164
+
165
+ it 'gets an existing value when `options` are passed as nil' do
166
+ cache.write('great-key', 'great')
167
+ expect(cache.fetch('great-key', nil)).to eq('great')
168
+ end
169
+
170
+ it 'serves computed content when the cache is down and tolerance is enabled' do
171
+ Readthis.fault_tolerant = true
172
+
173
+ allow(cache.pool).to receive(:with).and_raise(Redis::CannotConnectError)
174
+
175
+ computed = cache.fetch('error-key') { 'computed' }
176
+
177
+ expect(computed).to eq('computed')
178
+ end
138
179
  end
139
180
 
140
181
  describe '#read_multi' do
@@ -146,7 +187,7 @@ RSpec.describe Readthis::Cache do
146
187
  expect(cache.read_multi('a', 'b', 'c')).to eq(
147
188
  'a' => 1,
148
189
  'b' => 2,
149
- 'c' => '3',
190
+ 'c' => '3'
150
191
  )
151
192
  end
152
193
 
@@ -156,7 +197,7 @@ RSpec.describe Readthis::Cache do
156
197
 
157
198
  expect(cache.read_multi('d', 'e', namespace: 'cache')).to eq(
158
199
  'd' => 1,
159
- 'e' => 2,
200
+ 'e' => 2
160
201
  )
161
202
  end
162
203
 
@@ -175,7 +216,11 @@ RSpec.describe Readthis::Cache do
175
216
  end
176
217
 
177
218
  it 'respects passed options' do
178
- cache.write_multi({ 'a' => 1, 'b' => 2 }, namespace: 'multi', expires_in: 1)
219
+ cache.write_multi(
220
+ { 'a' => 1, 'b' => 2 },
221
+ namespace: 'multi',
222
+ expires_in: 1
223
+ )
179
224
 
180
225
  expect(cache.read('a')).to be_nil
181
226
  expect(cache.read('a', namespace: 'multi')).to eq(1)
@@ -194,7 +239,7 @@ RSpec.describe Readthis::Cache do
194
239
  expect(results).to eq(
195
240
  'a' => 1,
196
241
  'b' => 'bb',
197
- 'c' => 3,
242
+ 'c' => 3
198
243
  )
199
244
 
200
245
  expect(cache.read('b')).to eq('bb')
@@ -266,4 +311,27 @@ RSpec.describe Readthis::Cache do
266
311
  expect(cache.decrement('unknown')).to eq(-1)
267
312
  end
268
313
  end
314
+
315
+ describe 'instrumentation' do
316
+ it 'instruments cache invokations' do
317
+ require 'active_support/notifications'
318
+
319
+ notes = ActiveSupport::Notifications
320
+ cache = Readthis::Cache.new
321
+ events = []
322
+
323
+ notes.subscribe(/cache_*/) do |*args|
324
+ events << ActiveSupport::Notifications::Event.new(*args)
325
+ end
326
+
327
+ cache.write('a', 'a')
328
+ cache.read('a')
329
+
330
+ expect(events.length).to eq(2)
331
+ expect(events.map(&:name)).to eq(%w[
332
+ cache_write.active_support
333
+ cache_read.active_support
334
+ ])
335
+ end
336
+ end
269
337
  end
@@ -1,4 +1,4 @@
1
- require 'readthis/entity'
1
+ require 'readthis'
2
2
  require 'json'
3
3
 
4
4
  RSpec.describe Readthis::Entity do
@@ -7,14 +7,21 @@ RSpec.describe Readthis::Entity do
7
7
  string = 'some string'
8
8
  entity = Readthis::Entity.new
9
9
 
10
- expect(entity.dump(string)).to eq(Marshal.dump(string))
10
+ expect(entity.dump(string)).to include(Marshal.dump(string))
11
11
  end
12
12
 
13
13
  it 'marshals using a custom marshaller' do
14
14
  string = 'some string'
15
15
  entity = Readthis::Entity.new(marshal: JSON)
16
16
 
17
- expect(entity.dump(string)).to eq(JSON.dump(string))
17
+ expect(entity.dump(string)).to include(JSON.dump(string))
18
+ end
19
+
20
+ it 'overrides the marshaller' do
21
+ string = 'still some string'
22
+ entity = Readthis::Entity.new
23
+
24
+ expect(entity.dump(string, marshal: JSON)).to include(JSON.dump(string))
18
25
  end
19
26
 
20
27
  it 'applies compression when enabled' do
@@ -39,6 +46,22 @@ RSpec.describe Readthis::Entity do
39
46
  expect(entity.load(string)).to eq(string)
40
47
  end
41
48
 
49
+ it 'overrides the compression threshold' do
50
+ string = 'a' * 8
51
+ entity = Readthis::Entity.new(compress: true, threshold: 2)
52
+ dumped = entity.dump(string)
53
+
54
+ expect(entity.dump(string, threshold: 100)).not_to eq(dumped)
55
+ end
56
+
57
+ it 'overrides the compression option' do
58
+ string = 'a' * 8
59
+ entity = Readthis::Entity.new(compress: true, threshold: 2)
60
+ dumped = entity.dump(string)
61
+
62
+ expect(entity.dump(string, compress: false)).not_to eq(dumped)
63
+ end
64
+
42
65
  it 'safely roundtrips nil values' do
43
66
  entity = Readthis::Entity.new
44
67
 
@@ -49,26 +72,27 @@ RSpec.describe Readthis::Entity do
49
72
  describe '#load' do
50
73
  it 'unmarshals a value' do
51
74
  object = { a: 1, b: '2' }
52
- dumped = Marshal.dump(object)
53
75
  entity = Readthis::Entity.new
76
+ dumped = entity.dump(object)
54
77
 
55
78
  expect(entity.load(dumped)).to eq(object)
56
79
  end
57
80
 
58
81
  it 'uncompresses when compression is enabled' do
59
82
  string = 'another one of those huge strings'
60
- entity = Readthis::Entity.new(compress: true, threshold: 0)
61
- dumped = Marshal.dump(string)
62
-
63
- compressed = entity.compress(dumped)
83
+ entity = Readthis::Entity.new(compress: true, threshold: 4)
84
+ dumped = entity.dump(dumped)
64
85
 
65
- expect(entity.load(compressed)).not_to eq(string)
86
+ expect(entity.load(dumped)).not_to eq(string)
66
87
  end
67
88
 
68
- it 'does not try to load a nil value' do
69
- entity = Readthis::Entity.new
89
+ it 'uses the dumped value to define load options' do
90
+ value = [1, 2, 3]
91
+ custom = Readthis::Entity.new(marshal: JSON, compress: true)
92
+ general = Readthis::Entity.new(marshal: Marshal, compress: false)
93
+ dumped = custom.dump(value)
70
94
 
71
- expect(entity.load(nil)).to be_nil
95
+ expect(general.load(dumped)).to eq(value)
72
96
  end
73
97
 
74
98
  it 'passes through the value when it fails to marshal' do
@@ -84,4 +108,37 @@ RSpec.describe Readthis::Entity do
84
108
  expect { entity.load(dumped) }.not_to raise_error
85
109
  end
86
110
  end
111
+
112
+ describe '#compose' do
113
+ it 'prepends the string with a formatted marker' do
114
+ string = 'the quick brown fox'
115
+ marked = Readthis::Entity.new.compose(string, Marshal, true)
116
+
117
+ expect(marked[0]).not_to eq('t')
118
+ end
119
+ end
120
+
121
+ describe '#decompose' do
122
+ it 'returns extracted options and values' do
123
+ string = 'the quick brown fox'
124
+ entity = Readthis::Entity.new
125
+ marked = entity.compose(string.dup, JSON, true)
126
+
127
+ marshal, compress, value = entity.decompose(marked)
128
+
129
+ expect(marshal).to eq(JSON)
130
+ expect(compress).to eq(true)
131
+ expect(value).to eq(string)
132
+ end
133
+
134
+ it 'returns the original string without a marker' do
135
+ string = 'the quick brown fox'
136
+ entity = Readthis::Entity.new
137
+ marshal, compress, value = entity.decompose(string)
138
+
139
+ expect(marshal).to eq(Marshal)
140
+ expect(compress).to eq(false)
141
+ expect(value).to eq(string)
142
+ end
143
+ end
87
144
  end
@@ -19,7 +19,7 @@ RSpec.describe Readthis::Expanders do
19
19
  it 'expands an array of objects' do
20
20
  object = double(cache_key: 'gamma')
21
21
 
22
- expect(expand(['alpha', 'beta'])).to eq('alpha/beta')
22
+ expect(expand(%w[alpha beta])).to eq('alpha/beta')
23
23
  expect(expand([object, object])).to eq('gamma/gamma')
24
24
  end
25
25
 
@@ -0,0 +1,87 @@
1
+ require 'readthis/serializers'
2
+
3
+ RSpec.describe Readthis::Serializers do
4
+ CustomSerializer = Class.new
5
+ AnotherSerializer = Class.new
6
+
7
+ describe '#<<' do
8
+ it 'appends new serializers' do
9
+ serializers = Readthis::Serializers.new
10
+
11
+ serializers << CustomSerializer
12
+
13
+ expect(serializers.marshals).to include(CustomSerializer)
14
+ expect(serializers.flags).to eq([1, 2, 3, 4])
15
+ end
16
+
17
+ it 'increments flags' do
18
+ serializers = Readthis::Serializers.new
19
+ serializers << CustomSerializer
20
+ serializers << AnotherSerializer
21
+
22
+ expect(serializers.flags).to eq((1..5).to_a)
23
+ end
24
+
25
+ it 'prevents more than seven serializers' do
26
+ serializers = Readthis::Serializers.new
27
+
28
+ expect do
29
+ 10.times { serializers << Class.new }
30
+ end.to raise_error(Readthis::SerializersLimitError)
31
+ end
32
+ end
33
+
34
+ describe '#assoc' do
35
+ it 'looks up serializers by module' do
36
+ serializers = Readthis::Serializers.new
37
+
38
+ expect(serializers.assoc(Marshal)).to eq(0x1)
39
+ end
40
+
41
+ it 'raises a helpful error when the serializer is unknown' do
42
+ serializers = Readthis::Serializers.new
43
+
44
+ expect do
45
+ serializers.assoc(CustomSerializer)
46
+ end.to raise_error(Readthis::UnknownSerializerError)
47
+ end
48
+ end
49
+
50
+ describe '#rassoc' do
51
+ it 'inverts the current set of serializers' do
52
+ serializers = Readthis::Serializers.new
53
+
54
+ expect(serializers.rassoc(1)).to eq(Marshal)
55
+ end
56
+
57
+ it 'returns custom serializers' do
58
+ serializers = Readthis::Serializers.new
59
+ serializers << CustomSerializer
60
+
61
+ expect(serializers.rassoc(4)).to eq(CustomSerializer)
62
+ end
63
+ end
64
+
65
+ describe '#freeze!' do
66
+ it 'does now allow appending after freeze' do
67
+ serializers = Readthis::Serializers.new
68
+
69
+ serializers.freeze!
70
+
71
+ expect do
72
+ serializers << CustomSerializer
73
+ end.to raise_error(Readthis::SerializersFrozenError)
74
+ end
75
+ end
76
+
77
+ describe '#reset!' do
78
+ it 'reverts back to the original set of serializers' do
79
+ serializers = Readthis::Serializers.new
80
+
81
+ serializers << Class.new
82
+ serializers.reset!
83
+
84
+ expect(serializers.serializers.length).to eq(3)
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,21 @@
1
+ require 'readthis'
2
+
3
+ RSpec.describe Readthis do
4
+ describe '#serializers' do
5
+ it 'lists currently configured serializers' do
6
+ expect(Readthis.serializers.marshals).to include(Marshal, JSON)
7
+ end
8
+ end
9
+
10
+ describe '#fault_tolerant?' do
11
+ it 'defaults to being false' do
12
+ expect(Readthis).not_to be_fault_tolerant
13
+ end
14
+
15
+ it 'can be enabled' do
16
+ Readthis.fault_tolerant = true
17
+
18
+ expect(Readthis).to be_fault_tolerant
19
+ end
20
+ end
21
+ end
data/spec/spec_helper.rb CHANGED
@@ -16,10 +16,12 @@ RSpec.configure do |config|
16
16
 
17
17
  config.disable_monkey_patching!
18
18
 
19
- if config.files_to_run.one?
20
- config.default_formatter = 'doc'
21
- end
19
+ config.default_formatter = 'doc' if config.files_to_run.one?
22
20
 
23
21
  config.order = :random
24
22
  Kernel.srand config.seed
23
+
24
+ config.before do
25
+ Readthis.reset!
26
+ end
25
27
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: readthis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.1
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Parker Selbert
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-04 00:00:00.000000000 Z
11
+ date: 2016-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: redis
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">"
46
+ - !ruby/object:Gem::Version
47
+ version: '4.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">"
53
+ - !ruby/object:Gem::Version
54
+ version: '4.0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: bundler
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -94,44 +108,29 @@ dependencies:
94
108
  - - "~>"
95
109
  - !ruby/object:Gem::Version
96
110
  version: '3.1'
97
- description: Pooled active support compliant caching with redis
111
+ description:
98
112
  email:
99
113
  - parker@sorentwo.com
100
114
  executables: []
101
115
  extensions: []
102
116
  extra_rdoc_files: []
103
117
  files:
104
- - ".gitignore"
105
- - ".rspec"
106
- - ".travis.yml"
107
- - CHANGELOG.md
108
- - CONTRIBUTING.md
109
- - Gemfile
110
- - LICENSE.txt
111
- - PERFORMANCE.md
112
118
  - README.md
113
- - Rakefile
114
- - benchmarks/compressed.rb
115
- - benchmarks/driver.rb
116
- - benchmarks/marshalling.rb
117
- - benchmarks/memory.rb
118
- - benchmarks/multi.rb
119
- - benchmarks/profile.rb
120
- - bin/rspec
121
119
  - lib/active_support/cache/readthis_store.rb
122
120
  - lib/readthis.rb
123
121
  - lib/readthis/cache.rb
124
122
  - lib/readthis/entity.rb
123
+ - lib/readthis/errors.rb
125
124
  - lib/readthis/expanders.rb
126
- - lib/readthis/notifications.rb
127
125
  - lib/readthis/passthrough.rb
126
+ - lib/readthis/serializers.rb
128
127
  - lib/readthis/version.rb
129
- - readthis.gemspec
130
128
  - spec/readthis/cache_spec.rb
131
129
  - spec/readthis/entity_spec.rb
132
130
  - spec/readthis/expanders_spec.rb
133
- - spec/readthis/notifications_spec.rb
134
131
  - spec/readthis/passthrough_spec.rb
132
+ - spec/readthis/serializers_spec.rb
133
+ - spec/readthis_spec.rb
135
134
  - spec/spec_helper.rb
136
135
  homepage: https://github.com/sorentwo/readthis
137
136
  licenses:
@@ -153,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
153
152
  version: '0'
154
153
  requirements: []
155
154
  rubyforge_project:
156
- rubygems_version: 2.4.5
155
+ rubygems_version: 2.5.1
157
156
  signing_key:
158
157
  specification_version: 4
159
158
  summary: Pooled active support compliant caching with redis
@@ -161,6 +160,7 @@ test_files:
161
160
  - spec/readthis/cache_spec.rb
162
161
  - spec/readthis/entity_spec.rb
163
162
  - spec/readthis/expanders_spec.rb
164
- - spec/readthis/notifications_spec.rb
165
163
  - spec/readthis/passthrough_spec.rb
164
+ - spec/readthis/serializers_spec.rb
165
+ - spec/readthis_spec.rb
166
166
  - spec/spec_helper.rb
data/.gitignore DELETED
@@ -1,15 +0,0 @@
1
- /.bundle/
2
- /.yardoc
3
- /Gemfile.lock
4
- /_yardoc/
5
- /coverage/
6
- /doc/
7
- /pkg/
8
- /spec/reports/
9
- /tmp/
10
- *.bundle
11
- *.so
12
- *.o
13
- *.a
14
- mkmf.log
15
- TODO
data/.rspec DELETED
@@ -1,2 +0,0 @@
1
- --color
2
- --require spec_helper
data/.travis.yml DELETED
@@ -1,15 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.1.0
5
- - 2.2.2
6
- - ruby-head
7
- - rbx-2
8
- matrix:
9
- allow_failures:
10
- - rvm: ruby-head
11
- - rvm: rbx-2
12
- services:
13
- - redis-server
14
- script: bin/rspec
15
- bundler_args: --without benchmarking