Skip to content

Commit

Permalink
Merge 6a987ce into 46b7faf
Browse files Browse the repository at this point in the history
  • Loading branch information
0exp committed Sep 1, 2018
2 parents 46b7faf + 6a987ce commit 959f6d6
Show file tree
Hide file tree
Showing 11 changed files with 122 additions and 5 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
All notable changes to this project will be documented in this file.

## [Unreleased]
- existence operation `AnyCache#exist?(key)` - determine if an entry exists or not;
- support for `ActiveSupport::Cache::MemCacheStore`;
- configuration layer `AnyCache.configure`: an ability to choose and configure a necessary cache client
without any explicit client object instantiation (client object will be instantiated implicitly);
Expand Down
19 changes: 18 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# AnyCache · [![Gem Version](https://badge.fury.io/rb/any_cache.svg)](https://badge.fury.io/rb/any_cache) [![Build Status](https://travis-ci.org/0exp/any_cache.svg?branch=master)](https://travis-ci.org/0exp/any_cache) [![Coverage Status](https://coveralls.io/repos/github/0exp/any_cache/badge.svg)](https://coveralls.io/github/0exp/any_cache)

AnyCache - a simplest cache wrapper that provides a minimalistic generic interface for all well-known cache storages and includes a minimal set of necessary operations:
`read`, `write`, `delete`, `expire`, `persist`, `clear`, `increment`, `decrement`.
`read`, `write`, `delete`, `expire`, `persist`, `exist?`, `clear`, `increment`, `decrement`.

Supported clients:

Expand Down Expand Up @@ -55,6 +55,7 @@ require 'any_cache'
- [Decrement](#decrement)
- [Expire](#expire)
- [Persist](#persist)
- [Existence](#existence)
- [Clear](#clear)

---
Expand Down Expand Up @@ -234,6 +235,7 @@ If you want to use your own cache client implementation, you should provide an o
- `#decrement(key, amount, [**options])` ([doc](#decrement))
- `#expire(key, [**options])` ([doc](#expire))
- `#persist(key, [**options])` ([doc](#persist))
- `#exist?(key, [**options])` ([doc](#existence))
- `#clear([**options])` ([doc](#clear))

```ruby
Expand Down Expand Up @@ -266,6 +268,7 @@ AnyCache.build(MyCacheClient.new)
- [expire](#expire)
- [persist](#persist)
- [clear](#clear)
- [exist?](#existence)

---

Expand Down Expand Up @@ -383,6 +386,20 @@ any_cache.persist("data")

---

### Existence

- `AnyCache#exist?(key)` - determine if an entry exists

```ruby
# --- entry exists ---
any_cache.exist?("data") # => true

# --- entry does not exist ---
any_cache.exist?("another-data") # => false
```

---

### Clear

- `AnyCache#clear()` - clear cache database
Expand Down
3 changes: 2 additions & 1 deletion lib/any_cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ def build(driver = Drivers.build(config))
:decrement,
:expire,
:persist,
:clear
:clear,
:exist?

# @return [AnyCache::Adapters::Basic]
#
Expand Down
10 changes: 10 additions & 0 deletions lib/any_cache/adapters/active_support_mem_cache_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -133,5 +133,15 @@ def expire(key, expires_in: DEAD_TTL)
def persist(key, **options)
read(key).tap { |value| write(key, value) }
end

# @param key [String]
# @param options [Hash]
# @return [Boolean]
#
# @api private
# @since 0.2.0
def exist?(key, **options)
driver.exist?(key)
end
end
end
10 changes: 10 additions & 0 deletions lib/any_cache/adapters/active_support_naive_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,16 @@ def persist(key, **options)
lock.with_write_lock { pers_operation.call(key) }
end

# @param key [String]
# @param options [Hash]
# @return [Boolean]
#
# @api private
# @since 0.2.0
def exist?(key, **options)
lock.with_read_lock { super }
end

private

# @return [Concurrent::ReentrantReadWriteLock]
Expand Down
10 changes: 10 additions & 0 deletions lib/any_cache/adapters/active_support_redis_cache_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,15 @@ def expire(key, expires_in: DEAD_TTL)
def persist(key, **options)
read(key).tap { |value| write(key, value) }
end

# @param key [String]
# @param options [Hash]
# @return [Boolean]
#
# @api private
# @since 0.2.0
def exist?(key, **options)
driver.exist?(key)
end
end
end
10 changes: 10 additions & 0 deletions lib/any_cache/adapters/basic.rb
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,15 @@ def persist(key, **options)
def clear(**options)
raise NotImplementedError
end

# @param key [String]
# @param options [Hash]
# @return [Boolean]
#
# @api private
# @since 0.2.0
def exist?(key, **options)
raise NotImplementedError
end
end
end
10 changes: 10 additions & 0 deletions lib/any_cache/adapters/dalli.rb
Original file line number Diff line number Diff line change
Expand Up @@ -136,5 +136,15 @@ def persist(key, **options)
def clear(**options)
flush(0) # NOTE: 0 is a flush delay
end

# @param key [String]
# @param options [Hash]
# @return [Boolean]
#
# @api private
# @since 0.2.0
def exist?(key, **options)
!get(key).nil? # NOTE: can conflict with :cache_nils Dalli::Client option
end
end
end
6 changes: 4 additions & 2 deletions lib/any_cache/adapters/delegator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ def supported_driver?(driver)
driver.respond_to?(:decrement) &&
driver.respond_to?(:expire) &&
driver.respond_to?(:persist) &&
driver.respond_to?(:clear)
driver.respond_to?(:clear) &&
driver.respond_to?(:exist?)
end
end

Expand All @@ -31,6 +32,7 @@ def supported_driver?(driver)
:decrement,
:expire,
:persist,
:clear
:clear,
:exist?
end
end
13 changes: 12 additions & 1 deletion lib/any_cache/adapters/redis.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ def supported_driver?(driver)
:incrby,
:decrby,
:pipelined,
:flushdb
:flushdb,
:exists

# @param key [String]
# @param options [Hash]
Expand Down Expand Up @@ -147,5 +148,15 @@ def persist(key, **options)
def clear(**options)
flushdb
end

# @param key [String]
# @param options [Hash]
# @return [Boolean]
#
# @api private
# @since 0.2.0
def exist?(key, **options)
exists(key)
end
end
end
35 changes: 35 additions & 0 deletions spec/features/exist_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

describe 'Operation: #exist?' do
after { cache_store.clear }

let(:cache_store) { build_cache_store }
let(:expiration_time) { 8 } # NOTE: in seconds
let(:entry) { { key: SecureRandom.hex, value: SecureRandom.hex(4) } }

context 'entry with expiration time' do
before { cache_store.write(entry[:key], entry[:value], expires_in: expiration_time) }

specify 'returns corresponding value (exists => true, does not exist => false)' do
expect(cache_store.exist?(entry[:key])).to eq(true)

sleep(expiration_time + 1)

expect(cache_store.exist?(entry[:key])).to eq(false)
end
end

context 'when entry exists' do
before { cache_store.write(entry[:key], entry[:value]) }

it 'returns true' do
expect(cache_store.exist?(entry[:key])).to eq(true)
end
end

context 'when entry does not exist' do
it 'returns false' do
expect(cache_store.exist?(entry[:key])).to eq(false)
end
end
end

0 comments on commit 959f6d6

Please sign in to comment.