lock_and_cache_msgpack 4.0.7.pre1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in lock_and_cache.gemspec
4
+ gemspec
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
+ [![Build Status](https://travis-ci.org/seamusabshere/lock_and_cache.svg?branch=master&v=2.2.0)](https://travis-ci.org/seamusabshere/lock_and_cache)
4
+ [![Code Climate](https://codeclimate.com/github/seamusabshere/lock_and_cache/badges/gpa.svg?v=2.2.0)](https://codeclimate.com/github/seamusabshere/lock_and_cache)
5
+ [![Dependency Status](https://gemnasium.com/seamusabshere/lock_and_cache.svg?v=2.2.0)](https://gemnasium.com/seamusabshere/lock_and_cache)
6
+ [![Gem Version](https://badge.fury.io/rb/lock_and_cache.svg?v=2.2.0)](http://badge.fury.io/rb/lock_and_cache)
7
+ [![Security](https://hakiri.io/github/seamusabshere/lock_and_cache/master.svg?v=2.2.0)](https://hakiri.io/github/seamusabshere/lock_and_cache/master)
8
+ [![Inline docs](http://inch-ci.org/github/seamusabshere/lock_and_cache.svg?branch=master&v=2.2.0)](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