Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
434 commits
Select commit Hold shift + click to select a range
910f4a8
fix(counter): isolate keyspace and preserve exact integers
abmmhasan Sep 28, 2026
670240a
feat(redis): guard stale cleanup against concurrent replacement
abmmhasan Sep 28, 2026
5cb5136
fix(redis): make stale cleanup and tag repair compare-safe
abmmhasan Sep 28, 2026
e86f9c0
test(counter): share concurrent initialization probe
abmmhasan Sep 28, 2026
41e2efb
test(counter): cover Redis isolation precision and races
abmmhasan Sep 28, 2026
3787759
test(counter): cover Valkey isolation precision and contention
abmmhasan Sep 28, 2026
9980b53
docs(counter): document isolated exact counter semantics
abmmhasan Sep 28, 2026
ce74f1c
docs(counter): describe isolated exact counter storage
abmmhasan Sep 28, 2026
b39a56b
feat(memcached): add compare-safe value guard
abmmhasan Sep 28, 2026
47e783f
fix(memcached): guard stale cleanup and status handling
abmmhasan Sep 28, 2026
9380a46
fix(redis-cluster): avoid racy stale cleanup and generation overwrite
abmmhasan Sep 28, 2026
dd5f30a
test(memcached): cover guarded cleanup and failure statuses
abmmhasan Sep 28, 2026
9eff41b
fix(pdo): make stale reads and expiry pruning race-safe
abmmhasan Sep 28, 2026
0220d28
fix(apcu): avoid racy stale cleanup and tag overwrite
abmmhasan Sep 28, 2026
ebcb826
fix(cache): leave stale cleanup to safe maintenance
abmmhasan Sep 28, 2026
7d4a470
fix(cache): leave stale cleanup to safe maintenance
abmmhasan Sep 28, 2026
24e9678
fix(cache): leave stale cleanup to safe maintenance
abmmhasan Sep 28, 2026
30776f5
fix(cache): leave stale cleanup to safe maintenance
abmmhasan Sep 28, 2026
500bbd7
test(counter): verify Redis fixed-window expiry
abmmhasan Sep 28, 2026
fbda5a9
test(counter): verify Valkey fixed-window expiry
abmmhasan Sep 28, 2026
1cdb25a
test(redis-cluster): cover safe stale and generation races
abmmhasan Sep 28, 2026
0f5d94e
fix(shared-memory): initialize tags under one exclusive lock
abmmhasan Sep 28, 2026
4175bb3
fix(mongodb): initialize tag generations without overwrites
abmmhasan Sep 28, 2026
4eae413
fix(pdo): initialize tag generations without lost races
abmmhasan Sep 28, 2026
81b2b8d
fix(node): initialize tag generations without lost races
abmmhasan Sep 28, 2026
1a66013
fix(scylla): initialize tag generations with LWT
abmmhasan Sep 28, 2026
0c9b624
test(scylla): model conditional tag initialization
abmmhasan Sep 28, 2026
c6d2fad
fix(apcu): remove stale helper annotation
abmmhasan Sep 28, 2026
5a6f00a
fix(memcached): narrow extended CAS result types
abmmhasan Sep 28, 2026
b6e6fb1
refactor(pdo): isolate tag generation initialization
abmmhasan Sep 28, 2026
bff73a5
refactor(pdo): delegate tag generation initialization
abmmhasan Sep 28, 2026
86a78a2
refactor(redis): simplify tag generation initialization
abmmhasan Sep 28, 2026
31b7671
test(counter): assert exact Redis counter value correctly
abmmhasan Sep 28, 2026
4c62848
test(redis-cluster): assert fail-open generation repair semantics
abmmhasan Sep 28, 2026
11588fb
test(counter): avoid forbidden process exit helper
abmmhasan Sep 28, 2026
089c357
refactor(shared-memory): return locked bulk reads directly
abmmhasan Sep 28, 2026
8645f97
style(memcached): order private helpers for PHPForge
abmmhasan Sep 28, 2026
32c23c6
style(redis): order tag generation helpers
abmmhasan Sep 28, 2026
710ea9b
style(pdo): order private helpers for PHPForge
abmmhasan Sep 28, 2026
4ac0dac
style(counter): order private helpers for PHPForge
abmmhasan Sep 28, 2026
43a0e31
style(mongodb): separate tag initialization try block
abmmhasan Sep 28, 2026
2d823e4
style(pdo): align tag generation PHPDoc
abmmhasan Sep 28, 2026
9e1a3d5
style(cache): normalize class element separation
abmmhasan Sep 28, 2026
e3e6bf7
style(cache): normalize class element separation
abmmhasan Sep 28, 2026
60020dc
style(redis-cluster): separate miss return
abmmhasan Sep 28, 2026
d2f0bbb
style(node): separate bulk return
abmmhasan Sep 28, 2026
c898d54
docs(plan): close Batch 5 and start Batch 6
abmmhasan Sep 28, 2026
413fcec
ci(release): add real MongoDB replica-set coverage
abmmhasan Sep 28, 2026
743e54e
test(mongodb): exercise real replica-set backend
abmmhasan Sep 28, 2026
b97f253
test(release): add PHP 8.3 core consumer smoke
abmmhasan Sep 28, 2026
ec5b6aa
test(release): add real Redis Cluster smoke
abmmhasan Sep 28, 2026
41ca8bb
test(release): add real Scylla CQL smoke
abmmhasan Sep 28, 2026
7b2172a
test(release): add independent PSR consumer project
abmmhasan Sep 28, 2026
dfbc4ae
test(release): add PSR-6 and PSR-16 integration suites
abmmhasan Sep 28, 2026
e23f12f
ci(release): add final compatibility and backend gates
abmmhasan Sep 28, 2026
a7f2261
build: raise minimum PHP version to 8.4
abmmhasan Sep 28, 2026
a5055af
docs: document PHP 8.4 minimum
abmmhasan Sep 28, 2026
bf77824
docs: align manual with PHP 8.4 floor
abmmhasan Sep 28, 2026
82fe548
ci(release): align release matrix with PHP 8.4 floor
abmmhasan Sep 28, 2026
c57f8f8
test(release): remove obsolete PHP 8.3 smoke
abmmhasan Sep 28, 2026
649977e
docs(plan): adopt PHP 8.4 minimum for 4.0
abmmhasan Sep 28, 2026
4352228
test(release): add cross-platform core smoke
abmmhasan Sep 28, 2026
c28fc0a
test(release): add clean production consumer fixture
abmmhasan Sep 28, 2026
b57434f
test(release): add clean consumer smoke
abmmhasan Sep 28, 2026
8162756
ci(release): cover PHP 8.4+ platforms and consumers
abmmhasan Sep 28, 2026
532347e
docs(release): add 3.x to 4.0 upgrade guide
abmmhasan Sep 28, 2026
5ca9c2d
docs(release): link 4.0 upgrade guide
abmmhasan Sep 28, 2026
caca4cf
docs(release): point 3.x users to 4.0 migration guide
abmmhasan Sep 28, 2026
7f49914
docs: align regression template with PHP 8.4 floor
abmmhasan Sep 28, 2026
f74a7df
docs(plan): align audit notes with PHP 8.4 floor
abmmhasan Sep 28, 2026
65ecac2
docs(serialization): document 4.0 cache record defaults
abmmhasan Sep 28, 2026
f20b1ed
docs(release): add 4.0 release notes
abmmhasan Sep 28, 2026
b556e21
docs(release): expose 4.0 release notes
abmmhasan Sep 28, 2026
6daac14
test(release): narrow Redis Cluster atomic capability
abmmhasan Sep 28, 2026
ca91807
test(release): assert numeric keys through public reads
abmmhasan Sep 28, 2026
73f2234
test(release): keep external PSR fixture outside root analysis
abmmhasan Sep 28, 2026
4628a8c
fix(mongodb): preserve BSON binary values during normalization
abmmhasan Sep 28, 2026
17c3f18
test(mongodb): read contention result through fresh client
abmmhasan Sep 28, 2026
9ac0059
ci(release): fix Windows PSR and Scylla gates
abmmhasan Sep 28, 2026
7a8e7f4
docs: scope automatic section labels by document
abmmhasan Sep 28, 2026
0de7331
docs: normalize RST title adornments
abmmhasan Sep 28, 2026
aac151c
docs: normalize RST title adornments
abmmhasan Sep 28, 2026
cf284b7
docs: normalize RST title adornments
abmmhasan Sep 28, 2026
7af7cd3
docs: normalize RST title adornments
abmmhasan Sep 28, 2026
062256b
docs: normalize RST title adornments
abmmhasan Sep 28, 2026
a13f7d0
docs: normalize RST title adornments
abmmhasan Sep 28, 2026
ae14bfb
docs: normalize RST title adornments
abmmhasan Sep 28, 2026
aa655f1
docs: remove duplicated lock-provider bullets
abmmhasan Sep 28, 2026
048693a
refactor(cache): apply PHP 8.4 constructor chaining
abmmhasan Sep 28, 2026
a8a6221
refactor(tiered): apply PHP 8.4 constructor chaining
abmmhasan Sep 28, 2026
919a79e
refactor(node): apply PHP 8.4 constructor chaining
abmmhasan Sep 28, 2026
2fe2a00
refactor(release): use first-class trim callable
abmmhasan Sep 28, 2026
2218bbe
refactor(apcu): use PHP 8.4 array_all for batch stores
abmmhasan Sep 28, 2026
42f67d4
refactor(memcached): use PHP 8.4 array_all for batch stores
abmmhasan Sep 28, 2026
24ab3aa
refactor(null): reuse common item validation
abmmhasan Sep 28, 2026
8acf399
refactor(pdo): use PHP 8.4 array_all for batch upserts
abmmhasan Sep 28, 2026
862f94c
refactor(php-files): use PHP 8.4 array_all for tag rotation
abmmhasan Sep 28, 2026
6391693
refactor(redis-cluster): use PHP 8.4 array_all for deletes
abmmhasan Sep 28, 2026
4bfea77
refactor(cache): apply PHP 8.4 item chaining
abmmhasan Sep 28, 2026
2f23263
refactor(cache): use PHP 8.4 array_any for decoded values
abmmhasan Sep 28, 2026
d926a1c
ci(release): fix generated PSR fixture namespaces
abmmhasan Sep 28, 2026
a23fa28
fix(filesystem): apply Unix mode trust checks only on Unix
abmmhasan Sep 28, 2026
e5b8c11
ci(release): stabilize Redis and Scylla backend gates
abmmhasan Sep 28, 2026
09858af
ci(release): discover both PSR integration suites
abmmhasan Sep 28, 2026
85bcf2b
ci(release): isolate no-dev platform checks and Scylla runner
abmmhasan Sep 28, 2026
577cf6f
ci(release): split PSR fixtures for PHPUnit discovery
abmmhasan Sep 28, 2026
bc8db6a
ci(release): use Ubuntu 22.04 Scylla runtime packages
abmmhasan Sep 28, 2026
8b23b60
fix(psr): preserve numeric-string bulk keys and reject invalid keys
abmmhasan Sep 28, 2026
757a533
ci(release): run PSR contracts on persistent trusted-object stores
abmmhasan Sep 28, 2026
05040ef
test(cache): assert numeric-string bulk keys stay strings
abmmhasan Sep 28, 2026
d9a6221
ci(release): use portable Cassandra-linked Scylla driver
abmmhasan Sep 28, 2026
08c5164
fix(scylla): use native execution option arrays
abmmhasan Sep 28, 2026
f12fd1f
test(release): surface real Scylla backend failures
abmmhasan Sep 28, 2026
1255916
fix(scylla): adapt blob and bigint bindings to native driver types
abmmhasan Sep 28, 2026
2de1e3e
fix(scylla): bind prepared CQL values with exact native types
abmmhasan Sep 28, 2026
e32869b
refactor(cache): isolate bulk result key preservation
abmmhasan Sep 28, 2026
bd6038d
refactor(cache): delegate bulk result key preservation
abmmhasan Sep 28, 2026
de71d27
fix(scylla): type native execution options precisely
abmmhasan Sep 28, 2026
ef12fc6
style(cache): align decoded-value branch spacing
abmmhasan Sep 28, 2026
4a902b9
style(memcached): align PHPForge batch-store form
abmmhasan Sep 28, 2026
a64cead
refactor(redis-cluster): use PHP 8.4 array_all for bucket saves
abmmhasan Sep 28, 2026
7da852a
fix(scylla): narrow native driver scalar return types
abmmhasan Sep 28, 2026
d9f3a85
style(redis-cluster): align PHPForge statement spacing
abmmhasan Sep 28, 2026
bc1078f
style(cache): align PHPForge statement spacing
abmmhasan Sep 28, 2026
1541206
refactor(scylla): isolate native value normalization
abmmhasan Sep 28, 2026
1fc9c67
refactor(scylla): keep adapter under PHPForge complexity cap
abmmhasan Sep 28, 2026
e385f3c
fix(scylla): restore row normalization after helper extraction
abmmhasan Sep 28, 2026
9219b25
style(scylla): restore private method ordering
abmmhasan Sep 28, 2026
76a3118
docs(plan): close CacheLayer 4.0 Batch 6 tracker
abmmhasan Sep 28, 2026
12ecd81
docs(plan): resolve deferred and follow-up checklists
abmmhasan Sep 28, 2026
3bc8d06
docs(plan): require Runwire 2.1 integration for 4.0
abmmhasan Sep 28, 2026
2937d90
docs(plan): track required Runwire integration batches
abmmhasan Sep 28, 2026
29baf5c
feat(runwire): add runtime-aware memoizer policy
abmmhasan Sep 28, 2026
7f28304
feat(runwire): bind runtime memoizer lifecycle
abmmhasan Sep 28, 2026
b4e73bf
feat(runwire): reset sequential persistent memoizers
abmmhasan Sep 28, 2026
b605e88
refactor(runwire): align integration with shared execution scope
abmmhasan Sep 28, 2026
7bf25e2
refactor(runwire): align integration with shared execution scope
abmmhasan Sep 28, 2026
4fb229f
feat(runwire): model shared runtime execution context
abmmhasan Sep 28, 2026
8c2b681
feat(runwire): share runtime and execution scope
abmmhasan Sep 28, 2026
337f479
feat(runwire): support isolated request memoizers
abmmhasan Sep 28, 2026
9d958c1
feat(runwire): support isolated request memoizers
abmmhasan Sep 28, 2026
0416ffb
fix(runwire): safely resolve fiber execution context
abmmhasan Sep 28, 2026
b8e67e4
feat(runwire): isolate helper memoization by shared request scope
abmmhasan Sep 28, 2026
d5eee1f
test(runwire): cover shared runtime request and task scopes
abmmhasan Sep 28, 2026
6ed3dbf
fix(runwire): declare Fiber generic state
abmmhasan Sep 28, 2026
ad3b767
fix(runwire): type fiber context map by object key
abmmhasan Sep 28, 2026
a998ffa
style(runwire): remove unused memoizer import
abmmhasan Sep 28, 2026
e91f7eb
docs(plan): close Runwire 7A and open 7B
abmmhasan Sep 28, 2026
0761721
feat(runwire): expose cooperative cancellation checkpoint
abmmhasan Sep 28, 2026
dafcc71
feat(runwire): add bounded cluster polling
abmmhasan Sep 28, 2026
2104bf0
feat(node): expose bounded maintenance cycle
abmmhasan Sep 28, 2026
bb28eef
test(runwire): cover bounded polling and cooperative worker scope
abmmhasan Sep 28, 2026
0e065ce
test(node): cover bounded maintenance cycle
abmmhasan Sep 28, 2026
bc641e2
style(cluster): align bounded polling with PHPForge
abmmhasan Sep 28, 2026
19a0b5c
feat(runwire): add host-owned worker runners
abmmhasan Sep 28, 2026
d609fe9
test(runwire): cover host-owned worker integration
abmmhasan Sep 28, 2026
54ef776
fix(runwire): rely on worker scope cancellation for shutdown
abmmhasan Sep 28, 2026
97b5854
fix(runwire): make worker loops cancellation-driven
abmmhasan Sep 28, 2026
abae64c
style(cluster): match PER brace placement
abmmhasan Sep 29, 2026
04321c6
docs(plan): close Runwire 7B and open 7C
abmmhasan Sep 29, 2026
6488982
feat(runwire): add executable invalidation worker example
abmmhasan Sep 29, 2026
3689b60
test(runwire): add isolated consumer fixture
abmmhasan Sep 29, 2026
5d24cc8
test(runwire): exercise isolated consumer integration
abmmhasan Sep 29, 2026
d2b2568
docs(runwire): document runtime integration contract
abmmhasan Sep 29, 2026
c2bb8df
docs(runwire): add integration guide to manual
abmmhasan Sep 29, 2026
f7b90cf
chore(runwire): advertise optional integration dependency
abmmhasan Sep 29, 2026
5f63efd
docs(runwire): document shipped optional integration
abmmhasan Sep 29, 2026
3b2c238
docs(release): include Runwire 2.1 integration
abmmhasan Sep 29, 2026
acf766a
docs(upgrade): add Runwire 2.1 deployment guidance
abmmhasan Sep 29, 2026
cbd4a89
fix(runwire): create executable example workspace
abmmhasan Sep 29, 2026
49fe238
ci(runwire): verify optional consumer on PHP 8.4 and 8.5
abmmhasan Sep 29, 2026
546273f
test(runwire): reject stale request scopes after worker replacement
abmmhasan Sep 29, 2026
1e2c4a7
docs(plan): align Runwire scope wording
abmmhasan Sep 29, 2026
c9d80b9
docs(cluster): link Runwire worker lifecycle
abmmhasan Sep 29, 2026
3466038
docs(node): cover bounded and Runwire maintenance
abmmhasan Sep 29, 2026
e6cd20c
test(runwire): stress persistent request memoizer cleanup
abmmhasan Sep 29, 2026
c1bf6cb
test(runwire): add matched integration certification workload
abmmhasan Sep 29, 2026
30ad36c
test(runwire): add bounded persistent-worker soak
abmmhasan Sep 29, 2026
91cc2d4
test(runwire): record resolved runtime capabilities
abmmhasan Sep 29, 2026
e90378b
ci(runwire): certify matched workload and persistent soak
abmmhasan Sep 29, 2026
db95deb
test(runwire): cover worker failure and topology fallback
abmmhasan Sep 29, 2026
56862e5
fix(runwire): use valid cache keys in release workloads
abmmhasan Sep 29, 2026
0d26254
fix(runwire): use valid cache keys in release workloads
abmmhasan Sep 29, 2026
3d659d2
fix(runwire): retain task scope in soak workload
abmmhasan Sep 29, 2026
12f4867
fix(runwire): test cancellation in request-owned scopes
abmmhasan Sep 29, 2026
b5d623b
fix(runwire): satisfy PHPForge certification analysis
abmmhasan Sep 29, 2026
1b6559b
fix(runwire): keep certification operation void
abmmhasan Sep 29, 2026
afdddbc
docs(runwire): declare certification usage shapes
abmmhasan Sep 29, 2026
cee1d9b
fix(runwire): normalize certification resource usage
abmmhasan Sep 29, 2026
b8e7d36
fix(runwire): accept getrusage array key domain
abmmhasan Sep 29, 2026
cd24d1e
style(runwire): adopt PHPForge callable form
abmmhasan Sep 29, 2026
c1ff97b
style(runwire): align soak with PHPForge
abmmhasan Sep 29, 2026
7d2a561
test(runwire): keep failure fixture PHPForge-clean
abmmhasan Sep 29, 2026
8dd980f
style(runwire): separate intentional soak throw
abmmhasan Sep 29, 2026
342bb0c
docs(plan): close Runwire 2.1 release scope
abmmhasan Sep 29, 2026
51fcba7
docs(plan): finalize Runwire release-ready status
abmmhasan Sep 29, 2026
8ec3789
:memo: docs(plans): add CacheLayer 4.0 release re-audit report and up…
abmmhasan Sep 29, 2026
2845cb6
fix(atomic): discard deferred state before consume
abmmhasan Sep 29, 2026
1f127ef
fix(atomic): discard deferred state before consume
abmmhasan Sep 29, 2026
d3ec1ff
fix(atomic): discard deferred state before consume
abmmhasan Sep 29, 2026
8ade101
fix(atomic): discard deferred state before consume
abmmhasan Sep 29, 2026
77a5421
fix(atomic): discard deferred state before consume
abmmhasan Sep 29, 2026
20c341c
fix(atomic): discard deferred state before consume
abmmhasan Sep 29, 2026
ce367b1
fix(atomic): discard deferred state before consume
abmmhasan Sep 29, 2026
2062a28
fix(atomic): discard deferred state before consume
abmmhasan Sep 29, 2026
5fc809c
fix(atomic): discard deferred state before consume
abmmhasan Sep 29, 2026
4df8e56
fix(atomic): discard deferred state before consume
abmmhasan Sep 29, 2026
f46f6cd
fix(redis): isolate clear domains and guard stale cleanup
abmmhasan Sep 29, 2026
31a9728
fix(traversal): bound allocation before descent
abmmhasan Sep 29, 2026
a06bb3b
fix(memoize): avoid traversing closure captures
abmmhasan Sep 29, 2026
4ce8e51
fix(memoize): preserve identities across isolated flushes
abmmhasan Sep 29, 2026
86fa96d
fix(memoize): preserve identities across isolated flushes
abmmhasan Sep 29, 2026
a8c03b2
fix(cache): avoid unsafe tagged stale deletion
abmmhasan Sep 29, 2026
b8a6375
fix(tiered): keep L1 fenced until full reconciliation
abmmhasan Sep 29, 2026
5b1e5f6
fix(redis): redact authentication credentials in traces
abmmhasan Sep 29, 2026
435c1d3
fix(cluster): expose retained history upper boundary
abmmhasan Sep 29, 2026
6709389
fix(cluster): expose Redis stream upper boundary
abmmhasan Sep 29, 2026
d0810a2
fix(cluster): recover from empty or reset invalidation history
abmmhasan Sep 29, 2026
8b9529a
test(atomic): prevent deferred consume resurrection
abmmhasan Sep 29, 2026
e587e4e
test(atomic): cover deferred consume across expanded backends
abmmhasan Sep 29, 2026
52b518e
test(atomic): cover deferred consume reconciliation
abmmhasan Sep 29, 2026
7d83409
test(atomic): cover deferred consume reconciliation
abmmhasan Sep 29, 2026
febf920
test(atomic): cover deferred consume reconciliation
abmmhasan Sep 29, 2026
bc4cea3
test(atomic): cover deferred consume reconciliation
abmmhasan Sep 29, 2026
3932440
test(atomic): cover deferred consume reconciliation
abmmhasan Sep 29, 2026
6a90500
test(redis): protect operational domains and concurrent replacements
abmmhasan Sep 29, 2026
4ccf0f1
test(cluster): cover complete history loss and reset
abmmhasan Sep 29, 2026
0222c96
test(tiered): keep failed L1 globally fenced
abmmhasan Sep 29, 2026
5f09a82
test(traversal): cover wide deep and cyclic graphs
abmmhasan Sep 29, 2026
408c770
test(memoize): cover recursive captures and isolated identity flush
abmmhasan Sep 29, 2026
c5f3c4d
test(runwire): isolate memoizer identities across request flushes
abmmhasan Sep 29, 2026
a4a8257
test(cluster): reproduce complete PDO history loss
abmmhasan Sep 29, 2026
84c51b2
test(cluster): reproduce complete Redis history loss
abmmhasan Sep 29, 2026
ed201cf
test(redis): require sensitive auth helper parameters
abmmhasan Sep 29, 2026
bbca5f2
test(redis): keep auth secrets out of traces
abmmhasan Sep 29, 2026
74c3663
test(valkey): preserve operational domains on clear
abmmhasan Sep 29, 2026
bf0068a
refactor(tiered): keep monotonic L1 fence branch-light
abmmhasan Sep 29, 2026
ac55943
refactor(tiered): reduce fence complexity under PHPForge
abmmhasan Sep 29, 2026
c946ad1
fix(qa): close re-audit regression gates
abmmhasan Sep 29, 2026
306173e
fix(codec): bound value and tag graphs independently
abmmhasan Sep 29, 2026
efb52d1
docs(plan): track re-audit remediation progress
abmmhasan Sep 29, 2026
9795789
docs(plan): add re-audit remediation batch
abmmhasan Sep 29, 2026
4f4e391
docs(plan): close release re-audit remediation
abmmhasan Sep 29, 2026
3aaa433
docs(plan): finalize re-audit closure evidence
abmmhasan Sep 29, 2026
909f73f
fix(release): close final sweep gaps
abmmhasan Sep 29, 2026
6984555
docs(plan): close final release sweep
abmmhasan Sep 29, 2026
73701d8
:sparkles: refactor(cluster): enforce cold clear on new cursor scopes…
abmmhasan Sep 29, 2026
f8c9f0e
docs(release): finalize CacheLayer 4.0 documentation
abmmhasan Sep 29, 2026
726e945
:construction_worker: ci(workflows): add release workflow trigger and…
abmmhasan Sep 29, 2026
b752add
🔥 chore(ci): remove PHPForge Pint diagnostic workflow
abmmhasan Sep 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/regression_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@ body:
attributes:
label: Environment details
description: PHP version, Composer version, OS, CI provider (if relevant).
placeholder: PHP 8.3, Composer 2.9, Ubuntu 24.04...
placeholder: PHP 8.4, Composer 2.10, Ubuntu 24.04...
validations:
required: true
256 changes: 256 additions & 0 deletions .github/workflows/release-verification.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,256 @@
name: "Release Verification"

on:
pull_request:
branches: [ "main", "master", "develop", "development" ]
push:
branches: [ "main", "master" ]
workflow_dispatch:

permissions:
contents: read

jobs:
core-platform:
name: Core smoke - PHP ${{ matrix.php }} - ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
php: [ "8.4", "8.5" ]
os: [ ubuntu-24.04, windows-latest ]
steps:
- uses: actions/checkout@v7
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: composer:v2
extensions: mbstring, mongodb, pdo, pdo_sqlite, opcache
coverage: none
- run: composer install --no-dev --no-interaction --prefer-dist --no-progress --classmap-authoritative --ignore-platform-req=ext-mongodb
- run: composer check-platform-reqs --no-dev
- name: Core smoke without CLI OPcache
run: php -d error_reporting=E_ALL -d opcache.enable_cli=0 tools/release/core-smoke.php
- name: Core smoke with CLI OPcache
run: php -d error_reporting=E_ALL -d opcache.enable_cli=1 tools/release/core-smoke.php

clean-consumer:
name: Clean no-dev consumer - PHP ${{ matrix.php }}
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
php: [ "8.4", "8.5" ]
steps:
- uses: actions/checkout@v7
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: composer:v2
coverage: none
- name: Resolve candidate in fresh consumer
working-directory: tools/release/consumer
run: composer update --no-dev --no-interaction --prefer-dist --no-progress
- name: Reinstall locked candidate as production-only
working-directory: tools/release/consumer
shell: bash
run: rm -rf vendor && composer install --no-dev --prefer-dist --optimize-autoloader --no-interaction --no-progress
- name: Smoke production consumer
working-directory: tools/release/consumer
run: php -d error_reporting=E_ALL smoke.php

runwire-consumer:
name: Runwire 2.1 consumer - PHP ${{ matrix.php }} - ${{ matrix.dependencies }}
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
php: [ "8.4", "8.5" ]
dependencies: [ lowest, stable ]
steps:
- uses: actions/checkout@v7
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
tools: composer:v2
extensions: pdo, pdo_sqlite
coverage: none
- name: Resolve CacheLayer with Runwire 2.1
working-directory: tools/release/runwire-consumer
shell: bash
run: |
set -euo pipefail
if [ "${{ matrix.dependencies }}" = "lowest" ]; then
composer update --prefer-lowest --prefer-stable --no-interaction --prefer-dist --no-progress
else
composer update --prefer-stable --no-interaction --prefer-dist --no-progress
fi
composer check-platform-reqs
- name: Run Runwire integration smoke
working-directory: tools/release/runwire-consumer
run: php -d error_reporting=E_ALL smoke.php
- name: Run matched Runwire certification workload
working-directory: tools/release/runwire-consumer
run: php -d error_reporting=E_ALL certify.php
- name: Run persistent-worker Runwire soak
working-directory: tools/release/runwire-consumer
run: php -d error_reporting=E_ALL soak.php

psr-contracts:
name: Independent PSR-6 / PSR-16 contracts
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v7
- uses: shivammathur/setup-php@v2
with:
php-version: "8.4"
tools: composer:v2
coverage: none
- name: Install independent consumer
working-directory: tools/release/psr-consumer
run: composer update --no-interaction --prefer-dist --no-progress --prefer-stable
- name: Materialize independent integration fixtures
working-directory: tools/release/psr-consumer
shell: bash
run: |
mkdir -p tests
cat > tests/Psr6MemoryIntegrationTest.php <<'PHP'
<?php
declare(strict_types=1);

use Cache\IntegrationTests\CachePoolTest;
use Infocyph\CacheLayer\Cache\Cache;
use Infocyph\CacheLayer\Cache\CacheOptions;
use Psr\Cache\CacheItemPoolInterface;

final class Psr6MemoryIntegrationTest extends CachePoolTest
{
protected array $skippedTests = [
'testBasicUsageWithLongKey' => 'CacheLayer intentionally supports 64-character logical keys, satisfying the PSR minimum.',
];

public function createCachePool(): CacheItemPoolInterface
{
return Cache::sqlite(
'psr6',
sys_get_temp_dir() . '/cachelayer-psr6-' . getmypid() . '.sqlite',
new CacheOptions(allowObjects: true),
);
}
}
PHP

cat > tests/Psr16MemoryIntegrationTest.php <<'PHP'
<?php
declare(strict_types=1);

use Cache\IntegrationTests\SimpleCacheTest;
use Infocyph\CacheLayer\Cache\Cache;
use Infocyph\CacheLayer\Cache\CacheOptions;
use Psr\SimpleCache\CacheInterface;

final class Psr16MemoryIntegrationTest extends SimpleCacheTest
{
protected array $skippedTests = [
'testBasicUsageWithLongKey' => 'CacheLayer intentionally supports 64-character logical keys, satisfying the PSR minimum.',
];

public function createSimpleCache(): CacheInterface
{
return Cache::sqlite(
'psr16',
sys_get_temp_dir() . '/cachelayer-psr16-' . getmypid() . '.sqlite',
new CacheOptions(allowObjects: true),
);
}
}
PHP
- name: Run upstream integration suites
working-directory: tools/release/psr-consumer
run: vendor/bin/phpunit tests

docs:
name: Documentation warnings as errors
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v7
- uses: actions/setup-python@v6
with:
python-version: "3.13"
- run: python -m pip install --disable-pip-version-check -r docs/requirements.txt
- run: python -m sphinx -W --keep-going -b html docs docs/_build/html

redis-cluster:
name: Real Redis Cluster
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v7
- uses: shivammathur/setup-php@v2
with:
php-version: "8.4"
tools: composer:v2
extensions: redis
coverage: none
- run: composer install --no-dev --no-interaction --prefer-dist --no-progress --classmap-authoritative
- name: Start three-node Redis Cluster
shell: bash
run: |
set -euo pipefail
for port in 7001 7002 7003; do
docker run -d --name "cachelayer-redis-$port" --network host redis:8.10-alpine redis-server --port "$port" --cluster-enabled yes --cluster-config-file "nodes-$port.conf" --cluster-node-timeout 5000 --cluster-announce-ip 127.0.0.1 --cluster-announce-port "$port" --cluster-announce-bus-port "$((port + 10000))" --appendonly no --protected-mode no
done
for attempt in {1..60}; do
if docker exec cachelayer-redis-7001 redis-cli -p 7001 ping | grep -q PONG; then break; fi
sleep 1
done
docker exec cachelayer-redis-7001 redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 --cluster-replicas 0 --cluster-yes
for attempt in {1..60}; do
if docker exec cachelayer-redis-7001 redis-cli -c -p 7001 cluster info | tr -d '\r' | grep -q "cluster_state:ok"; then
break
fi
sleep 1
done
docker exec cachelayer-redis-7001 redis-cli -c -p 7001 cluster info | tr -d '\r' | grep -q "cluster_state:ok"
- name: Exercise CacheLayer against real Redis Cluster
env:
CACHELAYER_REDIS_CLUSTER_SEEDS: "127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003"
run: php -d error_reporting=E_ALL tools/release/redis-cluster-smoke.php
- if: always()
shell: bash
run: docker rm -f cachelayer-redis-7001 cachelayer-redis-7002 cachelayer-redis-7003 >/dev/null 2>&1 || true

scylla-cql:
name: Real Scylla CQL
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v7
- uses: shivammathur/setup-php@v2
with:
php-version: "8.4"
tools: composer:v2
coverage: none
- run: composer install --no-dev --no-interaction --prefer-dist --no-progress --classmap-authoritative
- name: Start ScyllaDB CQL service
shell: bash
run: |
set -euo pipefail
docker run -d --name cachelayer-scylla -p 9042:9042 scylladb/scylla:2026.2 --reactor-backend epoll --smp 1 --memory 1G --overprovisioned 1 --developer-mode=1
for attempt in {1..120}; do
if docker exec cachelayer-scylla cqlsh -e "SELECT release_version FROM system.local;" >/dev/null 2>&1; then break; fi
sleep 2
done
docker exec cachelayer-scylla cqlsh -e "CREATE KEYSPACE IF NOT EXISTS cachelayer WITH replication = {'class':'NetworkTopologyStrategy','datacenter1':1};"
- name: Install pinned Scylla PHP CQL driver
shell: bash
run: |
set -euo pipefail
sudo apt-get update
sudo apt-get install -y libuv1 libgmp10
mkdir -p .ci/scylla-driver
curl -fsSL https://github.com/he4rt/scylladb-php-driver/releases/download/v1.5.1/manylinux_2_28_x86_64-php8.4-nts-cassandra.tar.gz -o .ci/scylla-driver/driver.tar.gz
tar -xzf .ci/scylla-driver/driver.tar.gz -C .ci/scylla-driver
php -d "extension=$PWD/.ci/scylla-driver/cassandra.so" -r 'if (!class_exists("Cassandra")) { throw new RuntimeException("Cassandra extension did not load."); }'
- name: Exercise CacheLayer against real CQL
run: php -d error_reporting=E_ALL -d "extension=$PWD/.ci/scylla-driver/cassandra.so" tools/release/scylla-cql-smoke.php
- if: always()
run: docker rm -f cachelayer-scylla >/dev/null 2>&1 || true
16 changes: 13 additions & 3 deletions .github/workflows/security-standards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,28 @@ on:
- cron: "0 0 * * 0"
push:
branches: [ "main", "master" ]
tags: [ "v*", "[0-9]*" ]
pull_request:
branches: [ "main", "master", "develop", "development" ]

jobs:
phpforge:
if: github.event_name != 'push' || !startsWith(github.ref, 'refs/tags/')
uses: infocyph/phpforge/.github/workflows/security-standards.yml@main
permissions:
security-events: write
actions: read
contents: read
with:
php_extensions: "apcu, mbstring, memcached, mongodb, pdo, pdo_mysql, pdo_pgsql, pdo_sqlite, redis, sysvshm"
php_extensions: "apcu, mbstring, memcached, mongodb, pcntl, pdo, pdo_mysql, pdo_pgsql, pdo_sqlite, redis, sysvshm"
fail_on_skipped_tests: true
integration_services: '["mysql","postgres","sqlite","redis","valkey","memcached","scylladb"]'
service_topologies: '{}'
integration_services: '["mysql","mariadb","postgres","sqlite","mongodb","redis","valkey","memcached","scylladb"]'
service_topologies: '{"mongodb":"replica-set"}'

release:
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')
uses: infocyph/phpforge/.github/workflows/release.yml@main
permissions:
contents: write
secrets:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
18 changes: 14 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
![Packagist Version](https://img.shields.io/packagist/v/infocyph/CacheLayer)
![Packagist PHP Version](https://img.shields.io/packagist/dependency-v/infocyph/CacheLayer/php)

CacheLayer is a PHP 8.3+ caching toolkit built around four deliberately separate concerns:
CacheLayer is a PHP 8.4+ caching toolkit built around four deliberately separate concerns:

```text
CacheLayer
Expand Down Expand Up @@ -34,6 +34,8 @@ composer require infocyph/cachelayer

Choose extensions and client packages only for the backends you use: APCu, Redis/Valkey, Memcached, PDO, SysV shared memory, MongoDB, or Cassandra/ScyllaDB.

For 3.x upgrades, read `docs/upgrade-4.0.rst` before deployment. 4.0 raises the minimum runtime to PHP 8.4 and intentionally changes serialization, storage identity, cursor, counter, and cache-contract behavior.

## Cache

```php
Expand Down Expand Up @@ -204,7 +206,7 @@ function createCache(string $integrityKey): Cache
}
```

Records use only the CacheLayer v2 markers `cl2:`, `cl2-gz:`, and `cl2-sig:`. Compression is threshold-based and retained only when smaller. HMAC verification, payload bounds, bounded decompression, and deserialization policy are isolated per cache instance. Corrupt payloads are safe misses.
Records use the plain/compressed v2 markers `cl2:` and `cl2-gz:`, plus the identity-bound signed marker `cl3-sig:`. Compression is threshold-based and retained only when smaller. HMAC verification, payload bounds, bounded decompression, and deserialization policy are isolated per cache instance. Corrupt payloads are safe misses.

Construction and configuration errors throw. Runtime backend failures default to fail-open: reads become misses, writes/deletes return `false`, and `backend_failure` is recorded. Set `failOpen: false` to propagate runtime failures. Pass deploy-varying values from the application's composition root; CacheLayer never reads process environment state.

Expand Down Expand Up @@ -235,11 +237,19 @@ $runtime->consume();

Failed local invalidation stops consumption without advancing the cursor; operators can repair the cause and retry. A poison event can only be skipped explicitly with `skipEventAfterClear()`, which clears the local namespace before advancing. Plain key invalidation cannot fence an in-flight resolver, so mutable read-through data that requires ordering should also use a tag generation. It does not replicate values and is not a distributed lock, session store, or counter system.

## Runwire 2.1 integration

CacheLayer 4.0 ships optional Runwire 2.1 integration without making Runwire a core dependency. A framework shares its active `RuntimeContext` at worker/application bootstrap and the current `RequestContext` / `CoroutineScope` at the request or task boundary. CacheLayer then uses relevant capabilities automatically; when Runwire is absent, inactive, or missing a capability, the ordinary CacheLayer path remains in use.

Runwire keeps ownership of listeners, workers, supervisors, and event loops. `RunwireWorkerIntegration` can place bounded Cluster invalidation consumption and Node SQLite maintenance inside a host-provided task/service worker scope; CacheLayer never starts background work merely because Runwire is installed. Synchronous backend calls remain synchronous.

Concurrent persistent Runwire requests receive request-owned memoizer state. If a concurrent runtime is bound without a shared request scope, memoization helpers bypass the process-global cache rather than risk cross-request leakage. See `docs/runwire.rst` and the executable `examples/runwire-invalidation-worker.php`.

## Atomic counters and memoization

`AtomicCounters` uses an `AtomicCounterStoreInterface`; Redis/Valkey is the distributed implementation. Counters are never emulated with cache `get()` plus `set()`. Atomic counters are separate from `Cache::atomic()`: counters mutate numeric state, while the cache capability provides conditional claim/replace/consume primitives for encoded cache records.
`AtomicCounters` uses an `AtomicCounterStoreInterface`; Redis/Valkey is the distributed implementation. Counters are never emulated with cache `get()` plus `set()`. They live in a dedicated `cachelayer:counter:<namespace>:` keyspace, so ordinary cache `clear()` does not reset them, and the Lua update returns an exact decimal string before PHP range validation. Atomic counters are separate from `Cache::atomic()`: counters mutate numeric state, while the cache capability provides conditional claim/replace/consume primitives for encoded cache records.

The `memoize()`, `remember(object: ...)`, and `once()` helpers plus `MemoizeTrait` provide bounded process-local memoization. Their state survives requests in persistent workers until evicted or reset with `flush_memoizers()`; call that reset at request boundaries when cross-request reuse is not intended. They are independent of persistent backend caching.
The `memoize()`, `remember(object: ...)`, and `once()` helpers plus `MemoizeTrait` provide bounded process-local memoization on the normal path. With an active Runwire request scope they use request-owned memoizers; a concurrent persistent Runwire runtime without a shared request scope bypasses global memoization rather than leaking state between requests. `flush_memoizers()` resets the currently owned memoizer scope. They are independent of persistent backend caching.

## Metrics and benchmarks

Expand Down
8 changes: 7 additions & 1 deletion benchmarks/CachePolicyBench.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,13 @@ public function benchCompressedCodec(array $params): int
public function benchHmacCodec(): int
{
$codec = new CachePayloadCodec(new CacheOptions(integrityKey: 'benchmark-secret'));
$record = $codec->decode($codec->encode($this->payload, null));
$payload = $codec->encode(
$this->payload,
null,
storageIdentity: 'benchmark',
key: 'payload',
);
$record = $codec->decode($payload, 'benchmark', 'payload');

return strlen((string) $record?->value);
}
Expand Down
6 changes: 4 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,15 @@
}
],
"require": {
"php": ">=8.3",
"php": ">=8.4",
"opis/closure": "^4.5",
"psr/cache": "^3.0",
"psr/simple-cache": "^3.0"
},
"require-dev": {
"infocyph/phpforge": "dev-main@dev",
"mongodb/mongodb": "^1.20 || ^2.0"
"infocyph/runwire": "2.1",
"mongodb/mongodb": "*"
},
"suggest": {
"ext-apcu": "For APCu-based caching (in-memory, per-process)",
Expand All @@ -55,6 +56,7 @@
"ext-pdo_sqlite": "For default SQLite usage via Cache::pdo(...) or Cache::sqlite(...)",
"ext-redis": "For Redis-based caching (persistent, networked)",
"ext-sysvshm": "For shared-memory caching via SharedMemoryCacheAdapter",
"infocyph/runwire": "For optional Runwire 2.1 request/task isolation and worker-owned invalidation/maintenance integration",
"mongodb/mongodb": "For MongoDB caching via MongoDbCacheAdapter"
},
"minimum-stability": "stable",
Expand Down
Loading
Loading