Skip to content

Commit 94124d1

Browse files
authored
Harden Redis store semantics and align CI/tooling (#3)
* Harden Redis store semantics and align CI/tooling * timecop pin * updated LuckyCache::Cacheable naming
1 parent c90dbd8 commit 94124d1

8 files changed

Lines changed: 369 additions & 253 deletions

File tree

.github/workflows/ci.yml

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,13 @@ on:
44
push:
55
branches: [main]
66
pull_request:
7-
branches: "*"
87

98
jobs:
109
check_format:
11-
strategy:
12-
fail-fast: false
1310
runs-on: ubuntu-latest
14-
continue-on-error: false
1511
steps:
1612
- name: Download source
17-
uses: actions/checkout@v3
13+
uses: actions/checkout@v4
1814
- name: Install Crystal
1915
uses: crystal-lang/install-crystal@v1
2016
- name: Install shards
@@ -23,17 +19,15 @@ jobs:
2319
run: crystal tool format --check
2420
- name: Lint
2521
run: ./bin/ameba
22+
- name: Build shard entrypoint
23+
run: crystal build src/lucky_cache_redis_store.cr
24+
2625
specs:
2726
strategy:
2827
fail-fast: false
2928
matrix:
30-
os: [ubuntu-latest, windows-latest]
31-
crystal_version: [latest]
32-
include:
33-
- os: ubuntu-latest
34-
crystal_version: 1.4.0
35-
runs-on: ${{ matrix.os }}
36-
continue-on-error: false
29+
crystal_version: ["1.16.3", latest]
30+
runs-on: ubuntu-latest
3731
services:
3832
redis:
3933
image: redis:7-alpine
@@ -45,11 +39,11 @@ jobs:
4539
ports:
4640
- 6379:6379
4741
steps:
48-
- uses: actions/checkout@v3
42+
- uses: actions/checkout@v4
4943
- uses: crystal-lang/install-crystal@v1
5044
with:
5145
crystal: ${{ matrix.crystal_version }}
5246
- name: Install dependencies
5347
run: shards install --skip-postinstall --skip-executables
5448
- name: Run tests
55-
run: crystal spec
49+
run: crystal spec

.github/workflows/docs.yml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@ on:
77
jobs:
88
deploy:
99
runs-on: ubuntu-latest
10+
permissions:
11+
contents: write
1012
steps:
11-
- uses: actions/checkout@v2
13+
- uses: actions/checkout@v4
1214
with:
1315
persist-credentials: false
1416
- uses: crystal-lang/install-crystal@v1
@@ -17,7 +19,7 @@ jobs:
1719
- name: "Generate docs"
1820
run: crystal docs
1921
- name: Deploy to GitHub Pages
20-
uses: peaceiris/actions-gh-pages@v3
22+
uses: peaceiris/actions-gh-pages@v4
2123
with:
2224
github_token: ${{ secrets.GITHUB_TOKEN }}
23-
publish_dir: ./docs
25+
publish_dir: ./docs

README.md

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ A Redis storage backend for [LuckyCache](https://github.com/luckyframework/lucky
88

99
```yaml
1010
dependencies:
11-
lucky_cache:
12-
github: luckyframework/lucky_cache
1311
lucky_cache_redis_store:
1412
github: luckyframework/lucky_cache_redis_store
1513
```
@@ -19,9 +17,7 @@ A Redis storage backend for [LuckyCache](https://github.com/luckyframework/lucky
1917
## Usage
2018

2119
```crystal
22-
require "lucky_cache"
2320
require "lucky_cache_redis_store"
24-
require "redis"
2521
2622
LuckyCache.configure do |settings|
2723
settings.storage = LuckyCache::RedisStore.new(
@@ -58,13 +54,26 @@ cache.delete("my_key")
5854
cache.flush
5955
```
6056

57+
## Expiration Semantics
58+
59+
- `expires_in` is stored with millisecond precision.
60+
- TTL values must be at least `1.millisecond`.
61+
- `0.seconds`, negative durations, and positive durations below `1.millisecond` raise `ArgumentError`.
62+
- `read` restores cache items with their original TTL metadata and the correct absolute expiration time.
63+
64+
## Prefix Operations
65+
66+
- `flush` removes only keys that match the store's configured prefix.
67+
- `size` counts only keys that match the configured prefix.
68+
- Both operations iterate Redis with `SCAN`, not `KEYS`, so they remain safer on larger keyspaces.
69+
6170
### Supported Types
6271

6372
The Redis store supports the following types:
6473
- Basic types: `String`, `Int32`, `Int64`, `Float64`, `Bool`, `Time`, `UUID`, `JSON::Any`
6574
- Arrays of basic types: `Array(String)`, `Array(Int32)`, `Array(Int64)`, `Array(Float64)`, `Array(Bool)`
6675

67-
**Note:** Custom objects that include `LuckyCache::Cachable` are not supported by RedisStore due to serialization limitations. Use MemoryStore for caching custom objects.
76+
**Note:** Custom objects that include `LuckyCache::Cacheable` are not supported by RedisStore due to serialization limitations. Use MemoryStore for caching custom objects.
6877

6978
### Workaround for Custom Objects
7079

@@ -75,7 +84,10 @@ You can cache JSON representations of your objects:
7584
# cache.write("user:123") { User.new("test@example.com") } # This will raise an error
7685
7786
# Cache a JSON representation
78-
user_data = {"id" => 123, "email" => "test@example.com"}
87+
user_data = {
88+
"id" => JSON::Any.new(123_i64),
89+
"email" => JSON::Any.new("test@example.com"),
90+
}
7991
cache.write("user:123") { JSON::Any.new(user_data) }
8092
8193
# Retrieve and reconstruct
@@ -87,14 +99,16 @@ user = User.new(cached_data["email"].as_s)
8799

88100
To run the tests:
89101

90-
1. Make sure Redis is running locally on the default port (6379)
102+
1. Make sure Redis is running locally on the default port (`6379`)
91103
2. Run `crystal spec`
92104

93105
The test suite includes tests for:
94106
- Basic type caching
95107
- Array type caching
96-
- Expiration functionality
97-
- Key deletion and cache flushing
108+
- Millisecond TTL handling and TTL validation
109+
- Expiration correctness after Redis deserialization
110+
- Key deletion, prefix-scoped flushing, and prefix-scoped sizing
111+
- Standalone shard loading
98112
- Custom prefix support
99113
- Error handling for non-serializable types
100114

shard.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
name: lucky_cache_redis_store
2-
version: 0.1.0
2+
version: 0.2.0
33

44
authors:
55
- Jeremy Woertink <jeremywoertink@gmail.com>
66

7-
crystal: '>= 1.14.1'
7+
crystal: ">= 1.16.3"
88

99
license: MIT
1010

@@ -17,6 +17,7 @@ dependencies:
1717
development_dependencies:
1818
ameba:
1919
github: crystal-ameba/ameba
20-
version: ~> 1.5.0
20+
version: ~> 1.6.4
2121
timecop:
2222
github: crystal-community/timecop.cr
23+
version: ~> 0.5.0

0 commit comments

Comments
 (0)