legion-cache 1.3.15 → 1.3.17

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8d143549258e7e7a2ec8d3ff702a724eb98648582a442c594bd8df360f8fd1c5
4
- data.tar.gz: cff229d7de54b78aa9b3995a8fa9d5877e059ab32059fadb786b786357fbebaf
3
+ metadata.gz: 2d0de0aa53a2886b16a2d2e10bb18e37128a0e0d50d118d689c8f87aa15fcb72
4
+ data.tar.gz: 49387e7f795a779e595b700c2afe8eda19b7bc0e07273306ae57ca9ec71b2782
5
5
  SHA512:
6
- metadata.gz: 073ea47e6e2c886388fa980f490cf395bbfe3be1a90129cc3d804ea5df36d7c8ee814e725e1bcaae94b35d840c0729b47ab5181d5c7f12581e2c3664d76a74b3
7
- data.tar.gz: 82599629d8df3d385c96001321e55c123670154cbc72e243ded365d4f22d93dc085e19bfa2605fb377fab69e0be21291d46937450702d1b4a70860e41d06efde
6
+ metadata.gz: af05e3b8f771a81307f9c3fb81c6dcb6a9fad154bd127660d71a9e645c44636fb1317ef70db618fa5e139fb617d012747bb477017226b829cc5d26ff3db6cd5a
7
+ data.tar.gz: 0e31e8c387e44ff1c8e4089cabd04536df39e373cbc38bc90dc1beba85b080d92d77887ee1f4faccf4ef96bb0a02bc51d43bdebda53231e627d26f57e014775f
@@ -0,0 +1,7 @@
1
+ # Auto-generated from team-config.yml
2
+ # Team: core
3
+ #
4
+ # To apply: scripts/apply-codeowners.sh legion-cache
5
+
6
+ * @LegionIO/maintainers
7
+ * @LegionIO/core
@@ -0,0 +1,18 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: /
5
+ schedule:
6
+ interval: weekly
7
+ day: monday
8
+ open-pull-requests-limit: 5
9
+ labels:
10
+ - "type:dependencies"
11
+ - package-ecosystem: github-actions
12
+ directory: /
13
+ schedule:
14
+ interval: weekly
15
+ day: monday
16
+ open-pull-requests-limit: 5
17
+ labels:
18
+ - "type:dependencies"
@@ -3,6 +3,8 @@ on:
3
3
  push:
4
4
  branches: [main]
5
5
  pull_request:
6
+ schedule:
7
+ - cron: '0 9 * * 1'
6
8
 
7
9
  jobs:
8
10
  ci:
@@ -11,9 +13,25 @@ jobs:
11
13
  needs-redis: true
12
14
  needs-memcached: true
13
15
 
16
+ lint:
17
+ uses: LegionIO/.github/.github/workflows/lint-patterns.yml@main
18
+
19
+ security:
20
+ uses: LegionIO/.github/.github/workflows/security-scan.yml@main
21
+
22
+ version-changelog:
23
+ uses: LegionIO/.github/.github/workflows/version-changelog.yml@main
24
+
25
+ dependency-review:
26
+ uses: LegionIO/.github/.github/workflows/dependency-review.yml@main
27
+
28
+ stale:
29
+ if: github.event_name == 'schedule'
30
+ uses: LegionIO/.github/.github/workflows/stale.yml@main
31
+
14
32
  release:
15
- needs: ci
33
+ needs: [ci, lint]
16
34
  if: github.event_name == 'push' && github.ref == 'refs/heads/main'
17
35
  uses: LegionIO/.github/.github/workflows/release.yml@main
18
36
  secrets:
19
- rubygems-api-key: ${{ secrets.RUBYGEMS_API_KEY }}
37
+ rubygems-api-key: ${{ secrets.RUBYGEMS_API_KEY }}
data/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # Changelog
2
2
 
3
+ ## [Unreleased]
4
+
5
+ ## [1.3.17] - 2026-03-25
6
+
7
+ ### Added
8
+ - `Legion::Cache::RedisHash` module: Redis hash and sorted-set operations (`hset`, `hgetall`, `hdel`, `zadd`, `zrangebyscore`, `zrem`, `expire`) with `redis_available?` guard and safe defaults when Redis is not connected
9
+ - Auto-required from `legion/cache.rb` alongside the existing Redis adapter
10
+
11
+ ## [1.3.16] - 2026-03-25
12
+
13
+ ### Fixed
14
+ - Accept ttl as positional or keyword argument in Cache.set for caller flexibility
15
+ - Align Redis.set signature to positional ttl arg matching parent module convention
16
+
3
17
  ## [1.3.15] - 2026-03-24
4
18
 
5
19
  ### Added
data/CLAUDE.md CHANGED
@@ -56,7 +56,7 @@ Legion::Cache (singleton module)
56
56
  - **Driver Selection at Load Time**: `Legion::Settings[:cache][:driver]` determines which module gets `extend`ed into `Legion::Cache` (`'redis'` or `'dalli'`)
57
57
  - **Connection Pooling**: Both drivers use `connection_pool` gem for thread-safe access
58
58
  - **Unified Interface**: Same `get`/`set`/`delete`/`flush`/`connected?`/`shutdown` methods regardless of backend
59
- - **TTL Signature Difference**: Memcached `set(key, value, ttl)` uses a positional TTL (default 180s); Redis `set(key, value, ttl: nil)` uses a keyword TTL
59
+ - **Uniform TTL Signature**: All backends use `set(key, value, ttl)` with a positional TTL argument (Memcached default 180s, Redis/Memory/Local default nil)
60
60
 
61
61
  ### Two-Tier Cache Architecture
62
62
 
data/README.md CHANGED
@@ -31,8 +31,8 @@ Legion::Cache.fetch('foobar') # => 'testing' (get with block support)
31
31
  Legion::Cache.delete('foobar') # => true
32
32
  Legion::Cache.flush # flush all keys
33
33
 
34
- # Redis driver — TTL is a keyword argument
35
- Legion::Cache.set('foobar', 'testing', ttl: 10)
34
+ # Redis driver — TTL is the third positional argument
35
+ Legion::Cache.set('foobar', 'testing', 10)
36
36
  Legion::Cache.get('foobar') # => 'testing'
37
37
  Legion::Cache.delete('foobar') # => true
38
38
  Legion::Cache.flush # flushdb
@@ -68,7 +68,7 @@ module Legion
68
68
  end
69
69
  alias fetch get
70
70
 
71
- def set(key, value, ttl: nil)
71
+ def set(key, value, ttl = nil)
72
72
  args = {}
73
73
  args[:ex] = ttl unless ttl.nil?
74
74
  result = client.with { |conn| conn.set(key, value, **args) == 'OK' }
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Cache
5
+ module RedisHash
6
+ module_function
7
+
8
+ # Returns true when the Redis driver is loaded and the connection pool is live.
9
+ def redis_available?
10
+ pool = Legion::Cache.instance_variable_get(:@client)
11
+ return false if pool.nil?
12
+
13
+ Legion::Cache.connected?
14
+ rescue StandardError
15
+ false
16
+ end
17
+
18
+ # Set hash fields from a Ruby Hash.
19
+ # Uses Redis HSET key field value [field value ...]
20
+ def hset(key, hash)
21
+ return false unless redis_available?
22
+
23
+ Legion::Cache.instance_variable_get(:@client).with do |conn|
24
+ flat = hash.flat_map { |k, v| [k.to_s, v.to_s] }
25
+ conn.hset(key, *flat)
26
+ end
27
+ true
28
+ rescue StandardError => e
29
+ log_redis_error('hset', e)
30
+ false
31
+ end
32
+
33
+ # Returns a Ruby Hash (string keys) of all field-value pairs for the key.
34
+ def hgetall(key)
35
+ return nil unless redis_available?
36
+
37
+ Legion::Cache.instance_variable_get(:@client).with do |conn|
38
+ conn.hgetall(key)
39
+ end
40
+ rescue StandardError => e
41
+ log_redis_error('hgetall', e)
42
+ nil
43
+ end
44
+
45
+ # Delete one or more hash fields.
46
+ def hdel(key, *fields)
47
+ return 0 unless redis_available?
48
+
49
+ Legion::Cache.instance_variable_get(:@client).with do |conn|
50
+ conn.hdel(key, *fields)
51
+ end
52
+ rescue StandardError => e
53
+ log_redis_error('hdel', e)
54
+ 0
55
+ end
56
+
57
+ # Add a member to a sorted set with the given score.
58
+ def zadd(key, score, member)
59
+ return false unless redis_available?
60
+
61
+ Legion::Cache.instance_variable_get(:@client).with do |conn|
62
+ conn.zadd(key, score.to_f, member.to_s)
63
+ end
64
+ true
65
+ rescue StandardError => e
66
+ log_redis_error('zadd', e)
67
+ false
68
+ end
69
+
70
+ # Range query on a sorted set by score. Returns an array of members.
71
+ # limit: accepts [offset, count] array matching Redis LIMIT semantics.
72
+ def zrangebyscore(key, min, max, limit: nil)
73
+ return [] unless redis_available?
74
+
75
+ opts = {}
76
+ opts[:limit] = limit if limit
77
+
78
+ Legion::Cache.instance_variable_get(:@client).with do |conn|
79
+ conn.zrangebyscore(key, min, max, **opts)
80
+ end
81
+ rescue StandardError => e
82
+ log_redis_error('zrangebyscore', e)
83
+ []
84
+ end
85
+
86
+ # Remove a member from a sorted set.
87
+ def zrem(key, member)
88
+ return false unless redis_available?
89
+
90
+ Legion::Cache.instance_variable_get(:@client).with do |conn|
91
+ conn.zrem(key, member.to_s)
92
+ end
93
+ true
94
+ rescue StandardError => e
95
+ log_redis_error('zrem', e)
96
+ false
97
+ end
98
+
99
+ # Set a TTL (in seconds) on a key.
100
+ def expire(key, seconds)
101
+ return false unless redis_available?
102
+
103
+ Legion::Cache.instance_variable_get(:@client).with do |conn|
104
+ conn.expire(key, seconds.to_i) == 1
105
+ end
106
+ rescue StandardError => e
107
+ log_redis_error('expire', e)
108
+ false
109
+ end
110
+
111
+ def log_redis_error(method, error)
112
+ return unless defined?(Legion::Logging)
113
+
114
+ Legion::Logging.warn "[cache:redis_hash] #{method} failed: #{error.class} — #{error.message}"
115
+ end
116
+ end
117
+ end
118
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module Cache
5
- VERSION = '1.3.15'
5
+ VERSION = '1.3.17'
6
6
  end
7
7
  end
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/redis_hash'
9
10
  require 'legion/cache/memory'
10
11
  require 'legion/cache/local'
11
12
  require 'legion/cache/helper'
@@ -79,8 +80,9 @@ module Legion
79
80
  [ttl, max].min
80
81
  end
81
82
 
82
- def set(key, value, ttl = 180, **)
83
- effective_ttl = enforce_phi_ttl(ttl, **)
83
+ def set(key, value, ttl = nil, **opts)
84
+ ttl = opts.delete(:ttl) || ttl || 180
85
+ effective_ttl = enforce_phi_ttl(ttl, **opts)
84
86
  return Legion::Cache::Memory.set(key, value, effective_ttl) if @using_memory
85
87
  return Legion::Cache::Local.set(key, value, effective_ttl) if @using_local
86
88
 
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.15
4
+ version: 1.3.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -90,6 +90,8 @@ extra_rdoc_files:
90
90
  - LICENSE
91
91
  - README.md
92
92
  files:
93
+ - ".github/CODEOWNERS"
94
+ - ".github/dependabot.yml"
93
95
  - ".github/workflows/ci.yml"
94
96
  - ".gitignore"
95
97
  - ".rubocop.yml"
@@ -107,6 +109,7 @@ files:
107
109
  - lib/legion/cache/memory.rb
108
110
  - lib/legion/cache/pool.rb
109
111
  - lib/legion/cache/redis.rb
112
+ - lib/legion/cache/redis_hash.rb
110
113
  - lib/legion/cache/settings.rb
111
114
  - lib/legion/cache/version.rb
112
115
  - sonar-project.properties