Skip to content
Open

Wip #10

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
11 changes: 11 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/.github export-ignore
/.vscode export-ignore
/.editorconfig export-ignore
/.gitignore export-ignore
/.gitattributes export-ignore
/docker-compose.yml export-ignore
/package-lock.json export-ignore
/phpstan.neon export-ignore
/phpunit.xml export-ignore
/pint.json export-ignore
/tests export-ignore
100 changes: 100 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,105 @@ jobs:
- name: Install dependencies
run: composer update --prefer-dist --no-interaction --no-progress

- name: Run Pint
run: composer lint

- name: Run Larastan
run: vendor/bin/phpstan analyse --memory-limit=512M --error-format=github

database:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
include:
- label: MySQL
driver: mysql
image: mysql:8.4
port: 3306
container_port: 3306
username: root
password: normcache
options: >-
--health-cmd "mysqladmin ping --password=normcache"
--health-interval 5s
--health-timeout 3s
--health-retries 10

- label: PostgreSQL
driver: pgsql
image: postgres:17
port: 5432
container_port: 5432
username: postgres
password: normcache
options: >-
--health-cmd "pg_isready -U postgres -d normcache"
--health-interval 5s
--health-timeout 3s
--health-retries 10

- label: MariaDB
driver: mariadb
image: mariadb:11.4
port: 3307
container_port: 3306
username: root
password: normcache
options: >-
--health-cmd "healthcheck.sh --connect --innodb_initialized"
--health-interval 5s
--health-timeout 3s
--health-retries 10

name: Database / ${{ matrix.label }}

services:
redis:
image: redis:7
ports:
- 6379:6379
options: >-
--health-cmd "redis-cli ping"
--health-interval 5s
--health-timeout 3s
--health-retries 5

database:
image: ${{ matrix.image }}
env:
MYSQL_DATABASE: normcache
MYSQL_ROOT_PASSWORD: normcache
POSTGRES_DB: normcache
POSTGRES_PASSWORD: normcache
MARIADB_DATABASE: normcache
MARIADB_ROOT_PASSWORD: normcache
ports:
- ${{ matrix.port }}:${{ matrix.container_port }}
options: ${{ matrix.options }}

steps:
- uses: actions/checkout@v6

- uses: shivammathur/setup-php@v2
with:
php-version: "8.3"
extensions: redis, pdo_mysql, pdo_pgsql
coverage: none

- name: Install dependencies
run: composer update --prefer-dist --no-interaction --no-progress

- name: Run database contract and cascade tests
env:
TEST_DB_DRIVER: ${{ matrix.driver }}
TEST_DB_HOST: 127.0.0.1
TEST_DB_PORT: ${{ matrix.port }}
TEST_DB_DATABASE: normcache
TEST_DB_USERNAME: ${{ matrix.username }}
TEST_DB_PASSWORD: ${{ matrix.password }}
run: >-
vendor/bin/phpunit
tests/Integration/Contract
tests/Integration/Cache/DeleteInvalidationTest.php
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,5 @@ composer.lock
.phpunit.result.cache
.phpunit.cache/
tests/Benchmark/
tests/Concerns/
docs
.worktrees/
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

---

## [4.0.0] — 2026-08-04

### Added

- **Membership revalidation:** a cached membership survives a version bump when every version in the gap was a precise `UPDATE` whose columns are disjoint from the query's predicate and order columns. Configure with `revalidation`, and declare `protected array $volatileColumns` for columns the database writes without the statement naming them.
- **Automatic result overlays:** eligible canonical queries store a complete result payload for faster warm reads and rebuild it from canonical rows when the overlay is missing.
- **Unified query controls:** `dependsOn()` accepts models and table names, `tag()` groups related queries, `NormCache::invalidate()` accepts model or table targets, and `NormCache::withoutCache()` runs a whole callback, eager loads included, against the database.
- **Runtime cache switch:** `normcache:disable` and `normcache:enable`, plus their facade equivalents, pause and safely resume caching across application nodes.
- **Database source scopes:** `database.connections.<name>.normcache_scope` isolates shards or tenants and allows aliases for the same source to share cache state deliberately.
- **Serializer selection:** choose `auto`, `php`, or `igbinary` payload serialization.

### Changed

- **BREAKING cache layout:** cache spaces were removed and Redis placement is now derived from physical tables and query groups. Cache keys changed, so v3 and v4 must not serve traffic together. Run `normcache:disable`, deploy every web and worker node, then run `normcache:enable`.
- **BREAKING API consolidation:** replace `dependsOnTables()` with `dependsOn()`, legacy invalidation methods with `NormCache::invalidate()`, and model-scoped tag flushing with `flushTag('name')`.
- **BREAKING flush behavior:** `normcache:flush` now always performs a global invalidation; `--model` and `--space` were removed.
- Model attribute lifetime is configured with `row_ttl` / `NORMCACHE_ROW_TTL` rather than `ttl` / `NORMCACHE_TTL`, and the key-prefix variable is now `NORMCACHE_KEY_PREFIX` rather than `NORMCACHE_PREFIX`.

### Fixed

- Improved cache isolation for connection aliases, shards, tenants, and runtime database switching.
- Manual and automatic invalidation now handle connection-aware table names, unknown write targets, and writes that throw after reaching the database safely.
- Improved build-lock and Redis reconnect behavior when responses are lost or operations are retried.

### Removed

- Cache spaces, `$normCacheSpaces`, `space()`, the `spaces` configuration, and space-targeted flushing.
- Legacy `cooldown`, `fallback`, and `fire_retrieved` options, `Builder::explain()`, and the cache-manager facade accessors (`modelCache()`, `resultCache()`, `versionStore()`, and friends).
- The `ModelCacheHit`, `ModelCacheMiss`, and `CacheMetricRecorded` events.
- The `stampede_wake_tokens` option and `NORMCACHE_STAMPEDE_WAKE_TOKENS`; the wake-token count is now fixed.
- Environment overrides for build-lock tuning: set `building_lock_ttl` and `stampede_wait_ms` in the published config file, not `NORMCACHE_BUILDING_LOCK_TTL` / `NORMCACHE_STAMPEDE_WAIT_MS`.
- The relation-specific cache classes; relation and pivot reads are cached through the same query path as everything else.

---

## [3.1.0] — 2026-07-23

### Added
Expand Down
Loading