lock_and_cache_msgpack 4.0.7.pre1
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 +7 -0
- data/CHANGELOG +215 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +68 -0
- data/LICENSE.txt +23 -0
- data/README.md +236 -0
- data/Rakefile +9 -0
- data/benchmarks/allowed_in_keys.rb +87 -0
- data/lib/lock_and_cache_msgpack.rb +164 -0
- data/lib/lock_and_cache_msgpack/action.rb +109 -0
- data/lib/lock_and_cache_msgpack/key.rb +135 -0
- data/lib/lock_and_cache_msgpack/version.rb +3 -0
- data/lib/messagepack_ext.rb +16 -0
- data/lock_and_cache_msgpack.gemspec +34 -0
- data/spec/lock_and_cache/key_spec.rb +65 -0
- data/spec/lock_and_cache_spec.rb +476 -0
- data/spec/spec_helper.rb +11 -0
- metadata +220 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 221660e4bbdfdf8d620d9623503e2e1f503052cf
|
4
|
+
data.tar.gz: 496b11c457fa396fad2a702049737b33b28b0c1d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3a6e2422232cd578907be08ce3e4e480856245799dbdb746174fc5e489007fc96e68133f76b93a1a63cd4f78b142a52f217506b6c4a511cdb5881c8944d7541a
|
7
|
+
data.tar.gz: 5cccb26f41913573aadd2ebeee600c5aba51bec366b565c43faff5fa3ecdf73f3fe1a6a9dd17e8016956fa4ae823a62731c742a80cb182cb8e6b41b2ae84dc04
|
data/CHANGELOG
ADDED
@@ -0,0 +1,215 @@
|
|
1
|
+
4.0.6
|
2
|
+
|
3
|
+
* ?
|
4
|
+
|
5
|
+
* Don't test on ruby 2.1
|
6
|
+
|
7
|
+
* Enhancements
|
8
|
+
|
9
|
+
* LockAndCacheMsgpack.cached?(*key_parts) to check if a value is cached
|
10
|
+
|
11
|
+
4.0.5 / 2017-04-01
|
12
|
+
|
13
|
+
* Enhancements
|
14
|
+
|
15
|
+
* allow dates and times in keys
|
16
|
+
* Test on ruby 2.3.0 and 2.4.1
|
17
|
+
* 2x faster key generation
|
18
|
+
|
19
|
+
4.0.4 / 2016-04-11
|
20
|
+
|
21
|
+
* Bug fixes
|
22
|
+
|
23
|
+
* Don't default to debug logging
|
24
|
+
|
25
|
+
4.0.3 / 2016-04-11
|
26
|
+
|
27
|
+
* Bug fixes
|
28
|
+
|
29
|
+
* Allow true or false in keys
|
30
|
+
|
31
|
+
4.0.2 / 2016-04-11
|
32
|
+
|
33
|
+
* Bug fixes
|
34
|
+
|
35
|
+
* When generating key, recurse into #lock_and_cache_key
|
36
|
+
|
37
|
+
4.0.1 / 2016-04-11
|
38
|
+
|
39
|
+
* Bug fixes
|
40
|
+
|
41
|
+
* Avoid deadlocks related to logging
|
42
|
+
|
43
|
+
4.0.0 / 2016-04-11
|
44
|
+
|
45
|
+
* Breaking changes
|
46
|
+
|
47
|
+
* The cache key generation I've always wanted: recursively call #id or #lock_and_cache_key
|
48
|
+
|
49
|
+
3.0.1 / 2016-04-04
|
50
|
+
|
51
|
+
* Enhancements
|
52
|
+
|
53
|
+
* Don't use deprecated Thread.exclusive
|
54
|
+
|
55
|
+
3.0.0 / 2016-04-02
|
56
|
+
|
57
|
+
* Breaking changes
|
58
|
+
|
59
|
+
* In context mode (when you `include LockAndCacheMsgpack`), really call #lock_and_cache_key or #id on the instance
|
60
|
+
|
61
|
+
2.2.2 / 2015-12-18
|
62
|
+
|
63
|
+
* Bug fixes
|
64
|
+
|
65
|
+
* Don't die if you pass a non-integer expires - round it
|
66
|
+
|
67
|
+
2.2.1 / 2015-12-14
|
68
|
+
|
69
|
+
* Bug fixes
|
70
|
+
|
71
|
+
* Construct key using the correct class name
|
72
|
+
|
73
|
+
2.2.0 / 2015-11-15
|
74
|
+
|
75
|
+
* Enhancements
|
76
|
+
|
77
|
+
* Increase default heartbeat expires to 32 seconds from 2 (which was too strict IMO)
|
78
|
+
* Allow setting heartbeat_expires: globally (LockAndCacheMsgpack.heartbeat_expires=) or per call
|
79
|
+
* Provide LockAndCacheMsgpack.locked?()
|
80
|
+
|
81
|
+
2.1.1 / 2015-10-26
|
82
|
+
|
83
|
+
* Bug fixes
|
84
|
+
|
85
|
+
* Blow up if you try to use standalone mode without a key
|
86
|
+
|
87
|
+
2.1.0 / 2015-10-26
|
88
|
+
|
89
|
+
* Enhancements
|
90
|
+
|
91
|
+
* Better documentation
|
92
|
+
* Standalone mode (LockAndCacheMsgpack.lock_and_cache([...]) {})
|
93
|
+
* Nulls can be set to expire sooner than non-null return values (`nil_expires`)
|
94
|
+
|
95
|
+
2.0.2 / 2015-10-16
|
96
|
+
|
97
|
+
* Bug fixes (?)
|
98
|
+
|
99
|
+
* Make sure cached values are valid marshal format (seen in the wild that they're nil)
|
100
|
+
|
101
|
+
* Enhancements
|
102
|
+
|
103
|
+
* Use original redlock gem now that it supports extend
|
104
|
+
|
105
|
+
2.0.1 / 2015-09-14
|
106
|
+
|
107
|
+
* Bug fixes
|
108
|
+
|
109
|
+
* Don't explicitly kill the lock extender thread because that sometimes causes deadlocks (don't know why)
|
110
|
+
|
111
|
+
2.0.0 / 2015-09-11
|
112
|
+
|
113
|
+
* Breaking changes
|
114
|
+
|
115
|
+
* Stricter key digest - differentiates symbols and strings
|
116
|
+
* No more lock_expires or lock_spin options
|
117
|
+
|
118
|
+
* Bug fixes
|
119
|
+
|
120
|
+
* Allow method names with non-word chars like #foo?
|
121
|
+
|
122
|
+
* Enhancements
|
123
|
+
|
124
|
+
* heartbeats so that SIGKILL will effectively clear the lock
|
125
|
+
* #lock_and_cache_clear now clears lock too
|
126
|
+
|
127
|
+
1.1.0 / 2015-08-07
|
128
|
+
|
129
|
+
* Breaking changes
|
130
|
+
|
131
|
+
* Reduce default lock expiry to 1 day instead of weird 3 days
|
132
|
+
|
133
|
+
* Enhancements
|
134
|
+
|
135
|
+
* Added :max_lock_wait option inspired by @leandromoreira
|
136
|
+
|
137
|
+
1.0.3 / 2015-08-06
|
138
|
+
|
139
|
+
* Enhancements
|
140
|
+
|
141
|
+
* More granular debug output
|
142
|
+
|
143
|
+
1.0.2 / 2015-08-06
|
144
|
+
|
145
|
+
* Bug fixes
|
146
|
+
|
147
|
+
* Put LockAndCacheMsgpack.flush back
|
148
|
+
|
149
|
+
1.0.1 / 2015-08-06
|
150
|
+
|
151
|
+
* Bug fixes
|
152
|
+
|
153
|
+
* Return value properly if lock was acquired but cached value immediately found
|
154
|
+
|
155
|
+
* Enhancements
|
156
|
+
|
157
|
+
* Documentation
|
158
|
+
|
159
|
+
1.0.0 / 2015-08-05
|
160
|
+
|
161
|
+
* Enhancements
|
162
|
+
|
163
|
+
* Use Redis redlock http://redis.io/topics/distlock instead of Postgres advisory locks
|
164
|
+
* No more dependency on ActiveRecord or Postgres!
|
165
|
+
|
166
|
+
0.1.2 / 2015-06-24
|
167
|
+
|
168
|
+
* Enhancements
|
169
|
+
|
170
|
+
* Add :expires option in seconds
|
171
|
+
|
172
|
+
0.1.1 / 2015-02-04
|
173
|
+
|
174
|
+
* Enhancements
|
175
|
+
|
176
|
+
* Clear individual cached things with #lock_and_cache_clear
|
177
|
+
|
178
|
+
0.1.0 / 2015-01-22
|
179
|
+
|
180
|
+
* Breaking changes
|
181
|
+
|
182
|
+
* Redis only
|
183
|
+
* Now you use it inside methods (like Rails.cache.fetch) instead of outside (like cache_method)
|
184
|
+
|
185
|
+
* Enhancements
|
186
|
+
|
187
|
+
* Way simpler, no dependency on CacheMethod
|
188
|
+
|
189
|
+
0.0.5 / 2014-12-12
|
190
|
+
|
191
|
+
* Enhancements
|
192
|
+
|
193
|
+
* ENV['LOCK_AND_CACHE_DEBUG'] == 'true' debug output to $stderr
|
194
|
+
|
195
|
+
0.0.4 / 2014-12-12
|
196
|
+
|
197
|
+
* Bug fixes
|
198
|
+
|
199
|
+
* Pass arguments while caching method results
|
200
|
+
|
201
|
+
0.0.3 / 2014-12-12
|
202
|
+
|
203
|
+
* Enhancements
|
204
|
+
|
205
|
+
* Save a trip to the database if something is already cached
|
206
|
+
|
207
|
+
0.0.2 / 2014-12-11
|
208
|
+
|
209
|
+
* Bug fixes
|
210
|
+
|
211
|
+
* Gem name is activerecord
|
212
|
+
|
213
|
+
0.0.1 / 2014-12-11
|
214
|
+
|
215
|
+
initial release!
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
lock_and_cache_msgpack (4.0.6)
|
5
|
+
activesupport
|
6
|
+
msgpack (~> 1.1.0)
|
7
|
+
redis
|
8
|
+
redlock (>= 0.1.3)
|
9
|
+
|
10
|
+
GEM
|
11
|
+
remote: https://rubygems.org/
|
12
|
+
specs:
|
13
|
+
activesupport (5.1.3)
|
14
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
15
|
+
i18n (~> 0.7)
|
16
|
+
minitest (~> 5.1)
|
17
|
+
tzinfo (~> 1.1)
|
18
|
+
coderay (1.1.1)
|
19
|
+
concurrent-ruby (1.0.5)
|
20
|
+
diff-lcs (1.3)
|
21
|
+
i18n (0.8.6)
|
22
|
+
method_source (0.8.2)
|
23
|
+
minitest (5.10.3)
|
24
|
+
msgpack (1.1.0)
|
25
|
+
pry (0.10.4)
|
26
|
+
coderay (~> 1.1.0)
|
27
|
+
method_source (~> 0.8.1)
|
28
|
+
slop (~> 3.4)
|
29
|
+
rake (10.5.0)
|
30
|
+
redcarpet (3.4.0)
|
31
|
+
redis (3.3.3)
|
32
|
+
redlock (0.2.0)
|
33
|
+
redis (~> 3, >= 3.0.0)
|
34
|
+
rspec (3.6.0)
|
35
|
+
rspec-core (~> 3.6.0)
|
36
|
+
rspec-expectations (~> 3.6.0)
|
37
|
+
rspec-mocks (~> 3.6.0)
|
38
|
+
rspec-core (3.6.0)
|
39
|
+
rspec-support (~> 3.6.0)
|
40
|
+
rspec-expectations (3.6.0)
|
41
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
42
|
+
rspec-support (~> 3.6.0)
|
43
|
+
rspec-mocks (3.6.0)
|
44
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
45
|
+
rspec-support (~> 3.6.0)
|
46
|
+
rspec-support (3.6.0)
|
47
|
+
slop (3.6.0)
|
48
|
+
thread (0.2.2)
|
49
|
+
thread_safe (0.3.6)
|
50
|
+
tzinfo (1.2.3)
|
51
|
+
thread_safe (~> 0.1)
|
52
|
+
yard (0.9.9)
|
53
|
+
|
54
|
+
PLATFORMS
|
55
|
+
ruby
|
56
|
+
|
57
|
+
DEPENDENCIES
|
58
|
+
bundler (~> 1.6)
|
59
|
+
lock_and_cache_msgpack!
|
60
|
+
pry
|
61
|
+
rake (~> 10.0)
|
62
|
+
redcarpet
|
63
|
+
rspec
|
64
|
+
thread
|
65
|
+
yard
|
66
|
+
|
67
|
+
BUNDLED WITH
|
68
|
+
1.15.3
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2014 Seamus Abshere
|
2
|
+
Forked and modified 2017 Matt E. Patterson
|
3
|
+
|
4
|
+
MIT License
|
5
|
+
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
7
|
+
a copy of this software and associated documentation files (the
|
8
|
+
"Software"), to deal in the Software without restriction, including
|
9
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
10
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
11
|
+
permit persons to whom the Software is furnished to do so, subject to
|
12
|
+
the following conditions:
|
13
|
+
|
14
|
+
The above copyright notice and this permission notice shall be
|
15
|
+
included in all copies or substantial portions of the Software.
|
16
|
+
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
18
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
19
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
20
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
21
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,236 @@
|
|
1
|
+
# LockAndCacheMsgpack
|
2
|
+
|
3
|
+
[](https://travis-ci.org/seamusabshere/lock_and_cache)
|
4
|
+
[](https://codeclimate.com/github/seamusabshere/lock_and_cache)
|
5
|
+
[](https://gemnasium.com/seamusabshere/lock_and_cache)
|
6
|
+
[](http://badge.fury.io/rb/lock_and_cache)
|
7
|
+
[](https://hakiri.io/github/seamusabshere/lock_and_cache/master)
|
8
|
+
[](http://inch-ci.org/github/seamusabshere/lock_and_cache)
|
9
|
+
|
10
|
+
Lock and cache using redis!
|
11
|
+
|
12
|
+
Most caching libraries don't do locking, meaning that >1 process can be calculating a cached value at the same time. Since you presumably cache things because they cost CPU, database reads, or money, doesn't it make sense to lock while caching?
|
13
|
+
|
14
|
+
## Quickstart
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
LockAndCacheMsgpack.storage = Redis.new
|
18
|
+
|
19
|
+
LockAndCacheMsgpack.lock_and_cache(:stock_price, {company: 'MSFT', date: '2015-05-05'}, expires: 10, nil_expires: 1) do
|
20
|
+
# get yer stock quote
|
21
|
+
# if 50 processes call this at the same time, only 1 will call the stock quote service
|
22
|
+
# the other 49 will wait on the lock, then get the cached value
|
23
|
+
# the value will expire in 10 seconds
|
24
|
+
# but if the value you get back is nil, that will expire after 1 second
|
25
|
+
end
|
26
|
+
```
|
27
|
+
|
28
|
+
## Sponsor
|
29
|
+
|
30
|
+
<p><a href="http://faraday.io"><img src="http://cdn2.hubspot.net/hubfs/515497/img/logo.svg" alt="Faraday logo"/></a></p>
|
31
|
+
|
32
|
+
We use [`lock_and_cache`](https://github.com/seamusabshere/lock_and_cache) for [data-driven marketing at Faraday](http://faraday.io).
|
33
|
+
|
34
|
+
## TOC
|
35
|
+
|
36
|
+
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
37
|
+
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
38
|
+
|
39
|
+
|
40
|
+
- [Theory](#theory)
|
41
|
+
- [Practice](#practice)
|
42
|
+
- [Setup](#setup)
|
43
|
+
- [Locking](#locking)
|
44
|
+
- [Caching](#caching)
|
45
|
+
- [Standalone mode](#standalone-mode)
|
46
|
+
- [Context mode](#context-mode)
|
47
|
+
- [Special features](#special-features)
|
48
|
+
- [Locking of course!](#locking-of-course)
|
49
|
+
- [Heartbeat](#heartbeat)
|
50
|
+
- [Context mode](#context-mode-1)
|
51
|
+
- [nil_expires](#nil_expires)
|
52
|
+
- [Tunables](#tunables)
|
53
|
+
- [Few dependencies](#few-dependencies)
|
54
|
+
- [Wishlist](#wishlist)
|
55
|
+
- [Contributing](#contributing)
|
56
|
+
- [Copyright](#copyright)
|
57
|
+
|
58
|
+
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
59
|
+
|
60
|
+
## Theory
|
61
|
+
|
62
|
+
`lock_and_cache`...
|
63
|
+
|
64
|
+
1. <span style="color: red;">returns cached value</span> (if exists)
|
65
|
+
2. <span style="color: green;">acquires a lock</span>
|
66
|
+
3. <span style="color: red;">returns cached value</span> (just in case it was calculated while we were waiting for a lock)
|
67
|
+
4. <span style="color: red;">calculates and caches the value</span>
|
68
|
+
5. <span style="color: green;">releases the lock</span>
|
69
|
+
6. <span style="color: red;">returns the value</span>
|
70
|
+
|
71
|
+
As you can see, most caching libraries only take care of (1) and (4) (well, and (5) of course).
|
72
|
+
|
73
|
+
## Practice
|
74
|
+
|
75
|
+
### Setup
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
LockAndCacheMsgpack.storage = Redis.new
|
79
|
+
```
|
80
|
+
|
81
|
+
It will use this redis for both locking and storing cached values.
|
82
|
+
|
83
|
+
### Locking
|
84
|
+
|
85
|
+
Based on [antirez's Redlock algorithm](http://redis.io/topics/distlock).
|
86
|
+
|
87
|
+
Above and beyond Redlock, a 32-second heartbeat is used that will clear the lock if a process is killed. This is implemented using lock extensions.
|
88
|
+
|
89
|
+
### Caching
|
90
|
+
|
91
|
+
This gem is a simplified, improved version of https://github.com/seamusabshere/cache_method. In that library, you could only cache a method call.
|
92
|
+
|
93
|
+
In this library, you have two options: providing the whole cache key every time (standalone) or letting the library pull information about its context.
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
# standalone example
|
97
|
+
LockAndCacheMsgpack.lock_and_cache(:stock_price, {company: 'MSFT', date: '2015-05-05'}, expires: 10) do
|
98
|
+
# ...
|
99
|
+
end
|
100
|
+
|
101
|
+
# context example
|
102
|
+
def stock_price(date)
|
103
|
+
lock_and_cache(date, expires: 10) do
|
104
|
+
# ...
|
105
|
+
end
|
106
|
+
end
|
107
|
+
def lock_and_cache_key
|
108
|
+
company
|
109
|
+
end
|
110
|
+
```
|
111
|
+
|
112
|
+
#### Standalone mode
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
LockAndCacheMsgpack.lock_and_cache(:stock_price, company: 'MSFT', date: '2015-05-05') do
|
116
|
+
# get yer stock quote
|
117
|
+
end
|
118
|
+
```
|
119
|
+
|
120
|
+
You probably want an expiry
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
LockAndCacheMsgpack.lock_and_cache(:stock_price, {company: 'MSFT', date: '2015-05-05'}, expires: 10) do
|
124
|
+
# get yer stock quote
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
128
|
+
Note how we separated options (`{expires: 10}`) from a hash that is part of the cache key (`{company: 'MSFT', date: '2015-05-05'}`).
|
129
|
+
|
130
|
+
One other crazy thing: `nil_expires` - for when you want to check more often if the external stock price service returned nil
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
LockAndCacheMsgpack.lock_and_cache(:stock_price, {company: 'MSFT', date: '2015-05-05'}, expires: 10, nil_expires: 1) do
|
134
|
+
# get yer stock quote
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
138
|
+
Clear it with
|
139
|
+
|
140
|
+
```ruby
|
141
|
+
LockAndCacheMsgpack.clear :stock_price, company: 'MSFT', date: '2015-05-05'
|
142
|
+
```
|
143
|
+
|
144
|
+
Check locks with
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
LockAndCacheMsgpack.locked? :stock_price, company: 'MSFT', date: '2015-05-05'
|
148
|
+
```
|
149
|
+
|
150
|
+
#### Context mode
|
151
|
+
|
152
|
+
"Context mode" simply adds the class name, method name, and context key (the results of `#id` or `#lock_and_cache_key`) of the caller to the cache key.
|
153
|
+
|
154
|
+
```ruby
|
155
|
+
class Stock
|
156
|
+
include LockAndCacheMsgpack
|
157
|
+
|
158
|
+
def initialize(company)
|
159
|
+
[...]
|
160
|
+
end
|
161
|
+
|
162
|
+
def stock_price(date)
|
163
|
+
lock_and_cache(date, expires: 10) do
|
164
|
+
# the cache key will be StockQuote (the class) + get (the method name) + id (the instance identifier) + date (the arg you specified)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def lock_and_cache_key # <---------- if you don't define this, it will try to call #id
|
169
|
+
company
|
170
|
+
end
|
171
|
+
end
|
172
|
+
```
|
173
|
+
|
174
|
+
The cache key will be StockQuote (the class) + get (the method name) + id (the instance identifier) + date (the arg you specified).
|
175
|
+
|
176
|
+
In other words, it auto-detects the class, method, context key ... and you add other args if you want.
|
177
|
+
|
178
|
+
Clear it with
|
179
|
+
|
180
|
+
```ruby
|
181
|
+
blog.lock_and_cache_clear(:get, date)
|
182
|
+
```
|
183
|
+
|
184
|
+
## Special features
|
185
|
+
|
186
|
+
### Locking of course!
|
187
|
+
|
188
|
+
Most caching libraries don't do locking, meaning that >1 process can be calculating a cached value at the same time. Since you presumably cache things because they cost CPU, database reads, or money, doesn't it make sense to lock while caching?
|
189
|
+
|
190
|
+
### Heartbeat
|
191
|
+
|
192
|
+
If the process holding the lock dies, we automatically remove the lock so somebody else can do it (using heartbeats and redlock extends).
|
193
|
+
|
194
|
+
### Context mode
|
195
|
+
|
196
|
+
This pulls information about the context of a lock_and_cache block from the surrounding class, method, and object... so that you don't have to!
|
197
|
+
|
198
|
+
Standalone mode is cool too, tho.
|
199
|
+
|
200
|
+
### nil_expires
|
201
|
+
|
202
|
+
You can expire nil values with a different timeout (`nil_expires`) than other values (`expires`).
|
203
|
+
|
204
|
+
## Tunables
|
205
|
+
|
206
|
+
* `LockAndCacheMsgpack.storage=[redis]`
|
207
|
+
* `ENV['LOCK_AND_CACHE_DEBUG']='true'` if you want some debugging output on `$stderr`
|
208
|
+
|
209
|
+
## Few dependencies
|
210
|
+
|
211
|
+
* [activesupport](https://rubygems.org/gems/activesupport) (come on, it's the bomb)
|
212
|
+
* [redis](https://github.com/redis/redis-rb)
|
213
|
+
* [redlock](https://github.com/leandromoreira/redlock-rb)
|
214
|
+
|
215
|
+
## Known issues
|
216
|
+
|
217
|
+
* In cache keys, can't distinguish {a: 1} from [[:a, 1]]
|
218
|
+
|
219
|
+
## Wishlist
|
220
|
+
|
221
|
+
* Convert most tests to use standalone mode, which is easier to understand
|
222
|
+
* Check options
|
223
|
+
* Lengthen heartbeat so it's not so sensitive
|
224
|
+
* Clarify which options are seconds or milliseconds
|
225
|
+
|
226
|
+
## Contributing
|
227
|
+
|
228
|
+
1. Fork it ( https://github.com/[my-github-username]/lock_and_cache/fork )
|
229
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
230
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
231
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
232
|
+
5. Create a new Pull Request
|
233
|
+
|
234
|
+
# Copyright
|
235
|
+
|
236
|
+
Copyright 2015 Seamus Abshere
|