legion-cache 1.3.11 → 1.3.13
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 +4 -4
- data/CHANGELOG.md +13 -0
- data/CLAUDE.md +10 -4
- data/README.md +15 -1
- data/lib/legion/cache/memory.rb +89 -0
- data/lib/legion/cache/version.rb +1 -1
- data/lib/legion/cache.rb +22 -2
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bb361d980bfc1761a6ea272c5225a1a1c33389ea8a15f87a1496354fb6f62390
|
|
4
|
+
data.tar.gz: f70347db3d1b7c2e849d7b31b3c456c992f776d9db0f16d801d1c0cb824160bb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4b96a2ebb1066ace5026f7376e3c6e2788d9a744dd28e675d01e37539b02ad9cad5e18b9dd69172f2986b28742659b205d9e23708b0c1d0885a64149a1e80a4f
|
|
7
|
+
data.tar.gz: 4b45f7bc7d8ccca724d41e86899365db9ee08e1357052e70b46620752e0a91916f47372c33d11ae6ab38967c8f3ea028c2f25ee3687a29dfc0560bfb49e84f9b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.3.13] - 2026-03-24
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- Reindex docs: update CLAUDE.md and README with Memory adapter and Helper mixin docs
|
|
7
|
+
|
|
8
|
+
## [1.3.12] - 2026-03-24
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `Legion::Cache::Memory` adapter module for lite mode: pure in-memory cache with TTL expiry and thread-safe Mutex synchronization
|
|
12
|
+
- Cache `setup` auto-detects `LEGION_MODE=lite` and activates Memory adapter, skipping Redis/Memcached
|
|
13
|
+
- `@using_memory` flag routes `get`/`set`/`fetch`/`delete`/`flush` through Memory adapter
|
|
14
|
+
- `shutdown` cleanly tears down Memory adapter when active
|
|
15
|
+
|
|
3
16
|
## [1.3.11] - 2026-03-22
|
|
4
17
|
|
|
5
18
|
### Added
|
data/CLAUDE.md
CHANGED
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
Caching wrapper for the LegionIO framework. Provides a consistent interface for Memcached (via `dalli`) and Redis (via `redis` gem) with connection pooling. Driver selection is config-driven.
|
|
9
9
|
|
|
10
10
|
**GitHub**: https://github.com/LegionIO/legion-cache
|
|
11
|
-
**Version**: 1.3.
|
|
11
|
+
**Version**: 1.3.12
|
|
12
12
|
**License**: Apache-2.0
|
|
13
13
|
|
|
14
14
|
## Architecture
|
|
15
15
|
|
|
16
16
|
```
|
|
17
17
|
Legion::Cache (singleton module)
|
|
18
|
-
├── .setup(**opts) # Connect to cache backend
|
|
18
|
+
├── .setup(**opts) # Connect to cache backend (auto-detects LEGION_MODE=lite -> Memory adapter)
|
|
19
19
|
├── .get(key) # Retrieve cached value
|
|
20
20
|
├── .fetch(key, ttl) # Get with block/TTL support (Memcached only; alias for get on Redis)
|
|
21
21
|
├── .set(key, value, ttl) # Store value with optional TTL (positional on Memcached, keyword on Redis)
|
|
@@ -25,9 +25,10 @@ Legion::Cache (singleton module)
|
|
|
25
25
|
├── .size # Total pool connections
|
|
26
26
|
├── .available # Idle pool connections
|
|
27
27
|
├── .restart(**opts) # Close and reconnect pool with optional new opts
|
|
28
|
-
├── .shutdown # Close connections, mark disconnected
|
|
28
|
+
├── .shutdown # Close connections, mark disconnected (handles Memory adapter)
|
|
29
29
|
├── .local # Accessor for Legion::Cache::Local
|
|
30
30
|
├── .using_local? # Whether fallback to local is active
|
|
31
|
+
├── .using_memory? # Whether Memory adapter (lite mode) is active
|
|
31
32
|
│
|
|
32
33
|
├── Memcached # Dalli-based Memcached driver (default)
|
|
33
34
|
│ └── Uses connection_pool for thread safety
|
|
@@ -35,6 +36,9 @@ Legion::Cache (singleton module)
|
|
|
35
36
|
├── Redis # Redis driver
|
|
36
37
|
│ └── Uses connection_pool for thread safety
|
|
37
38
|
│ └── Default pool_size is 20 (Memcached default is 10)
|
|
39
|
+
├── Memory # Lite mode adapter: pure in-memory cache, TTL expiry, Mutex thread-safety
|
|
40
|
+
│ └── Activated by LEGION_MODE=lite env var; no Redis/Memcached required
|
|
41
|
+
├── Helper # Injectable cache mixin for LEX extensions (namespaced cache_*/local_cache_*)
|
|
38
42
|
├── Local # Local cache tier (localhost Redis/Memcached, fallback target)
|
|
39
43
|
│ ├── .setup # Connect to local cache server (auto-detect driver)
|
|
40
44
|
│ ├── .shutdown # Close local connection
|
|
@@ -124,9 +128,11 @@ Dalli enforces a 1MB client-side limit by default (`value_max_bytes: 1_048_576`)
|
|
|
124
128
|
|
|
125
129
|
| Path | Purpose |
|
|
126
130
|
|------|---------|
|
|
127
|
-
| `lib/legion/cache.rb` | Module entry, driver selection, setup/shutdown, fallback wiring |
|
|
131
|
+
| `lib/legion/cache.rb` | Module entry, driver selection, setup/shutdown, fallback wiring, Memory adapter activation |
|
|
128
132
|
| `lib/legion/cache/memcached.rb` | Dalli/Memcached driver implementation |
|
|
129
133
|
| `lib/legion/cache/redis.rb` | Redis driver implementation |
|
|
134
|
+
| `lib/legion/cache/memory.rb` | Lite mode Memory adapter: in-memory store with TTL + Mutex thread-safety |
|
|
135
|
+
| `lib/legion/cache/helper.rb` | Injectable cache mixin for LEX extensions |
|
|
130
136
|
| `lib/legion/cache/local.rb` | Local cache tier (localhost, fallback target) |
|
|
131
137
|
| `lib/legion/cache/pool.rb` | Connection pool management |
|
|
132
138
|
| `lib/legion/cache/settings.rb` | Default configuration + local defaults |
|
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Caching wrapper for the [LegionIO](https://github.com/LegionIO/LegionIO) framework. Provides a consistent interface for Memcached (via `dalli`) and Redis (via `redis` gem) with connection pooling. Driver selection is config-driven.
|
|
4
4
|
|
|
5
|
-
**Version**: 1.3.
|
|
5
|
+
**Version**: 1.3.12
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
@@ -40,6 +40,20 @@ Legion::Cache.flush # flushdb
|
|
|
40
40
|
Legion::Cache.shutdown
|
|
41
41
|
```
|
|
42
42
|
|
|
43
|
+
## Lite Mode (No Infrastructure)
|
|
44
|
+
|
|
45
|
+
When `LEGION_MODE=lite` is set, `Legion::Cache` activates the pure in-memory `Memory` adapter, bypassing Redis and Memcached entirely:
|
|
46
|
+
|
|
47
|
+
```ruby
|
|
48
|
+
ENV['LEGION_MODE'] = 'lite'
|
|
49
|
+
Legion::Cache.setup
|
|
50
|
+
Legion::Cache.using_memory? # => true
|
|
51
|
+
Legion::Cache.set('key', 'value', 60)
|
|
52
|
+
Legion::Cache.get('key') # => 'value'
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The Memory adapter is thread-safe (Mutex), supports TTL expiry, and exposes the same `get`/`set`/`fetch`/`delete`/`flush` interface. Shutdown cleanly tears it down.
|
|
56
|
+
|
|
43
57
|
## Two-Tier Cache
|
|
44
58
|
|
|
45
59
|
Legion::Cache supports a two-tier architecture: a shared remote cluster and a local per-machine cache. If the shared cluster is unreachable at setup, all operations transparently fall back to local.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Cache
|
|
5
|
+
module Memory
|
|
6
|
+
extend self
|
|
7
|
+
|
|
8
|
+
@store = {}
|
|
9
|
+
@expiry = {}
|
|
10
|
+
@mutex = Mutex.new
|
|
11
|
+
@connected = false
|
|
12
|
+
|
|
13
|
+
def setup(**)
|
|
14
|
+
@connected = true
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def client(**) = self
|
|
18
|
+
|
|
19
|
+
def connected?
|
|
20
|
+
@connected
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def get(key)
|
|
24
|
+
@mutex.synchronize do
|
|
25
|
+
expire_if_needed(key)
|
|
26
|
+
@store[key]
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def set(key, value, ttl = nil)
|
|
31
|
+
@mutex.synchronize do
|
|
32
|
+
@store[key] = value
|
|
33
|
+
@expiry[key] = Time.now + ttl if ttl&.positive?
|
|
34
|
+
value
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def fetch(key, ttl = nil)
|
|
39
|
+
val = get(key)
|
|
40
|
+
return val unless val.nil?
|
|
41
|
+
|
|
42
|
+
val = yield if block_given?
|
|
43
|
+
set(key, val, ttl)
|
|
44
|
+
val
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def delete(key)
|
|
48
|
+
@mutex.synchronize do
|
|
49
|
+
@store.delete(key)
|
|
50
|
+
@expiry.delete(key)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def flush(_delay = 0)
|
|
55
|
+
@mutex.synchronize do
|
|
56
|
+
@store.clear
|
|
57
|
+
@expiry.clear
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def close = nil
|
|
62
|
+
|
|
63
|
+
def shutdown
|
|
64
|
+
flush
|
|
65
|
+
@connected = false
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def reset!
|
|
69
|
+
@mutex.synchronize do
|
|
70
|
+
@store.clear
|
|
71
|
+
@expiry.clear
|
|
72
|
+
@connected = false
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def size = 1
|
|
77
|
+
def available = 1
|
|
78
|
+
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def expire_if_needed(key)
|
|
82
|
+
return unless @expiry.key?(key) && Time.now > @expiry[key]
|
|
83
|
+
|
|
84
|
+
@store.delete(key)
|
|
85
|
+
@expiry.delete(key)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
data/lib/legion/cache/version.rb
CHANGED
data/lib/legion/cache.rb
CHANGED
|
@@ -6,6 +6,7 @@ require 'legion/cache/cacheable'
|
|
|
6
6
|
|
|
7
7
|
require 'legion/cache/memcached'
|
|
8
8
|
require 'legion/cache/redis'
|
|
9
|
+
require 'legion/cache/memory'
|
|
9
10
|
require 'legion/cache/local'
|
|
10
11
|
require 'legion/cache/helper'
|
|
11
12
|
|
|
@@ -21,15 +22,29 @@ module Legion
|
|
|
21
22
|
def setup(**)
|
|
22
23
|
return Legion::Settings[:cache][:connected] = true if connected?
|
|
23
24
|
|
|
25
|
+
if ENV['LEGION_MODE'] == 'lite'
|
|
26
|
+
Legion::Cache::Memory.setup
|
|
27
|
+
@using_memory = true
|
|
28
|
+
@connected = true
|
|
29
|
+
Legion::Settings[:cache][:connected] = true
|
|
30
|
+
Legion::Logging.info 'Legion::Cache using in-memory adapter (lite mode)' if defined?(Legion::Logging)
|
|
31
|
+
return
|
|
32
|
+
end
|
|
33
|
+
|
|
24
34
|
setup_local
|
|
25
35
|
setup_shared(**)
|
|
26
36
|
end
|
|
27
37
|
|
|
28
38
|
def shutdown
|
|
29
39
|
Legion::Logging.info 'Shutting down Legion::Cache'
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
if @using_memory
|
|
41
|
+
Legion::Cache::Memory.shutdown
|
|
42
|
+
else
|
|
43
|
+
close unless @using_local
|
|
44
|
+
Legion::Cache::Local.shutdown if Legion::Cache::Local.connected?
|
|
45
|
+
end
|
|
32
46
|
@using_local = false
|
|
47
|
+
@using_memory = false
|
|
33
48
|
@connected = false
|
|
34
49
|
Legion::Settings[:cache][:connected] = false
|
|
35
50
|
end
|
|
@@ -43,30 +58,35 @@ module Legion
|
|
|
43
58
|
end
|
|
44
59
|
|
|
45
60
|
def get(key)
|
|
61
|
+
return Legion::Cache::Memory.get(key) if @using_memory
|
|
46
62
|
return Legion::Cache::Local.get(key) if @using_local
|
|
47
63
|
|
|
48
64
|
super
|
|
49
65
|
end
|
|
50
66
|
|
|
51
67
|
def set(key, value, ttl = 180)
|
|
68
|
+
return Legion::Cache::Memory.set(key, value, ttl) if @using_memory
|
|
52
69
|
return Legion::Cache::Local.set(key, value, ttl) if @using_local
|
|
53
70
|
|
|
54
71
|
super
|
|
55
72
|
end
|
|
56
73
|
|
|
57
74
|
def fetch(key, ttl = nil)
|
|
75
|
+
return Legion::Cache::Memory.fetch(key, ttl) if @using_memory
|
|
58
76
|
return Legion::Cache::Local.fetch(key, ttl) if @using_local
|
|
59
77
|
|
|
60
78
|
super
|
|
61
79
|
end
|
|
62
80
|
|
|
63
81
|
def delete(key)
|
|
82
|
+
return Legion::Cache::Memory.delete(key) if @using_memory
|
|
64
83
|
return Legion::Cache::Local.delete(key) if @using_local
|
|
65
84
|
|
|
66
85
|
super
|
|
67
86
|
end
|
|
68
87
|
|
|
69
88
|
def flush(delay = 0)
|
|
89
|
+
return Legion::Cache::Memory.flush(delay) if @using_memory
|
|
70
90
|
return Legion::Cache::Local.flush(delay) if @using_local
|
|
71
91
|
|
|
72
92
|
super
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: legion-cache
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.3.
|
|
4
|
+
version: 1.3.13
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
@@ -104,6 +104,7 @@ files:
|
|
|
104
104
|
- lib/legion/cache/helper.rb
|
|
105
105
|
- lib/legion/cache/local.rb
|
|
106
106
|
- lib/legion/cache/memcached.rb
|
|
107
|
+
- lib/legion/cache/memory.rb
|
|
107
108
|
- lib/legion/cache/pool.rb
|
|
108
109
|
- lib/legion/cache/redis.rb
|
|
109
110
|
- lib/legion/cache/settings.rb
|