redcache 0.0.2 → 0.0.3

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: 793fd19a398f38a5bcdc992bc217569fd2b9a198
4
- data.tar.gz: 68e67159b66834a941ae9d98b4f924237f29c74c
3
+ metadata.gz: b9134505b631ba6721ae691c4a9031dd3e62a551
4
+ data.tar.gz: f4a352cc66f24de9d52b8907f62b96d4aa413e91
5
5
  SHA512:
6
- metadata.gz: d0311ccbaf060b02bc5690426b7157779d3956aa0dd1ab9d2dca0ed58631011f9f6391300b8bee4767fc7c15482b2800db4e4afd572ddb68db253931d2f1a74c
7
- data.tar.gz: 11b2359e537853933c9dfd3502e5365e3d80801581f72572d2e00b611acdba9c510018e023bf2c67d8218769a184d916e5e502135f435667daa06890ec277213
6
+ metadata.gz: 04bb02ff0a7e38f07ccd7741edd113c0eb7e7b4c3c6cd10d2405a1ea03261caad59e6d7bacfa48b7b8a2a7c5cf242ef59673faee1d004657bbf08d8dfb6ac9dc
7
+ data.tar.gz: c1ff6af3a7bc067f2844440e4a33876d2a88f9d6c472caad29a78b3dfe3c01770e272c4038f0b4e740713eee162d442fe34d72d151d7c7a1f37ea94e018e85a8
@@ -6,6 +6,7 @@ module Redcache
6
6
  attr_accessor :stale_time
7
7
  attr_accessor :encrypt
8
8
  attr_accessor :skip_cache
9
+ attr_accessor :silent
9
10
  attr_accessor :logger
10
11
  attr_accessor :log_prefix
11
12
 
@@ -15,6 +16,7 @@ module Redcache
15
16
  @encrypt = false
16
17
  @secret = nil
17
18
  @skip_cache = false
19
+ @silent = false
18
20
  @logger = nil
19
21
  @log_prefix = "redcache"
20
22
  end
@@ -1,3 +1,3 @@
1
1
  module Redcache
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/redcache.rb CHANGED
@@ -1,6 +1,11 @@
1
1
  require "redcache/version"
2
+ require "fernet"
2
3
  require "redcache/configuration"
3
4
 
5
+ Fernet::Configuration.run do |config|
6
+ config.enforce_ttl = false
7
+ end
8
+
4
9
  module Redcache
5
10
  class << self
6
11
  attr_writer :configuration
@@ -10,15 +15,67 @@ module Redcache
10
15
  end
11
16
 
12
17
  def cache(redis_key, &block)
13
- return block.call if skip_cache?
14
- if redis_up?
15
- value = read_from_cache(redis_key, block) || write_into_cache(redis_key, block)
16
- return value unless value.nil?
17
- else
18
- block.call
18
+ # return immediately if we shouldn't or can't cache
19
+ return block.call if skip_cache? || !redis_up?
20
+ with_redis do
21
+ # attempt to read from cache, running and caching the block if cold
22
+ value = read_from_cache(redis_key, block)
23
+ if value.nil?
24
+ value = block.call if value.nil?
25
+ write_into_cache(redis_key, value)
26
+ end
27
+ return value
28
+ end
29
+ end
30
+
31
+ def read_from_cache(redis_key, block)
32
+ value = get_value(redis_key)
33
+ value.nil? ? log("cache.miss", redis_key) : log("cache.hit", redis_key)
34
+ refresh_cache(redis_key, block) if key_stale?(redis_key) && !value.nil?
35
+ return value
36
+ end
37
+
38
+ def refresh_cache(redis_key, block)
39
+ log("cache.stale_refresh", redis_key)
40
+ Thread.new do
41
+ write_into_cache(redis_key, block.call)
19
42
  end
20
43
  end
21
44
 
45
+ def write_into_cache(redis_key, value)
46
+ with_redis do
47
+ log("cache.write", redis_key)
48
+ set_value(redis_key, value)
49
+ end
50
+ value
51
+ end
52
+
53
+ def get_value(key)
54
+ decrypt redis.get(key)
55
+ end
56
+
57
+ def set_value(key, value)
58
+ redis.setex key, configuration.cache_time, encrypt(value)
59
+ end
60
+
61
+ def key_stale?(redis_key)
62
+ ttl = redis.ttl(redis_key)
63
+ return ttl < (configuration.cache_time - configuration.stale_time)
64
+ end
65
+
66
+ def encrypt(value)
67
+ return prep_value(value) unless encrypt?
68
+ fernet.generate(secret, prep_value(value))
69
+ end
70
+
71
+ def decrypt(value)
72
+ return nil if value.nil?
73
+ return value unless encrypt?
74
+ verifier = fernet.verifier(secret, value)
75
+ return MultiJson.load(verifier.message) if verifier.valid?
76
+ return nil
77
+ end
78
+
22
79
  def configuration
23
80
  @configuration ||= Configuration.new
24
81
  end
@@ -53,73 +110,32 @@ module Redcache
53
110
  configuration.skip_cache
54
111
  end
55
112
 
56
- def read_from_cache(redis_key, block)
57
- value = get_value(redis_key)
58
- value.nil? ? log("cache.miss", redis_key) : log("cache.hit", redis_key)
59
- refresh_cache(redis_key, block) if key_stale?(redis_key) && !value.nil?
60
- return value
61
- end
62
-
63
113
  def test?
64
114
  ENV["RACK_ENV"] == 'test'
65
115
  end
66
116
 
67
- def refresh_cache(redis_key, block)
68
- log("cache.stale_refresh", redis_key)
69
- Thread.new do
70
- write_into_cache(redis_key, block)
71
- end
72
- end
73
-
74
- def write_into_cache(redis_key, block)
75
- json = block.call
76
- with_redis do
77
- log("cache.write", redis_key)
78
- set_value(redis_key, json)
79
- end
80
- json
81
- end
82
-
83
- def key_stale?(redis_key)
84
- ttl = redis.ttl(redis_key)
85
- return ttl < (configuration.cache_time - configuration.stale_time)
86
- end
87
-
88
- def get_value(key)
89
- decrypt redis.get(key)
90
- end
91
-
92
- def set_value(key, value)
93
- redis.setex key, configuration.cache_time, encrypt(value)
94
- end
95
-
96
- def encrypt(value)
97
- return value unless encrypt?
98
- Fernet.generate(secret, MultiJson.encode(value))
117
+ def prep_value(value)
118
+ MultiJson.encode(value)
99
119
  end
100
120
 
101
121
  def encrypt?
102
122
  configuration.encrypt
103
123
  end
104
124
 
105
- def decrypt(value)
106
- return nil if value.nil?
107
- return value unless encrypt?
108
- verifier = Fernet.verifier(secret, value)
109
- return MultiJson.load(verifier.message) if verifier.valid?
110
- return nil
111
- end
112
-
113
125
  def secret
114
126
  configuration.secret
115
127
  end
116
128
 
117
129
  def log(str, key)
118
- configuration.logger.log(log_prefix(str) => 1, :key => key)
130
+ configuration.logger.log(log_prefix(str) => 1, :key => key) unless configuration.silent
119
131
  end
120
132
 
121
133
  def log_prefix(str)
122
134
  [configuration.log_prefix, str].join(".")
123
135
  end
136
+
137
+ def fernet
138
+ ::Fernet
139
+ end
124
140
  end
125
141
  end
@@ -1,8 +1,10 @@
1
1
  require 'spec_helper'
2
+ require 'fernet'
2
3
 
3
4
  Redcache.configure do |c|
4
5
  c.redis = Redis.new
5
6
  c.logger = Pliny
7
+ c.silent = true
6
8
  end
7
9
 
8
10
  class Dummy
@@ -18,46 +20,116 @@ class Dummy
18
20
  end
19
21
 
20
22
  describe Redcache do
23
+ let(:rc) { Redcache }
24
+ let(:config) { Redcache.configuration }
25
+
26
+ before do
27
+ allow(rc.fernet).to receive(:generate){ "abd" }
28
+ end
21
29
 
22
30
  context 'when skipping caching' do
23
31
  before do
24
- allow(Redcache.configuration).to receive(:skip_cache){true}
32
+ config.skip_cache = true
25
33
  end
34
+
26
35
  it 'does not use the cache' do
27
- expect(Redcache).to_not receive(:read_from_cache)
36
+ expect(rc).to_not receive(:read_from_cache)
28
37
  Dummy.run
29
38
  end
30
39
  end
31
40
 
32
41
  context 'when caching' do
33
42
  before do
34
- allow(Redcache.configuration).to receive(:skip_cache){false}
43
+ config.skip_cache = false
35
44
  end
36
45
 
37
46
  it 'uses the cached' do
38
- expect(Redcache).to receive(:read_from_cache){ {} }
47
+ expect(rc).to receive(:read_from_cache){ {} }
39
48
  Dummy.run
40
49
  end
41
50
 
42
51
  it 'triggers a cache write if the cache is cold' do
43
- allow(Redcache).to receive(:read_from_cache){ nil }
44
- expect(Redcache).to receive(:write_into_cache) { "" }
52
+ allow(rc).to receive(:read_from_cache){ nil }
53
+ expect(rc).to receive(:write_into_cache) { "" }
45
54
  Dummy.run
46
55
  end
47
56
 
48
57
  it 'skips cache when redis is down' do
49
- allow(Redcache).to receive(:redis_up?){ false }
50
- expect(Redcache).to_not receive(:read_from_cache)
58
+ allow(rc).to receive(:redis_up?){ false }
59
+ expect(rc).to_not receive(:read_from_cache)
51
60
  expect(Dummy).to receive(:get_value)
52
61
  Dummy.run
53
62
  end
54
63
 
55
64
  it 'triggers a cache refresh with a stale warm cache' do
56
- allow(Redcache).to receive(:key_stale?){ true }
57
- allow(Redcache).to receive(:get_value){ "" }
58
- expect(Redcache).to receive(:refresh_cache).once
65
+ allow(rc).to receive(:key_stale?){ true }
66
+ allow(rc).to receive(:get_value){ "" }
67
+ expect(rc).to receive(:refresh_cache).once
59
68
  Dummy.run
60
69
  end
61
70
  end
62
71
 
72
+ describe 'configuration' do
73
+ it 'respects cache_time' do
74
+ config.cache_time = 100
75
+ expect(rc.cache_time).to eq(100)
76
+ end
77
+
78
+ it 'respects stale_time' do
79
+ config.stale_time = 100
80
+ expect(rc.stale_time).to eq(100)
81
+ end
82
+
83
+ it 'respects skip_cache' do
84
+ config.skip_cache = true
85
+ expect(rc.skip_cache?).to eq(true)
86
+ end
87
+
88
+ it 'knows the secret' do
89
+ config.secret = "bar"
90
+ expect(rc.secret).to eq("bar")
91
+ end
92
+ end
93
+
94
+ it 'knows when a key is stale' do
95
+ config.cache_time = 100
96
+ config.stale_time = 10
97
+ allow(rc.redis).to receive(:ttl){ 80 }
98
+ expect(rc.key_stale?("foo")).to eq(true)
99
+
100
+ allow(rc.redis).to receive(:ttl){ 91 }
101
+ expect(rc.key_stale?("foo")).to eq(false)
102
+ end
103
+
104
+ it 'can refresh the cache' do
105
+ p = Proc.new {}
106
+ expect(Thread).to receive(:new)
107
+ rc.refresh_cache("foo", p)
108
+ end
109
+
110
+ it 'can write into the cache' do
111
+ p = Proc.new { "" }
112
+ expect(rc).to receive(:set_value).with("foo", "")
113
+ rc.write_into_cache("foo", p.call)
114
+ end
115
+
116
+ it 'can get a value' do
117
+ expect(rc.redis).to receive(:get).with("foo"){ "bar" }
118
+ expect(rc).to receive(:decrypt).with("bar")
119
+ rc.get_value("foo")
120
+ end
121
+
122
+ it 'can set a value' do
123
+ config.cache_time = 100
124
+ config.encrypt = false
125
+ expect(rc.redis).to receive(:setex).with("foo", 100, '"bar"')
126
+ rc.set_value("foo", "bar")
127
+ end
128
+
129
+ it 'encrypts' do
130
+ config.encrypt = true
131
+ config.secret = "foo"
132
+ expect(rc.fernet).to receive(:generate).with("foo", '"bar"'){ "abc" }
133
+ rc.encrypt("bar")
134
+ end
63
135
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redcache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Neil Middleton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-05 00:00:00.000000000 Z
11
+ date: 2014-10-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler