sane_memcached_ttl 0.0.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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +15 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +73 -0
- data/Rakefile +19 -0
- data/lib/active_support/cache/concerns/sane_memcached_ttl_helper.rb +32 -0
- data/lib/active_support/cache/couchbase_store_with_sane_ttl.rb +38 -0
- data/lib/active_support/cache/dalli_store_with_sane_ttl.rb +40 -0
- data/lib/active_support/cache/mem_cache_store_with_sane_ttl.rb +40 -0
- data/lib/sane_memcached_ttl.rb +7 -0
- data/lib/sane_memcached_ttl/utils.rb +17 -0
- data/lib/sane_memcached_ttl/version.rb +3 -0
- data/sane_memcached_ttl.gemspec +34 -0
- data/spec/active_support/cache/couchbase_store_with_sane_ttl_spec.rb +333 -0
- data/spec/integration/couchbase_stores_spec.rb +101 -0
- data/spec/integration/dalli_stores_spec.rb +70 -0
- data/spec/integration/mem_cache_stores_spec.rb +69 -0
- data/spec/spec_helper.rb +10 -0
- metadata +197 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8eabf6e5afe588b8529425c18587573797b8bd3d
|
4
|
+
data.tar.gz: 04cf4fe55796da3690a4767775cd69b4917cd78e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 531f55f7481de513547df1de895422e8a56d2b2fa2fba25565f8661e628618a0ff31884961ce472a7f1e638166cf1e42416363456304c1c9311a2237a37200b6
|
7
|
+
data.tar.gz: 9c3b47a6d878f630b94f62dea3392fb60a6a934e46b064022809d42f56fc22381dd43052c3d94211d4f23b6f1cb81ec92dd3e97a49f99fc6cdfd13fe0a6dff8a
|
data/.gitignore
ADDED
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
sane_memcached_ttl
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby-2.1.4
|
data/.travis.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
language: ruby
|
2
|
+
cache:
|
3
|
+
- bundler
|
4
|
+
- apt
|
5
|
+
before_install:
|
6
|
+
- curl http://packages.couchbase.com/ubuntu/couchbase.key | sudo apt-key add -
|
7
|
+
- echo "deb http://packages.couchbase.com/ubuntu precise precise/main" | sudo tee -a /etc/apt/sources.list
|
8
|
+
- sudo apt-get update -qq
|
9
|
+
- sudo apt-get install -y libcouchbase-dev
|
10
|
+
services:
|
11
|
+
- memcached
|
12
|
+
rvm:
|
13
|
+
- 1.9
|
14
|
+
- 2.0
|
15
|
+
- 2.1
|
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Errikos Koen
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# SaneMemcachedTtl
|
2
|
+
|
3
|
+
Work around memcached's [feature](https://code.google.com/p/memcached/wiki/NewProgramming#Expiration) of treating expiration times larger than one month as timestamps for Rails cache stores.
|
4
|
+
|
5
|
+
This is a memcached documented behaviour:
|
6
|
+
|
7
|
+
* Store a key with expiration time of 10 seconds
|
8
|
+
* Retrieve key ~> you get it
|
9
|
+
* Wait 10 seconds
|
10
|
+
* Retrieve key ~> you don't get it
|
11
|
+
|
12
|
+
makes sense... but:
|
13
|
+
|
14
|
+
* Store a key with expiration time of 3.000.000 seconds (about 35 days)
|
15
|
+
* Retrieve key ~> you **don't** get it
|
16
|
+
|
17
|
+
3.000.000 is treated as timestamp, so the key expired at 1970-02-04 17:20:00 (3.000.000 seconds after the UNIX epoch). So when you want to store something with an expiration time larger than a month you have to convert the expiration time to a proper timestamp. This is annoying and it even becomes impossible when you want to set default expiration times on stores.
|
18
|
+
|
19
|
+
This gem provides additional cache stores, subclasses of the original ones altering this behaviour for sanity.
|
20
|
+
|
21
|
+
Supported cache stores: couchbase_store, dalli_store, mem_cache_store.
|
22
|
+
|
23
|
+
## Dalli note
|
24
|
+
|
25
|
+
The dalli store actually fixed this on version 2.7.1 but it's kinda debated ([issue #436](https://github.com/mperham/dalli/issues/436)) on whether this should stay in as it's a documented memcached "feature" and clients should probably be not alter to these things.
|
26
|
+
|
27
|
+
So **don't** use this if your dalli gem version is >= 2.7.1.
|
28
|
+
|
29
|
+
## Installation
|
30
|
+
|
31
|
+
Add this line to your application's Gemfile:
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
gem 'sane_memcached_ttl'
|
35
|
+
```
|
36
|
+
|
37
|
+
And then execute:
|
38
|
+
|
39
|
+
$ bundle
|
40
|
+
|
41
|
+
Or install it yourself as:
|
42
|
+
|
43
|
+
$ gem install sane_memcached_ttl
|
44
|
+
|
45
|
+
## Usage
|
46
|
+
|
47
|
+
When defining a Rails cache store like:
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
config.cache_store = :mem_cache_store, "cache-1.example.com", "cache-2.example.com"
|
51
|
+
```
|
52
|
+
|
53
|
+
just change to:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
config.cache_store = :mem_cache_store_with_sane_ttl, "cache-1.example.com", "cache-2.example.com"
|
57
|
+
```
|
58
|
+
|
59
|
+
Same for all supported stores:
|
60
|
+
|
61
|
+
| Original store | Sane store |
|
62
|
+
| ----------------- | --------------------------------- |
|
63
|
+
| `mem_cache_store` | `mem_cache_store_with_sane_ttl` |
|
64
|
+
| `dalli_store` | `dalli_store_store_with_sane_ttl` |
|
65
|
+
| `couchbase_store` | `couchbase_store_with_sane_ttl` |
|
66
|
+
|
67
|
+
## Contributing
|
68
|
+
|
69
|
+
1. Fork it ( https://github.com/[my-github-username]/sane_memcached_ttl/fork )
|
70
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
71
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
72
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
73
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rake/testtask'
|
3
|
+
|
4
|
+
Rake::TestTask.new do |t|
|
5
|
+
t.name = 'spec'
|
6
|
+
t.libs << 'spec'
|
7
|
+
t.test_files = FileList['spec/**/*_spec.rb'].exclude(/^spec\/integration\//)
|
8
|
+
t.verbose = true
|
9
|
+
end
|
10
|
+
|
11
|
+
Rake::TestTask.new do |t|
|
12
|
+
t.name = 'integration'
|
13
|
+
t.libs << 'spec'
|
14
|
+
t.test_files = FileList['spec/integration**/*_spec.rb']
|
15
|
+
t.verbose = true
|
16
|
+
end
|
17
|
+
|
18
|
+
desc 'Run tests'
|
19
|
+
task :default => [:spec, :integration]
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
module ActiveSupport
|
4
|
+
module Cache
|
5
|
+
module Concerns
|
6
|
+
module SaneMemcachedTtlHelper
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
include SaneMemcachedTtl::Utils
|
9
|
+
|
10
|
+
included do
|
11
|
+
attr_accessor :large_default_ttl
|
12
|
+
end
|
13
|
+
|
14
|
+
def extract_large_default_ttl!(options, insane_options)
|
15
|
+
ttl = options[insane_options.find { |option| options[option] != nil }]
|
16
|
+
|
17
|
+
if ttl.present? && is_large_ttl?(ttl)
|
18
|
+
insane_options.each { |option| options.delete option }
|
19
|
+
self.large_default_ttl = ttl
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def sanitize_ttl_options!(options, insane_options, default_option)
|
24
|
+
ttl = options[insane_options.find { |option| options[option] != nil }]
|
25
|
+
|
26
|
+
insane_options.each { |option| options.delete(option) }
|
27
|
+
options[default_option] = sanitize_ttl(ttl || large_default_ttl)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'active_support/cache'
|
2
|
+
require 'active_support/cache/couchbase_store'
|
3
|
+
require 'active_support/cache/concerns/sane_memcached_ttl_helper'
|
4
|
+
|
5
|
+
module ActiveSupport
|
6
|
+
module Cache
|
7
|
+
class CouchbaseStoreWithSaneTtl < CouchbaseStore
|
8
|
+
|
9
|
+
include ActiveSupport::Cache::Concerns::SaneMemcachedTtlHelper
|
10
|
+
|
11
|
+
def initialize(options = nil)
|
12
|
+
options = options || {}
|
13
|
+
extract_large_default_ttl! options, [:default_ttl, :expires_in]
|
14
|
+
super options
|
15
|
+
end
|
16
|
+
|
17
|
+
def increment(name, amount = 1, options = nil)
|
18
|
+
options = options || {}
|
19
|
+
sanitize_ttl_options! options, [:ttl, :expires_in], :expires_in
|
20
|
+
super name, amount, options
|
21
|
+
end
|
22
|
+
|
23
|
+
def decrement(name, amount = 1, options = nil)
|
24
|
+
options = options || {}
|
25
|
+
sanitize_ttl_options! options, [:ttl, :expires_in], :expires_in
|
26
|
+
super name, amount, options
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def write_entry(key, value, options)
|
32
|
+
options = options || {}
|
33
|
+
sanitize_ttl_options! options, [:ttl, :expires_in], :expires_in
|
34
|
+
super key, value, options
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'active_support/cache'
|
2
|
+
require 'active_support/notifications'
|
3
|
+
require 'active_support/cache/dalli_store'
|
4
|
+
require 'active_support/cache/concerns/sane_memcached_ttl_helper'
|
5
|
+
|
6
|
+
module ActiveSupport
|
7
|
+
module Cache
|
8
|
+
class DalliStoreWithSaneTtl < DalliStore
|
9
|
+
|
10
|
+
include ActiveSupport::Cache::Concerns::SaneMemcachedTtlHelper
|
11
|
+
|
12
|
+
def initialize(*addresses)
|
13
|
+
addresses = addresses.flatten
|
14
|
+
options = addresses.extract_options!
|
15
|
+
extract_large_default_ttl! options, [:expires_in]
|
16
|
+
super addresses, options
|
17
|
+
end
|
18
|
+
|
19
|
+
def increment(name, amount = 1, options = nil)
|
20
|
+
options = options || {}
|
21
|
+
sanitize_ttl_options! options, [:expires_in], :expires_in
|
22
|
+
super name, amount, options
|
23
|
+
end
|
24
|
+
|
25
|
+
def decrement(name, amount = 1, options = nil)
|
26
|
+
options = options || {}
|
27
|
+
sanitize_ttl_options! options, [:expires_in], :expires_in
|
28
|
+
super name, amount, options
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def write_entry(key, value, options)
|
34
|
+
options = options || {}
|
35
|
+
sanitize_ttl_options! options, [:expires_in], :expires_in
|
36
|
+
super key, value, options
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'active_support/cache'
|
2
|
+
require 'active_support/cache/mem_cache_store'
|
3
|
+
require 'active_support/cache/concerns/sane_memcached_ttl_helper'
|
4
|
+
require 'active_support/notifications'
|
5
|
+
|
6
|
+
module ActiveSupport
|
7
|
+
module Cache
|
8
|
+
class MemCacheStoreWithSaneTtl < MemCacheStore
|
9
|
+
|
10
|
+
include ActiveSupport::Cache::Concerns::SaneMemcachedTtlHelper
|
11
|
+
|
12
|
+
def initialize(*addresses)
|
13
|
+
addresses = addresses.flatten
|
14
|
+
options = addresses.extract_options!
|
15
|
+
extract_large_default_ttl! options, [:expires_in]
|
16
|
+
super addresses, options
|
17
|
+
end
|
18
|
+
|
19
|
+
def increment(name, amount = 1, options = nil)
|
20
|
+
options = options || {}
|
21
|
+
sanitize_ttl_options! options, [:expires_in], :expires_in
|
22
|
+
super name, amount, options
|
23
|
+
end
|
24
|
+
|
25
|
+
def decrement(name, amount = 1, options = nil)
|
26
|
+
options = options || {}
|
27
|
+
sanitize_ttl_options! options, [:expires_in], :expires_in
|
28
|
+
super name, amount, options
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def write_entry(key, value, options)
|
34
|
+
options = options || {}
|
35
|
+
sanitize_ttl_options! options, [:expires_in], :expires_in
|
36
|
+
super key, value, options
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module SaneMemcachedTtl
|
2
|
+
module Utils
|
3
|
+
MEMCACHED_MAX_TTL = 30 * 24 * 60 * 60 # 30 days
|
4
|
+
|
5
|
+
def sanitize_ttl(ttl)
|
6
|
+
is_large_ttl?(ttl) ? ttl_to_timestamp(ttl) : ttl
|
7
|
+
end
|
8
|
+
|
9
|
+
def is_large_ttl?(ttl)
|
10
|
+
ttl.to_i > MEMCACHED_MAX_TTL
|
11
|
+
end
|
12
|
+
|
13
|
+
def ttl_to_timestamp(ttl)
|
14
|
+
Time.now.utc.to_i + ttl.to_i
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sane_memcached_ttl/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'sane_memcached_ttl'
|
8
|
+
spec.version = SaneMemcachedTtl::VERSION
|
9
|
+
spec.authors = ['Errikos Koen']
|
10
|
+
spec.email = ['eirc.eric@gmail.com']
|
11
|
+
spec.summary = %q{Add sanity to memcached expiration times.}
|
12
|
+
spec.homepage = 'https://github.com/eirc/sane_memcached_ttl'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
|
20
|
+
spec.add_development_dependency 'bundler'
|
21
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
22
|
+
|
23
|
+
spec.add_development_dependency 'activesupport'
|
24
|
+
|
25
|
+
# Cache stores
|
26
|
+
spec.add_development_dependency 'couchbase'
|
27
|
+
spec.add_development_dependency 'dalli', '< 2.7.1'
|
28
|
+
|
29
|
+
# Testing gems
|
30
|
+
spec.add_development_dependency 'minitest'
|
31
|
+
spec.add_development_dependency 'mocha'
|
32
|
+
spec.add_development_dependency 'guard'
|
33
|
+
spec.add_development_dependency 'guard-minitest'
|
34
|
+
end
|
@@ -0,0 +1,333 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'mocha/setup'
|
3
|
+
require 'active_support/cache/couchbase_store_with_sane_ttl'
|
4
|
+
|
5
|
+
module ActiveSupport::Cache
|
6
|
+
describe CouchbaseStoreWithSaneTtl do
|
7
|
+
let (:small_ttl) { 7 * 24 * 60 * 60 }
|
8
|
+
let (:large_ttl) { 6 * 30 * 24 * 60 * 60 }
|
9
|
+
|
10
|
+
describe '#initialize' do
|
11
|
+
it 'should remove from options and store large default_ttl value' do
|
12
|
+
Couchbase::Bucket.expects(:new).with do |options|
|
13
|
+
options[:default_ttl].must_be_nil
|
14
|
+
options[:expires_in].must_be_nil
|
15
|
+
end
|
16
|
+
|
17
|
+
store = ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl,
|
18
|
+
:default_ttl => large_ttl
|
19
|
+
|
20
|
+
store.large_default_ttl.must_equal large_ttl
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should remove from options and store large expires_in value' do
|
24
|
+
Couchbase::Bucket.expects(:new).with do |options|
|
25
|
+
options[:default_ttl].must_be_nil
|
26
|
+
options[:expires_in].must_be_nil
|
27
|
+
end
|
28
|
+
|
29
|
+
store = ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl,
|
30
|
+
:expires_in => large_ttl
|
31
|
+
|
32
|
+
store.large_default_ttl.must_equal large_ttl
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should not remove from options or store small default_ttl value' do
|
36
|
+
Couchbase::Bucket.expects(:new).with do |options|
|
37
|
+
options[:default_ttl].must_equal small_ttl
|
38
|
+
options[:expires_in].must_be_nil
|
39
|
+
end
|
40
|
+
|
41
|
+
store = ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl,
|
42
|
+
:default_ttl => small_ttl
|
43
|
+
|
44
|
+
store.large_default_ttl.must_be_nil
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should not remove or store small expires_in value' do
|
48
|
+
Couchbase::Bucket.expects(:new).with do |options|
|
49
|
+
options[:default_ttl].must_equal small_ttl
|
50
|
+
options[:expires_in].must_be_nil
|
51
|
+
end
|
52
|
+
|
53
|
+
store = ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl,
|
54
|
+
:expires_in => small_ttl
|
55
|
+
|
56
|
+
store.large_default_ttl.must_be_nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#increment' do
|
61
|
+
describe 'with no default tll' do
|
62
|
+
let(:bucket_mock) { mock }
|
63
|
+
subject do
|
64
|
+
Couchbase::Bucket.expects(:new).returns(bucket_mock)
|
65
|
+
ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'should convert ttl to timestamp when set to large value' do
|
69
|
+
bucket_mock.expects(:incr).with do |key, amount, options|
|
70
|
+
options[:ttl].must_equal Time.now.utc.to_i + large_ttl
|
71
|
+
end
|
72
|
+
subject.increment 'key', 1, :expires_in => large_ttl
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'should keep ttl intact when set to small value' do
|
76
|
+
bucket_mock.expects(:incr).with do |key, amount, options|
|
77
|
+
options[:ttl].must_equal small_ttl
|
78
|
+
end
|
79
|
+
subject.increment 'key', 1, :expires_in => small_ttl
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'should leave ttl nil when not set' do
|
83
|
+
bucket_mock.expects(:incr).with do |key, amount, options|
|
84
|
+
options[:ttl].must_be_nil
|
85
|
+
end
|
86
|
+
subject.increment 'key', 1
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe 'with large default tll' do
|
91
|
+
let(:bucket_mock) { mock }
|
92
|
+
subject do
|
93
|
+
Couchbase::Bucket.expects(:new).returns(bucket_mock)
|
94
|
+
ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl,
|
95
|
+
:expires_in => large_ttl
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'should convert ttl to timestamp when set to large value' do
|
99
|
+
bucket_mock.expects(:incr).with do |key, amount, options|
|
100
|
+
options[:ttl].must_equal Time.now.utc.to_i + large_ttl
|
101
|
+
end
|
102
|
+
subject.increment 'key', 1, :expires_in => large_ttl
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should keep ttl intact when set to small value' do
|
106
|
+
bucket_mock.expects(:incr).with do |key, amount, options|
|
107
|
+
options[:ttl].must_equal small_ttl
|
108
|
+
end
|
109
|
+
subject.increment 'key', 1, :expires_in => small_ttl
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should calculate from default ttl when not set' do
|
113
|
+
bucket_mock.expects(:incr).with do |key, amount, options|
|
114
|
+
(options[:ttl]).must_equal Time.now.utc.to_i + large_ttl
|
115
|
+
end
|
116
|
+
subject.increment 'key', 1
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe 'with small default tll' do
|
121
|
+
let(:bucket_mock) { mock }
|
122
|
+
subject do
|
123
|
+
Couchbase::Bucket.expects(:new).returns(bucket_mock)
|
124
|
+
ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl,
|
125
|
+
:default_ttl => small_ttl
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'should convert ttl to timestamp when set to large value' do
|
129
|
+
bucket_mock.expects(:incr).with do |key, amount, options|
|
130
|
+
options[:ttl].must_equal Time.now.utc.to_i + large_ttl
|
131
|
+
end
|
132
|
+
subject.increment 'key', 1, :expires_in => large_ttl
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'should keep ttl intact when set to small value' do
|
136
|
+
bucket_mock.expects(:incr).with do |key, amount, options|
|
137
|
+
options[:ttl].must_equal small_ttl
|
138
|
+
end
|
139
|
+
subject.increment 'key', 1, :expires_in => small_ttl
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'should leave ttl nil when not set' do
|
143
|
+
bucket_mock.expects(:incr).with do |key, amount, options|
|
144
|
+
options[:ttl].must_be_nil
|
145
|
+
end
|
146
|
+
subject.increment 'key', 1
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
describe '#decrement' do
|
152
|
+
describe 'with no default tll' do
|
153
|
+
let(:bucket_mock) { mock }
|
154
|
+
subject do
|
155
|
+
Couchbase::Bucket.expects(:new).returns(bucket_mock)
|
156
|
+
ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl
|
157
|
+
end
|
158
|
+
|
159
|
+
it 'should convert ttl to timestamp when set to large value' do
|
160
|
+
bucket_mock.expects(:decr).with do |key, amount, options|
|
161
|
+
options[:ttl].must_equal Time.now.utc.to_i + large_ttl
|
162
|
+
end
|
163
|
+
subject.decrement 'key', 1, :expires_in => large_ttl
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'should keep ttl intact when set to small value' do
|
167
|
+
bucket_mock.expects(:decr).with do |key, amount, options|
|
168
|
+
options[:ttl].must_equal small_ttl
|
169
|
+
end
|
170
|
+
subject.decrement 'key', 1, :expires_in => small_ttl
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'should leave ttl nil when not set' do
|
174
|
+
bucket_mock.expects(:decr).with do |key, amount, options|
|
175
|
+
options[:ttl].must_be_nil
|
176
|
+
end
|
177
|
+
subject.decrement 'key', 1
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe 'with large default tll' do
|
182
|
+
let(:bucket_mock) { mock }
|
183
|
+
subject do
|
184
|
+
Couchbase::Bucket.expects(:new).returns(bucket_mock)
|
185
|
+
ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl,
|
186
|
+
:default_ttl => large_ttl
|
187
|
+
end
|
188
|
+
|
189
|
+
it 'should convert ttl to timestamp when set to large value' do
|
190
|
+
bucket_mock.expects(:decr).with do |key, amount, options|
|
191
|
+
options[:ttl].must_equal Time.now.utc.to_i + large_ttl
|
192
|
+
end
|
193
|
+
subject.decrement 'key', 1, :expires_in => large_ttl
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'should keep ttl intact when set to small value' do
|
197
|
+
bucket_mock.expects(:decr).with do |key, amount, options|
|
198
|
+
options[:ttl].must_equal small_ttl
|
199
|
+
end
|
200
|
+
subject.decrement 'key', 1, :expires_in => small_ttl
|
201
|
+
end
|
202
|
+
|
203
|
+
it 'should calculate from default ttl when not set' do
|
204
|
+
bucket_mock.expects(:decr).with do |key, amount, options|
|
205
|
+
options[:ttl].must_equal Time.now.utc.to_i + large_ttl
|
206
|
+
end
|
207
|
+
subject.decrement 'key', 1
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
describe 'with small default tll' do
|
212
|
+
let(:bucket_mock) { mock }
|
213
|
+
subject do
|
214
|
+
Couchbase::Bucket.expects(:new).returns(bucket_mock)
|
215
|
+
ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl,
|
216
|
+
:default_ttl => small_ttl
|
217
|
+
end
|
218
|
+
|
219
|
+
it 'should convert ttl to timestamp when set to large value' do
|
220
|
+
bucket_mock.expects(:decr).with do |key, amount, options|
|
221
|
+
options[:ttl].must_equal Time.now.utc.to_i + large_ttl
|
222
|
+
end
|
223
|
+
subject.decrement 'key', 1, :expires_in => large_ttl
|
224
|
+
end
|
225
|
+
|
226
|
+
it 'should keep ttl intact when set to small value' do
|
227
|
+
bucket_mock.expects(:decr).with do |key, amount, options|
|
228
|
+
options[:ttl].must_equal small_ttl
|
229
|
+
end
|
230
|
+
subject.decrement 'key', 1, :expires_in => small_ttl
|
231
|
+
end
|
232
|
+
|
233
|
+
it 'should leave ttl nil when not set' do
|
234
|
+
bucket_mock.expects(:decr).with do |key, amount, options|
|
235
|
+
options[:ttl].must_be_nil
|
236
|
+
end
|
237
|
+
subject.decrement 'key', 1
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
describe '#write' do
|
243
|
+
describe 'with no default tll' do
|
244
|
+
let(:bucket_mock) { mock }
|
245
|
+
subject do
|
246
|
+
Couchbase::Bucket.expects(:new).returns(bucket_mock)
|
247
|
+
ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'should convert ttl to timestamp when set to large value' do
|
251
|
+
bucket_mock.expects(:set).with do |key, value, options|
|
252
|
+
options[:ttl].must_equal Time.now.utc.to_i + large_ttl
|
253
|
+
end
|
254
|
+
subject.write 'key', 'value', :expires_in => large_ttl
|
255
|
+
end
|
256
|
+
|
257
|
+
it 'should keep ttl intact when set to small value' do
|
258
|
+
bucket_mock.expects(:set).with do |key, value, options|
|
259
|
+
options[:ttl].must_equal small_ttl
|
260
|
+
end
|
261
|
+
subject.write 'key', 'value', :expires_in => small_ttl
|
262
|
+
end
|
263
|
+
|
264
|
+
it 'should leave ttl nil when not set' do
|
265
|
+
bucket_mock.expects(:set).with do |key, value, options|
|
266
|
+
options[:ttl].must_be_nil
|
267
|
+
end
|
268
|
+
subject.write 'key', 'value'
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
describe 'with large default tll' do
|
273
|
+
let(:bucket_mock) { mock }
|
274
|
+
subject do
|
275
|
+
Couchbase::Bucket.expects(:new).returns(bucket_mock)
|
276
|
+
ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl,
|
277
|
+
:default_ttl => large_ttl
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'should convert ttl to timestamp when set to large value' do
|
281
|
+
bucket_mock.expects(:set).with do |key, value, options|
|
282
|
+
options[:ttl].must_equal Time.now.utc.to_i + large_ttl
|
283
|
+
end
|
284
|
+
subject.write 'key', 'value', :expires_in => large_ttl
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'should keep ttl intact when set to small value' do
|
288
|
+
bucket_mock.expects(:set).with do |key, value, options|
|
289
|
+
options[:ttl].must_equal small_ttl
|
290
|
+
end
|
291
|
+
subject.write 'key', 'value', :expires_in => small_ttl
|
292
|
+
end
|
293
|
+
|
294
|
+
it 'should calculate from default ttl when not set' do
|
295
|
+
bucket_mock.expects(:set).with do |key, value, options|
|
296
|
+
options[:ttl].must_equal Time.now.utc.to_i + large_ttl
|
297
|
+
end
|
298
|
+
subject.write 'key', 'value'
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
describe 'with small default tll' do
|
303
|
+
let(:bucket_mock) { mock }
|
304
|
+
subject do
|
305
|
+
Couchbase::Bucket.expects(:new).returns(bucket_mock)
|
306
|
+
ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl,
|
307
|
+
:default_ttl => small_ttl
|
308
|
+
end
|
309
|
+
|
310
|
+
it 'should convert ttl to timestamp when set to large value' do
|
311
|
+
bucket_mock.expects(:set).with do |key, value, options|
|
312
|
+
options[:ttl].must_equal Time.now.utc.to_i + large_ttl
|
313
|
+
end
|
314
|
+
subject.write 'key', 'value', :expires_in => large_ttl
|
315
|
+
end
|
316
|
+
|
317
|
+
it 'should keep ttl intact when set to small value' do
|
318
|
+
bucket_mock.expects(:set).with do |key, value, options|
|
319
|
+
options[:ttl].must_equal small_ttl
|
320
|
+
end
|
321
|
+
subject.write 'key', 'value', :expires_in => small_ttl
|
322
|
+
end
|
323
|
+
|
324
|
+
it 'should leave ttl nil when not set' do
|
325
|
+
bucket_mock.expects(:set).with do |key, value, options|
|
326
|
+
options[:ttl].must_be_nil
|
327
|
+
end
|
328
|
+
subject.write 'key', 'value'
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_support/cache'
|
3
|
+
|
4
|
+
module ActiveSupport::Cache
|
5
|
+
describe 'couchbase stores' do
|
6
|
+
let(:large_ttl) { 6 * 30 * 24 * 60 * 60 }
|
7
|
+
|
8
|
+
before do
|
9
|
+
begin
|
10
|
+
ActiveSupport::Cache.lookup_store :couchbase_store,
|
11
|
+
CACHE_SETTINGS[:couchbase]
|
12
|
+
rescue
|
13
|
+
skip 'Cannot connect to Couchbase server, skipping integration tests.'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'with connection ttls' do
|
18
|
+
it 'couchbase_store_with_sane_ttl does store keys with large connection default_ttl' do
|
19
|
+
store = ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl,
|
20
|
+
CACHE_SETTINGS[:couchbase].merge(:default_ttl => large_ttl)
|
21
|
+
|
22
|
+
store.read('key').must_be_nil
|
23
|
+
store.write 'key', 'value'
|
24
|
+
store.read('key').must_equal 'value'
|
25
|
+
store.delete 'key'
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'couchbase_store does not store keys with large connection default_ttl' do
|
29
|
+
store = ActiveSupport::Cache.lookup_store :couchbase_store,
|
30
|
+
CACHE_SETTINGS[:couchbase].merge(:default_ttl => large_ttl)
|
31
|
+
|
32
|
+
store.read('key').must_be_nil
|
33
|
+
store.write 'key', 'value'
|
34
|
+
store.read('key').must_be_nil
|
35
|
+
store.delete 'key'
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'couchbase_store_with_sane_ttl does store keys with large connection expires_in' do
|
39
|
+
store = ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl,
|
40
|
+
CACHE_SETTINGS[:couchbase].merge(:expires_in => large_ttl)
|
41
|
+
|
42
|
+
store.read('key').must_be_nil
|
43
|
+
store.write 'key', 'value'
|
44
|
+
store.read('key').must_equal 'value'
|
45
|
+
store.delete 'key'
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'couchbase_store does not store keys with large connection expires_in' do
|
49
|
+
store = ActiveSupport::Cache.lookup_store :couchbase_store,
|
50
|
+
CACHE_SETTINGS[:couchbase].merge(:expires_in => large_ttl)
|
51
|
+
|
52
|
+
store.read('key').must_be_nil
|
53
|
+
store.write 'key', 'value'
|
54
|
+
store.read('key').must_be_nil
|
55
|
+
store.delete 'key'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe 'with ttls on write' do
|
60
|
+
it 'couchbase_store_with_sane_ttl does store keys with large expires_in' do
|
61
|
+
store = ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl,
|
62
|
+
CACHE_SETTINGS[:couchbase]
|
63
|
+
|
64
|
+
store.read('key').must_be_nil
|
65
|
+
store.write 'key', 'value', :expires_in => large_ttl
|
66
|
+
store.read('key').must_equal 'value'
|
67
|
+
store.delete 'key'
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'couchbase_store does not store keys with large expires_in' do
|
71
|
+
store = ActiveSupport::Cache.lookup_store :couchbase_store,
|
72
|
+
CACHE_SETTINGS[:couchbase]
|
73
|
+
|
74
|
+
store.read('key').must_be_nil
|
75
|
+
store.write 'key', 'value', :expires_in => large_ttl
|
76
|
+
store.read('key').must_be_nil
|
77
|
+
store.delete 'key'
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'couchbase_store_with_sane_ttl does store keys with large ttl' do
|
81
|
+
store = ActiveSupport::Cache.lookup_store :couchbase_store_with_sane_ttl,
|
82
|
+
CACHE_SETTINGS[:couchbase]
|
83
|
+
|
84
|
+
store.read('key').must_be_nil
|
85
|
+
store.write 'key', 'value', :ttl => large_ttl
|
86
|
+
store.read('key').must_equal 'value'
|
87
|
+
store.delete 'key'
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'couchbase_store does not store keys with large ttl' do
|
91
|
+
store = ActiveSupport::Cache.lookup_store :couchbase_store,
|
92
|
+
CACHE_SETTINGS[:couchbase]
|
93
|
+
|
94
|
+
store.read('key').must_be_nil
|
95
|
+
store.write 'key', 'value', :ttl => large_ttl
|
96
|
+
store.read('key').must_be_nil
|
97
|
+
store.delete 'key'
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_support/cache'
|
3
|
+
require 'active_support/notifications'
|
4
|
+
require 'dalli'
|
5
|
+
|
6
|
+
module ActiveSupport::Cache
|
7
|
+
describe 'dalli stores' do
|
8
|
+
let(:large_ttl) { 6 * 30 * 24 * 60 * 60 }
|
9
|
+
|
10
|
+
before do
|
11
|
+
# Silence all logging to make an initial check on whether server is up
|
12
|
+
Dalli.logger.level = Logger::UNKNOWN
|
13
|
+
store = ActiveSupport::Cache.lookup_store :dalli_store,
|
14
|
+
CACHE_SETTINGS[:dalli]
|
15
|
+
|
16
|
+
if store.stats.values.all? { |value| value == nil }
|
17
|
+
skip 'Cannot connect to Memcached server, skipping dalli stores integration specs.'
|
18
|
+
end
|
19
|
+
|
20
|
+
# Silence connection info messages from dalli
|
21
|
+
Dalli.logger.level = Logger::WARN
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'with connection ttls' do
|
25
|
+
it 'dalli_store_with_sane_ttl does store keys with large connection expires_in' do
|
26
|
+
store = ActiveSupport::Cache.lookup_store :dalli_store_with_sane_ttl,
|
27
|
+
CACHE_SETTINGS[:dalli],
|
28
|
+
:expires_in => large_ttl
|
29
|
+
|
30
|
+
store.read('key').must_be_nil
|
31
|
+
store.write 'key', 'value'
|
32
|
+
store.read('key').must_equal 'value'
|
33
|
+
store.delete 'key'
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'dalli_store does not store keys with large connection expires_in' do
|
37
|
+
store = ActiveSupport::Cache.lookup_store :dalli_store,
|
38
|
+
CACHE_SETTINGS[:dalli],
|
39
|
+
:expires_in => large_ttl
|
40
|
+
|
41
|
+
store.read('key').must_be_nil
|
42
|
+
store.write 'key', 'value'
|
43
|
+
store.read('key').must_be_nil
|
44
|
+
store.delete 'key'
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'with ttls on write' do
|
49
|
+
it 'dalli_store_with_sane_ttl does store keys with large expires_in' do
|
50
|
+
store = ActiveSupport::Cache.lookup_store :dalli_store_with_sane_ttl,
|
51
|
+
CACHE_SETTINGS[:dalli]
|
52
|
+
|
53
|
+
store.read('key').must_be_nil
|
54
|
+
store.write 'key', 'value', :expires_in => large_ttl
|
55
|
+
store.read('key').must_equal 'value'
|
56
|
+
store.delete 'key'
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'dalli_store does not store keys with large expires_in' do
|
60
|
+
store = ActiveSupport::Cache.lookup_store :dalli_store,
|
61
|
+
CACHE_SETTINGS[:dalli]
|
62
|
+
|
63
|
+
store.read('key').must_be_nil
|
64
|
+
store.write 'key', 'value', :expires_in => large_ttl
|
65
|
+
store.read('key').must_be_nil
|
66
|
+
store.delete 'key'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_support/cache'
|
3
|
+
require 'dalli'
|
4
|
+
|
5
|
+
module ActiveSupport::Cache
|
6
|
+
describe 'mem cache stores' do
|
7
|
+
let(:large_ttl) { 6 * 30 * 24 * 60 * 60 }
|
8
|
+
|
9
|
+
before do
|
10
|
+
# Silence all logging to make an initial check on whether server is up (mem_cache_store is backed by a dalli client)
|
11
|
+
Dalli.logger.level = Logger::UNKNOWN
|
12
|
+
store = ActiveSupport::Cache.lookup_store :mem_cache_store,
|
13
|
+
CACHE_SETTINGS[:mem_cache]
|
14
|
+
|
15
|
+
if store.stats.values.all? { |value| value == nil }
|
16
|
+
skip 'Cannot connect to Memcached server, skipping mem cache stores integration specs.'
|
17
|
+
end
|
18
|
+
|
19
|
+
# Silence connection info messages
|
20
|
+
Dalli.logger.level = Logger::WARN
|
21
|
+
end
|
22
|
+
|
23
|
+
describe 'with connection ttls' do
|
24
|
+
it 'mem_cache_store_with_sane_ttl does store keys with large connection expires_in' do
|
25
|
+
store = ActiveSupport::Cache.lookup_store :mem_cache_store_with_sane_ttl,
|
26
|
+
CACHE_SETTINGS[:mem_cache],
|
27
|
+
:expires_in => large_ttl
|
28
|
+
|
29
|
+
store.read('key').must_be_nil
|
30
|
+
store.write 'key', 'value'
|
31
|
+
store.read('key').must_equal 'value'
|
32
|
+
store.delete 'key'
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'mem_cache_store does not store keys with large connection expires_in' do
|
36
|
+
store = ActiveSupport::Cache.lookup_store :mem_cache_store,
|
37
|
+
CACHE_SETTINGS[:mem_cache],
|
38
|
+
:expires_in => large_ttl
|
39
|
+
|
40
|
+
store.read('key').must_be_nil
|
41
|
+
store.write 'key', 'value'
|
42
|
+
store.read('key').must_be_nil
|
43
|
+
store.delete 'key'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe 'with ttls on write' do
|
48
|
+
it 'mem_cache_store_with_sane_ttl does store keys with large expires_in' do
|
49
|
+
store = ActiveSupport::Cache.lookup_store :mem_cache_store_with_sane_ttl,
|
50
|
+
CACHE_SETTINGS[:mem_cache]
|
51
|
+
|
52
|
+
store.read('key').must_be_nil
|
53
|
+
store.write 'key', 'value', :expires_in => large_ttl
|
54
|
+
store.read('key').must_equal 'value'
|
55
|
+
store.delete 'key'
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'mem_cache_store does not store keys with large expires_in' do
|
59
|
+
store = ActiveSupport::Cache.lookup_store :mem_cache_store,
|
60
|
+
CACHE_SETTINGS[:mem_cache]
|
61
|
+
|
62
|
+
store.read('key').must_be_nil
|
63
|
+
store.write 'key', 'value', :expires_in => large_ttl
|
64
|
+
store.read('key').must_be_nil
|
65
|
+
store.delete 'key'
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,197 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sane_memcached_ttl
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Errikos Koen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: activesupport
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: couchbase
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: dalli
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "<"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 2.7.1
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "<"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 2.7.1
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: minitest
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: mocha
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: guard
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: guard-minitest
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
description:
|
140
|
+
email:
|
141
|
+
- eirc.eric@gmail.com
|
142
|
+
executables: []
|
143
|
+
extensions: []
|
144
|
+
extra_rdoc_files: []
|
145
|
+
files:
|
146
|
+
- ".gitignore"
|
147
|
+
- ".ruby-gemset"
|
148
|
+
- ".ruby-version"
|
149
|
+
- ".travis.yml"
|
150
|
+
- Gemfile
|
151
|
+
- Guardfile
|
152
|
+
- LICENSE.txt
|
153
|
+
- README.md
|
154
|
+
- Rakefile
|
155
|
+
- lib/active_support/cache/concerns/sane_memcached_ttl_helper.rb
|
156
|
+
- lib/active_support/cache/couchbase_store_with_sane_ttl.rb
|
157
|
+
- lib/active_support/cache/dalli_store_with_sane_ttl.rb
|
158
|
+
- lib/active_support/cache/mem_cache_store_with_sane_ttl.rb
|
159
|
+
- lib/sane_memcached_ttl.rb
|
160
|
+
- lib/sane_memcached_ttl/utils.rb
|
161
|
+
- lib/sane_memcached_ttl/version.rb
|
162
|
+
- sane_memcached_ttl.gemspec
|
163
|
+
- spec/active_support/cache/couchbase_store_with_sane_ttl_spec.rb
|
164
|
+
- spec/integration/couchbase_stores_spec.rb
|
165
|
+
- spec/integration/dalli_stores_spec.rb
|
166
|
+
- spec/integration/mem_cache_stores_spec.rb
|
167
|
+
- spec/spec_helper.rb
|
168
|
+
homepage: https://github.com/eirc/sane_memcached_ttl
|
169
|
+
licenses:
|
170
|
+
- MIT
|
171
|
+
metadata: {}
|
172
|
+
post_install_message:
|
173
|
+
rdoc_options: []
|
174
|
+
require_paths:
|
175
|
+
- lib
|
176
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
182
|
+
requirements:
|
183
|
+
- - ">="
|
184
|
+
- !ruby/object:Gem::Version
|
185
|
+
version: '0'
|
186
|
+
requirements: []
|
187
|
+
rubyforge_project:
|
188
|
+
rubygems_version: 2.4.2
|
189
|
+
signing_key:
|
190
|
+
specification_version: 4
|
191
|
+
summary: Add sanity to memcached expiration times.
|
192
|
+
test_files:
|
193
|
+
- spec/active_support/cache/couchbase_store_with_sane_ttl_spec.rb
|
194
|
+
- spec/integration/couchbase_stores_spec.rb
|
195
|
+
- spec/integration/dalli_stores_spec.rb
|
196
|
+
- spec/integration/mem_cache_stores_spec.rb
|
197
|
+
- spec/spec_helper.rb
|