You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CHANGELOG.md
+17Lines changed: 17 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,6 +5,23 @@ All notable changes to the `iazaran/smart-cache` package will be documented in t
5
5
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
8
+
## [1.13.0] - 2026-06-16
9
+
### Added
10
+
- Declarative model invalidation rules via a protected `cacheInvalidation(): array` method. Existing fluent setters still work and are merged with declared rules.
11
+
-`Model::flushCacheTags()` for explicit invalidation after `saveQuietly()`, query-builder updates/deletes, upserts, mass inserts, raw SQL, or any other path that bypasses Eloquent events.
12
+
-`TagFlushed` event, including the tag name, live key count, and source (`manual`, `model`, or `model_helper`), when cache events are enabled.
13
+
- Config options for metadata locks (`smart-cache.metadata_lock.*`) and transaction-aware model invalidation (`smart-cache.model_invalidation.after_commit`).
14
+
15
+
### Changed
16
+
- Model auto-invalidation now defers cache flushing until the active database transaction commits by default. Rollbacks no longer flush cache, and nested transactions wait for the outer commit. Set `smart-cache.model_invalidation.after_commit` to `false` to restore immediate invalidation.
17
+
- Tag metadata writes now register before the cache value is written and use a short Laravel cache lock when the store supports `LockProvider`, reducing lost tag-index updates under concurrent writers while preserving best-effort behavior for stores without locks.
18
+
- Tag reads lazily prune expired or missing key references, and tag flushes correctly handle keys written under an active namespace.
19
+
20
+
### Fixed
21
+
-`SmartCache::add()` no longer leaks active tags into the next write when the atomic add fails because the key already exists.
22
+
- Cache DNA deduplicated writes now still refresh tag/managed-key metadata and only skip the value write when the cached value is still present.
23
+
- Dependency invalidation now refreshes dependency metadata before traversal, so long-running workers do not miss relationships added by another process after the local map was loaded.
24
+
8
25
## [1.12.2] - 2026-05-29
9
26
### Security
10
27
- Upgraded every remaining `symfony/*` lockfile entry from `v8.0.8` to `v8.1.0` (>= patched lines `8.0.12` / `8.0.13`) to clear the rest of the open Dependabot advisories plus two pending CVEs surfaced by `composer audit`. Runtime: `symfony/mailer` (CVE-2026-45068, `SendmailTransport` argument injection via dash-prefixed recipient), `symfony/routing` (CVE-2026-45065, `UrlGenerator` route-requirement bypass via unanchored regex alternation; CVE-2026-48784, dot-segment encoding skip), `symfony/http-foundation` (CVE-2026-48736), `symfony/http-kernel` (CVE-2026-45075, `#[IsGranted(methods: ['GET'])]` filter bypass via `HEAD`). Dev: `symfony/yaml` (CVE-2026-45133 uncontrolled recursion, CVE-2026-45304 collection-alias "Billion Laughs", CVE-2026-45305 `Parser::cleanup()` ReDoS). `composer audit` is now clean across runtime and dev scopes. `composer.json` is unchanged — the existing ranges already permitted these versions; Dependabot was failing because of a stale resolver state on its side.
Model invalidation is deferred until the current database transaction commits by default (`smart-cache.model_invalidation.after_commit = true`). This prevents another request from re-caching pre-commit data between an Eloquent event and the final commit. Set the flag to `false` if you need the historical immediate behavior.
241
+
242
+
Eloquent events do not fire for `saveQuietly()`, query-builder `update()` / `delete()`, `upsert()`, mass `insert()`, or raw SQL. For those paths, call `flushCacheTags()` or `SmartCache::flushTags()` explicitly.
243
+
244
+
### Choosing Cache Tags
245
+
246
+
Tags should describe the data used to build a response, not the controller that built it. Start with the tables or models read by the endpoint: list endpoints usually use coarse tags such as `products`, while item endpoints can add instance tags such as `product_123`. Over-tagging causes extra refreshes; under-tagging leaves stale data behind. For hard-to-map endpoints, enable Laravel's query log in a test and compare the tables read during response generation with the tags declared for that cache entry.
<strong>Eloquent event blind spots.</strong> Model auto-invalidation depends on Eloquent events. It does not run for <code>saveQuietly()</code>, query-builder <code>update()</code> / <code>delete()</code>, <code>upsert()</code>, mass <code>insert()</code>, or raw SQL. Use <code>Model::flushCacheTags()</code> or <code>SmartCache::flushTags()</code> in those paths.
1446
+
</div>
1447
+
1448
+
<p>When an Eloquent event fires inside a database transaction, SmartCache defers invalidation until the outer transaction commits by default. This avoids flushing cache and then letting another request re-cache pre-commit data. Disable with <code>smart-cache.model_invalidation.after_commit = false</code> if your application needs immediate invalidation.</p>
1449
+
1450
+
<h3>Dependency Map Cookbook</h3>
1451
+
<p>Declare tags for the data used to build the response, not for the controller or route name. Use coarse tags for list endpoints such as <code>products</code>, add instance tags for detail endpoints such as <code>product_123</code>, and prefer over-tagging to under-tagging. For opaque endpoints, capture Laravel's query log in a test and compare the selected tables with the cache tags you declared.</p>
1418
1452
1419
1453
<h2>Custom Optimization Strategies</h2>
1420
1454
<p>Create custom optimization strategies for your specific needs:</p>
<p>Flush all cache entries associated with given tags. Tag metadata is pruned lazily when tags are read, so expired entries do not build up indefinitely in rarely flushed tags.</p>
2182
2226
<divclass="parameter">
2183
2227
<spanclass="parameter-name">$tags</span><spanclass="parameter-type">(string|array)</span> - Tag name(s)
2184
2228
</div>
2229
+
<divclass="parameter">
2230
+
<spanclass="parameter-name">$source</span><spanclass="parameter-type">(string)</span> - Optional source label exposed on the TagFlushed event
2231
+
</div>
2185
2232
<divclass="parameter">
2186
2233
<spanclass="return-type">Returns:</span> bool - True on success
<p>Flush model cache tags explicitly after writes that bypass Eloquent events, such as query-builder updates, upserts, mass inserts, quiet saves, or raw SQL.</p>
<p>SmartCache ships with automated coverage for the Laravel-compatible API surface, optimization strategies, SWR patterns, invalidation, memoization, dashboard command execution, and large-data recovery behavior.</p>
0 commit comments