Skip to content

Commit 325c20b

Browse files
authored
Merge pull request #8 from kai-init/3.1
3.1
2 parents 33229b1 + b8ab08c commit 325c20b

125 files changed

Lines changed: 4581 additions & 4270 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
---
99

10+
## [3.1.0] — 2026-07-23
11+
12+
### Added
13+
14+
- `CacheInvalidated` and `CacheMetricRecorded` events when `normcache.events` is enabled. Cache hit and miss events now include cache metadata.
15+
16+
### Changed
17+
18+
- Debugbar records overall cache-operation duration only; component-specific timing breakdowns are no longer collected.
19+
- Internal cache execution and invalidation code has been consolidated behind dedicated services.
20+
21+
### Fixed
22+
23+
- `useWritePdo()` reads, including relation reads, now bypass the cache and preserve read-your-writes behavior.
24+
- Cache keys for root, through, and pivot reads now consistently use the active Eloquent connection, preventing cross-connection cache leakage.
25+
- Model updates now invalidate before and after the write, so a concurrent pre-write read cannot remain reachable after a successful update.
26+
- Index, through, and pivot cache hits preserve the Lua-resolved model version when fetching model payloads.
27+
28+
---
29+
1030
## [3.0.0] — 2026-07-09
1131

1232
### Added

README.md

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
[![Latest Version on Packagist](https://img.shields.io/packagist/v/kai-init/laravel-normcache.svg)](https://packagist.org/packages/kai-init/laravel-normcache)
88
[![License](https://img.shields.io/github/license/kai-init/laravel-normcache.svg)](LICENSE)
99

10-
Normcache caches query results as ID lists and stores model attributes in versioned model keys. When a model changes, Normcache bumps a version key instead of scanning and deleting every query that may have returned that model.
10+
Normcache caches model-query results as ID lists and stores model attributes in versioned model keys. When a model changes, Normcache bumps a version key instead of scanning and deleting every query that may have returned that model.
1111

1212
**Requirements:** PHP 8.2+, Laravel 12/13, Redis 6.0+
1313

1414
## Table of Contents
1515

1616
- [Installation](#installation)
17-
- [What's new in 3.0](#whats-new-in-30)
17+
- [What's new in v3](#whats-new-in-v3)
1818
- [Usage](#usage)
1919
- [Invalidation](#invalidation)
2020
- [Cache spaces](#cache-spaces)
@@ -41,7 +41,7 @@ class Post extends Model
4141
}
4242
```
4343

44-
## What's new in 3.0
44+
## What's new in v3
4545

4646
Redis Cluster sharding is now fully atomic within each cache space. Normcache keeps the keys for a cached operation and its valid dependencies in one hash slot, so cache reads, rebuilds, and invalidation coordination remain atomic.
4747

@@ -55,7 +55,6 @@ Redis Cluster sharding is now fully atomic within each cache space. Normcache ke
5555
Normal Eloquent reads are cached automatically for cacheable models:
5656

5757
```php
58-
Post::all();
5958
Post::where('active', true)->get();
6059
Post::find(1);
6160
Post::paginate(20);
@@ -74,18 +73,12 @@ Simple `whereHas` / `whereDoesntHave` constraints on cacheable relations and pla
7473

7574
```php
7675
Author::whereHas('posts', fn($q) => $q->where('published', true))->get();
77-
78-
Author::join('posts', 'posts.author_id', '=', 'authors.id')
79-
->select('authors.*')
80-
->get();
8176
```
8277

8378
For other cross-table reads, declare dependencies explicitly:
8479

8580
```php
86-
Author::query()
87-
->dependsOn([Post::class])
88-
->get();
81+
Author::query()->dependsOn([Post::class])->get();
8982

9083
Author::join('legacy_stats', 'legacy_stats.author_id', '=', 'authors.id')
9184
->select('authors.*')
@@ -216,7 +209,7 @@ Common options:
216209
| `stampede_wait_ms` | How long waiters block for a rebuild wake signal. |
217210
| `stampede_wake_tokens` | Number of waiters to wake after a rebuild. |
218211
| `fallback` | Fail open to the database on Redis errors when `true`. |
219-
| `events` | Dispatch cache hit/miss events when `true`. |
212+
| `events` | Dispatch hit/miss/bypass, metric, and invalidation events. |
220213
| `fire_retrieved` | Fire Eloquent `retrieved` for cached models when `true`. |
221214
| `debugbar` | Enable Laravel Debugbar integration when installed. |
222215
| `spaces.*` | Cache-space limits, cross-space policy, and hash-tag placement. |
@@ -228,6 +221,7 @@ Normcache bypasses caching for unsafe reads rather than risking stale or incorre
228221
Always bypassed:
229222

230223
- pessimistic locks (`lockForUpdate`, `sharedLock`)
224+
- reads forced to the write connection with `useWritePdo()`
231225
- reads inside a database transaction
232226
- `DB::table(...)`, `DB::select()`, and raw SQL
233227

@@ -244,11 +238,11 @@ Other limitations:
244238
- Models should use standard single-column primary keys.
245239
- Writes outside Eloquent are invisible unless you manually flush or invalidate.
246240
- Packages that replace Eloquent builders, relation classes, or hydration behavior may bypass parts of Normcache.
247-
- Normcache caches model connection/table metadata. Call `CacheKeyBuilder::reset()` after switching tenants dynamically.
241+
- Normcache caches model connection/table metadata. Call `NormCache\Support\CacheKeyBuilder::reset()` after switching tenants dynamically.
248242

249243
## Observability
250244

251-
When events are enabled, Normcache dispatches query/model hit and miss events. When `fruitcake/laravel-debugbar` is installed and `normcache.debugbar` is enabled, cache hits, misses, bypasses, and model fetches appear in Debugbar.
245+
When events are enabled, Normcache dispatches cache hit, miss, bypass, metric, and invalidation events. When `fruitcake/laravel-debugbar` is installed and `normcache.debugbar` is enabled, cache hits, misses, bypasses, and model fetches appear in Debugbar.
252246

253247
## License
254248

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"scripts": {
4949
"test": "vendor/bin/phpunit",
5050
"test:cluster": "REDIS_CLUSTER=true REDIS_PORT=7010 vendor/bin/phpunit",
51+
"bench": "vendor/bin/phpunit tests/Benchmark",
5152
"lint": "vendor/bin/pint --test",
5253
"format": "vendor/bin/pint",
5354
"analyse": "vendor/bin/phpstan analyse --memory-limit=512M"
@@ -62,4 +63,4 @@
6263
}
6364
}
6465
}
65-
}
66+
}

src/Cache/ExecutionEngine.php

Lines changed: 0 additions & 117 deletions
This file was deleted.

0 commit comments

Comments
 (0)