Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[marshaling] Automatic object marshaling #19

Merged
merged 13 commits into from
Dec 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
- `AnyCache#cleanup` - remove expired entries manually
(make sence only for `:as_file_store` and `:as_memory_store` at this moment);
- automatic object marshaling (used in `fetch`, `fetch_multi`, `write`, `write_multi`, `read`, `read_multi`):
- used by default (`raw: false`);
- can be disabled via `raw: true` option;
- `raw: true` is required for incrementable/decrementable entries;

## [0.3.1] - 2018-10-08
### Added
Expand Down
62 changes: 47 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -353,10 +353,10 @@ params: INSPECTED_ARGUMENTS and options: INSPECTED_OPTIONS

```ruby
any_cache.write("data", 123, expires_in: 60)
# I, [2018-09-07T10:04:56.649960 #15761] INFO -- [AnyCache<AnyCache>/Activity<write>]: performed <write> operation with params: ["data", 123] and options: {:expires_in=>60}.
# I, [2018-09-07T10:04:56.649960 #15761] INFO -- [AnyCache<AnyCache>/Activity<write>]: performed <write> operation with attributes: ["data", 123] and options: {:expires_in=>60}.

any_cache.clear
# I, [2018-09-07T10:05:26.999847 #15761] INFO -- [AnyCache<AnyCache>/Activity<clear>]: performed <clear> operation with params: [] and options: {}.
# I, [2018-09-07T10:05:26.999847 #15761] INFO -- [AnyCache<AnyCache>/Activity<clear>]: performed <clear> operation with attributes: [] and options: {}.
```

## Operations
Expand All @@ -382,6 +382,7 @@ any_cache.clear
- fetches data from the cache using the given key;
- if a `fallback` block has been passed and data with the given key does not exist - that block
will be called with the given key and the return value will be written to the cache;
- use `raw: true` if you want to fetch incrementable/decrementable entry;

```ruby
# --- entry exists ---
Expand Down Expand Up @@ -416,6 +417,7 @@ cache_store.fetch("data") # => nil
- get a set of entries in hash form from the cache storage using given keys;
- works in `#fetch` manner but with a series of entries;
- nonexistent entries will be fetched with `nil` values;
- use `raw: true` if you want to fetch incrementable/decrementable entries;

```ruby
# --- fetch entries ---
Expand Down Expand Up @@ -451,13 +453,17 @@ cache_store.fetch_multi("data", "second_data", "last_data", force: true) { |key|
### Read

- `AnyCache#read(key)` - get an entry value from the cache storage
- pass `raw: true` if you want to read incrementable/decrementable entries;

```ruby
# --- entry exists ---
cache_store.read("data") # => "some_data"

# --- entry doesnt exist ---
cache_store.read("data") # => nil

# --- read incrementable/decrementable entry ---
cache_store.read("data", raw: true) # => "2" (for example)
```

---
Expand All @@ -467,6 +473,7 @@ cache_store.read("data") # => nil
- `AnyCache#read_multi(*keys)`
- get entries from the cache storage in hash form;
- nonexistent entries will be fetched with `nil` values;
- pass `raw: true` if you want to read incrementable/decrementable entries;

```ruby
cache_store.read_multi("data", "another_data", "last_data", "super_data")
Expand All @@ -477,37 +484,53 @@ cache_store.read_multi("data", "another_data", "last_data", "super_data")
"last_data" => "some_data", # exisitng enry
"super_data" => nil # existing entry
}

# --- read incrementable/decrementable entries ---
cache_store.read_multi("data", "another_data", raw: true)
# => returns
{
"data" => "1",
"another_data" => "2",
}
```

---

### Write

- `AnyCache#write(key, value, [expires_in:])` - write a new entry to the cache storage
- `AnyCache#write(key, value, [expires_in:])` - write a new entry to the cache storage;
- pass `raw: true` if you want to store incrementable/decrementable entries;

```ruby
# --- permanent entry ---
cache_store.write("data", 123)

# --- temporal entry (expires in 60 seconds) ---
cache_store.write("data", 123, expires_in: 60)

# --- incrementable/decrementable entry ---
cache_store.write("data", 123, raw: true)
```

---

### Write Multi

- `AnyCache#write_multi(**entries)` - write a set of permanent entries to the cache storage
- `AnyCache#write_multi(**entries)` - write a set of permanent entries to the cache storage;
- pass `raw: true` if you want to store incrementable/decrementable entries;

```ruby
cache_store.write_multi("data" => "test", "another_data" => 123)

# --- incrementable/decrementable entries ---
cache_store.write_multi("data" => 1, "another_data" => 2, raw: true)
```

---

### Delete

- `AnyCache#delete(key)` - remove entry from the cache storage
- `AnyCache#delete(key)` - remove entry from the cache storage;

```ruby
cache_store.delete("data")
Expand All @@ -519,7 +542,7 @@ cache_store.delete("data")

- `AnyCache#delete_matched(pattern)`
- removes all entries with keys matching the pattern;
- currently unsupported: `:dalli`, `:as_mem_cache_store`, `:as_dalli_Store`;
- currently unsupported: `:dalli`, `:as_mem_cache_store`, `:as_dalli_store`;

```ruby
# --- using a regepx ---
Expand All @@ -534,11 +557,12 @@ cache_store.delete_matched("data")
### Increment

- `AnyCache#increment(key, amount = 1, [expires_in:])` - increment entry's value by the given amount
and set the new expiration time if needed
and set the new expiration time if needed;
- can increment only nonexistent entries OR entries that were written with `raw: true` option;

```ruby
# --- increment existing entry ---
cache_store.write("data", 1)
cache_store.write("data", 1, raw: true) # you must provide :raw => true for incrementable entries

# --- increment by default value (1) ---
cache_store.increment("data") # => 2
Expand All @@ -551,18 +575,22 @@ cache_store.incrmeent("data", expires_in: 31) # => 15

# --- increment nonexistent entry (create new entry) ---
cache_store.increment("another_data", 5, expires_in: 5) # => 5

# --- read incrementable entry ---
cache_store.read("data", raw: true) # you must provide :raw => true for incrementable entries
```

---

### Decrement

- `AnyCache#decrement(key, amount = 1, [expires_in:])` - decrement entry's value by the given amount
and set the new expiration time if needed
and set the new expiration time if needed;
- can decrement only nonexistent entries OR entries that were written with `raw: true` option;

```ruby
# --- decrement existing entry ---
cache_store.write("data", 15)
cache_store.write("data", 15, raw: true) # you must provide :raw => true for decrementable entries

# --- decrement by default value (1) ---
cache_store.decrement("data") # => 14
Expand All @@ -575,13 +603,16 @@ cache_store.decrememnt("data", expirs_in: 5) # => 3

# --- decrement nonexistent entry (create new entry) ---
cache_store.decrememnt("another_data", 2, expires_in: 10) # => -2 (or 0 for Dalli::Client)

# --- read decrementable entry ---
cache_store.read("data", raw: true) # you must provide :raw => true for decrementable entries
```

---

### Expire

- `AnyCache#expire(key, [expires_in:])` - expire entry immediately or set the new expiration time
- `AnyCache#expire(key, [expires_in:])` - expire entry immediately or set the new expiration time;

```ruby
# --- expire immediately ---
Expand All @@ -595,7 +626,7 @@ cache_store.expire("data", expires_in: 36)

### Persist

- `AnyCache#persist(key)` - change entry's expiration time to permanent
- `AnyCache#persist(key)` - change entry's expiration time to permanent;

```ruby
# --- create temporal entry (30 seconds) ---
Expand All @@ -609,7 +640,7 @@ cache_store.persist("data")

### Existence

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

```ruby
# --- entry exists ---
Expand All @@ -623,7 +654,7 @@ cache_store.exist?("another-data") # => false

### Clear

- `AnyCache#clear()` - clear cache database
- `AnyCache#clear()` - clear cache database;

```ruby
# --- prepare cache data ---
Expand All @@ -644,7 +675,8 @@ cache_store.read("another_data") # => nil

### Cleanup

- `AnyCache#cleanup()` - remove expired entries from cache database (make sense only for `:as_file_store` and `:as_memory_store` cache clients)
- `AnyCache#cleanup()` - remove expired entries from cache database
(make sense only for `:as_file_store` and `:as_memory_store` cache clients);

```ruby
# --- prepare cache data ---
Expand Down
2 changes: 1 addition & 1 deletion any_cache.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Gem::Specification.new do |spec|

spec.add_development_dependency 'coveralls', '~> 0.8'
spec.add_development_dependency 'simplecov', '~> 0.16'
spec.add_development_dependency 'armitage-rubocop', '~> 0.12'
spec.add_development_dependency 'armitage-rubocop', '~> 0.13'
spec.add_development_dependency 'rspec', '~> 3.8'

spec.add_development_dependency 'bundler'
Expand Down
2 changes: 1 addition & 1 deletion bin/rspec
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ module AnyCacheSpecRunner
) { run_as_memory_store_cache_specs! }

opts.on(
'--test-as-mem-cache-store',
'--test-as-memcache-store',
'Run specs with ActiveSupport::Cache::MemCacheStore cache storage'
) { run_as_mem_cache_store_cache_specs! }

Expand Down
1 change: 1 addition & 0 deletions lib/any_cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
class AnyCache
require_relative 'any_cache/version'
require_relative 'any_cache/error'
require_relative 'any_cache/dumper'
require_relative 'any_cache/drivers'
require_relative 'any_cache/adapters'
require_relative 'any_cache/logging'
Expand Down
28 changes: 16 additions & 12 deletions lib/any_cache/adapters/active_support_dalli_store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,25 +49,25 @@ def supported_driver?(driver)
def_delegators :driver, :delete, :clear, :cleanup

# @param key [String]
# @param options [Hash]
# @option raw [Boolean]
# @return [void]
#
# @api private
# @since 0.3.0
def read(key, **options)
raw = options.fetch(:raw, true)
raw = options.fetch(:raw, false)

driver.read(key, raw: raw)
end

# @param keys [Array<String>]
# @param options [Hash]
# @option raw [Boolean]
# @return [Hash]
#
# @api private
# @since 0.3.0
def read_multi(*keys, **options)
raw = options.fetch(:raw, true)
raw = options.fetch(:raw, false)

driver.read_multi(*keys, raw: raw).tap do |entries|
entries.merge!(Hash[(keys - entries.keys).zip(READ_MULTI_EMPTY_KEYS_SET)])
Expand All @@ -77,25 +77,26 @@ def read_multi(*keys, **options)
# @param key [String]
# @param value [Object]
# @option expires_in [NilClass, Integer] Time in seconds
# @option raw [Boolean]
# @return [void]
#
# @api private
# @since 0.3.0
def write(key, value, **options)
expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
raw = options.fetch(:raw, true)
raw = options.fetch(:raw, false)

driver.write(key, value, expires_in: expires_in, raw: raw)
end

# @param entries [Hash]
# @param options [Hash]
# @option raw [Boolean]
# @return [void]
#
# @api private
# @since 0.3.0
def write_multi(entries, **options)
raw = options.fetch(:raw, true)
raw = options.fetch(:raw, false)

# NOTE: ActiveSupport::Cache::DalliStore does not support #write_multi :\
entries.each_pair do |key, value|
Expand All @@ -106,6 +107,7 @@ def write_multi(entries, **options)
# @param key [String]
# @option expires_in [Integer]
# @option force [Boolean, Proc]
# @option raw [Boolean]
# @return [Object]
#
# @api private
Expand All @@ -114,8 +116,9 @@ def fetch(key, **options, &fallback)
force_rewrite = options.fetch(:force, false)
force_rewrite = force_rewrite.call(key) if force_rewrite.respond_to?(:call)
expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)
raw = options.fetch(:raw, false)

driver.fetch(key, force: force_rewrite, expires_in: expires_in, &fallback)
driver.fetch(key, force: force_rewrite, expires_in: expires_in, raw: raw, &fallback)
end

# @param keys [Array<String>]
Expand All @@ -142,7 +145,7 @@ def increment(key, amount = DEFAULT_INCR_DECR_AMOUNT, **options)
expires_in = options.fetch(:expires_in, NO_EXPIRATION_TTL)

unless exist?(key)
write(key, amount, expires_in: expires_in) && amount
write(key, amount, expires_in: expires_in, raw: true) && amount
else
driver.increment(key, amount).tap do
expire(key, expires_in: expires_in) if expires_in
Expand All @@ -165,7 +168,8 @@ def decrement(key, amount = DEFAULT_INCR_DECR_AMOUNT, **options)
# - non-raw values;
# - values lower than zero;
# - empty entries;
write(key, INITIAL_DECREMNETED_VALUE, expires_in: expires_in) && INITIAL_DECREMNETED_VALUE
write(key, INITIAL_DECREMNETED_VALUE, expires_in: expires_in, raw: true)
INITIAL_DECREMNETED_VALUE
else
driver.decrement(key, amount).tap do
expire(key, expires_in: expires_in) if expires_in
Expand All @@ -190,9 +194,9 @@ def delete_matched(pattern, **options)
# @api private
# @since 0.3.0
def expire(key, expires_in: DEAD_TTL)
read(key).tap do |value|
read(key, raw: true).tap do |value|
is_alive = expires_in ? expires_in.positive? : false
is_alive ? write(key, value, expires_in: expires_in) : delete(key)
is_alive ? write(key, value, expires_in: expires_in, raw: true) : delete(key)
end
end

Expand Down
Loading