EN · ÖZGÜN DEPO BELGESİ
Bağımsız Free motoru
Özgün İngilizce metin. Komutlar ve kanıtlar, belgede belirtilen revizyona ve ortama aittir.
product/free-core/cache-core-free/README.md
Bu sayfada
Original standalone Free cache engine
This bounded implementation is independently authored in this task against public WordPress cache API contracts and Redis protocol documentation. It is not a clean-room claim: the worker previously inspected other implementations for earlier review tasks. No code was copied from proprietary Object Cache Pro or the GPL Redis Object Cache dependency. GPL-2.0-or-later applies only to newly authored files in this component; the surrounding repository’s upstream notices remain unchanged.
Public references inspected on 2026-10-02:
- https://developer.wordpress.org/reference/classes/wp_object_cache/
- https://developer.wordpress.org/reference/classes/wp_object_cache/incr/
- https://developer.wordpress.org/reference/classes/wp_object_cache/decr/
- https://redis.io/docs/latest/commands/set/
- https://redis.io/docs/latest/commands/watch/
- https://redis.io/docs/latest/develop/using-commands/transactions/
- https://developer.wordpress.org/plugins/wordpress-org/detailed-plugin-guidelines/
No source/asset bundling from those projects is needed; the included GPL-2 text is standard license material. Maintainer/brand identity and WordPress.org review remain publication gates. There has been no public submission or deployment.
Explicit configuration and lifecycle
define('CACHE_CORE_FREE_CONFIG', [
'host' => '127.0.0.1', 'port' => 6379, 'database' => 0,
'prefix' => 'operator-unique-installation-identifier',
// Optional: 'recovery_dir' => '/durable/shared/php-uid-owned/cache-recovery',
'timeout' => 0.5, 'read_timeout' => 0.5,
// 'password' => 'operator-secret', // or ['acl-user', 'operator-secret']
]);
Baseline: WordPress 6.5+, PHP 8.0+, PhpRedis, Redis 6.2+, single server, plain TCP. Unique nonempty prefix is REQUIRED for persistence. Missing prefix means local-only caching and no Redis writes. Different installations must use distinct prefixes in a shared Redis database. Configuration errors/connectivity fail softly without showing credential-bearing exceptions.
Activation does not enable persistence. The admin Tools/network Settings form uses
capability plus nonce checks for enable/update/disable. The fixture/integration API
is CacheCoreFree\manage_dropin('enable'|'update'|'disable') after loading plugin or
lifecycle.php. It refuses foreign files and symlinks; enable atomically publishes
without overwriting, own update uses same-directory atomic replacement. Actions
serialize using a local lock. Concurrent external filesystem actors do not honor
that lock and require operator coordination. The installed owned drop-in embeds
only the original engine plus wrappers, so plugin-folder absence cannot break its
runtime dependency. Source template should not be manually copied as an installed
drop-in. Explicit update installs a new snapshot; no remote code updater exists.
Semantics and limits
Scalar/array/object values use a format-marked PHP serialization envelope, so false and null remain distinct found values. Redis is trusted operator infrastructure; as with PHP object caching generally, do not allow untrusted parties to inject serialized PHP objects into this namespace. Top-level object clone behavior follows WordPress; deep mutable references are not independently cloned.
Persistent reads obtain value and TTL atomically; local expiry is conservative. Bulk operations return keyed caller order and currently loop over single operations, not an optimized pipeline or all-or-nothing batch. Add/replace use SET NX/XX.
Numeric operations WATCH the value and namespace generation, read the existing PHP value, apply PHP is_numeric conversion (otherwise zero), cast only offset to integer, clamp negative results to zero, then MULTI/EXEC SET XX KEEPTTL. Thus Redis preserves its exact expiration without PHP wall-clock arithmetic or Lua double conversion. Eight conflicted attempts return false and invalidate that local value, without claiming mutation success or disabling a healthy backend. Redis errors clear previous persistent runtime entries and disable the backend for the entire request. Offline request-local writes are never replayed automatically.
Recovery uses a durable per-request ticket and shared request lease in a local
filesystem lock domain. The ticket exists before Redis connects. Failed/crashed
requests retain their ticket; a pending marker also stops overlapping requests
from trusting persistent runtime/Redis data. A subsequent healthy request must
obtain an exclusive lease, wait until earlier SQL writers have finished, and rotate
this namespace before it can resume persistent reads/writes. Recovery never replays
offline writes. Every connection attempt holds only a shared lease, including initial Redis outages.
Recovery upgrades to exclusive only under the state lock and restores shared even
on failed upgrades or failed invalidation. A live earlier writer keeps recovery
request-local with recovery_waiting_for_requests. A new request arriving during
actual exclusive invalidation waits at most 1000 retries with 1ms pauses; exhaustion
refuses bootstrap with recovery_lease_busy before any unrecorded SQL writer.
recovery_dir defaults to WP_CONTENT_DIR/.cache-core-free-recovery; an optional
absolute configured path must survive requests and use a coherent flock-capable
filesystem. Each prefix has a hashed subdirectory, fixed lock inodes, atomic state
and private 0600 tickets/0700 directories. Web and CLI MUST run under the same PHP
UID, or operators must provision a compatible path/ownership policy. All nodes
sharing a Redis namespace MUST share this same filesystem/lock domain; independent
node-local paths are unsupported. Shared filesystem/multi-node operation is not
validated. Losing initial state forces namespace invalidation. Missing/unwritable
initial recovery setup or ticket fails bootstrap with an actionable error: silently
allowing unrecorded SQL writes would make later Redis reuse unsafe. Ordinary Redis
outages after the ticket exists remain fail-soft. This availability tradeoff is
intentional. No ticket or marker contains credentials or cached values.
State-lock contention retries at most 20 times with 1ms pauses. Every persistent operation checks the marker and at most 1000 ticket records (1010 directory entries); excess state disables persistence with a diagnostic. Healthy teardown removes only its own ticket, failed teardown leaves it behind. Filesystem repair, restoring a backup of recovery state, namespace/path migration, and power-loss durability require operator coordination and namespace invalidation; process-crash ticket recovery is implemented, machine power-loss guarantees are not established. WordPress database changes made outside this plugin’s cache requests remain outside this recovery contract. Existing in-flight operations still have ordinary cache invalidation races around generation switches.
wp_cache_flush() rotates this installation’s namespace generation, leaving other
prefixes untouched, then runs a bounded scoped SCAN/UNLINK cleanup of valid old
32-hex-generation/64-hex-value keys under only its hashed installation prefix.
Each deletion batch WATCHes the generation so a concurrent rotation cannot let
this cleanup delete another flush’s current data. Maximum per flush: 10 SCAN calls,
1000 visited keys and 100-key deletion batches. Metadata, malformed/unrecognized
keys, other prefixes and the observed current generation are never selected.
Status reports scoped_cleanup: pending when capped or interrupted by another
rotation, and pending after backend failure on errors. Logical flush does not
guarantee complete physical purge or memory reclamation: remaining keys (including
expire=0) can persist until another scoped cleanup or eviction, and concurrent
old-generation writers can add keys after the scan. Capacity remains a material
release limitation even when a bounded scan completes. Offline flush returns false because
remote invalidation could not happen. Group flush support is false and the wrapper
also returns false, avoiding WordPress’s possible global-flush polyfill.
No Sentinel/Cluster/Relay/TLS or performance superiority claims. Runtime absence of PhpRedis falls back to request-local caching. Broader PHP/Redis/WordPress versions, network partitions, production concurrency and unrelated plugin workloads need separate evidence before production release.
Validation
Focused original fixture tests outside the distributable folder:
php product/free-core/tests/faults.php
php product/free-core/tests/lifecycle.php
These stubs prove bounded failure/local behavior and file ownership behavior; real WordPress multisite, Redis CAS concurrency, TTL and lifecycle tests belong to the integration owner’s exact-code/version report. No passing evidence should be inferred merely from the presence of the source or this README.
Actual Cloud evidence
The original runtime passed 66 public-cache assertions, 16 cross-process scope/ flush assertions and 17 actual Redis recovery/TTL assertions on WordPress 6.8.3, PHP 8.3.28, PhpRedis 6.1.0 and Redis 7.4.2. Four concurrent workers persisted all 78 successful increments; two of 80 attempts explicitly returned false at the CAS retry limit. Actual service pause/unpause confirmed stale runtime removal, fresh request-local fallback and recovery after operator namespace invalidation (before the automatic recovery lease change), without replaying offline writes. An earlier Docker stop/DNS case exceeded the 20-second harness budget; socket cleanup was corrected, but DNS latency is not established as bounded by the Redis connect timeout.
HTTP lifecycle tests use real forms/permissions/nonces, not browser visual QA. Publishing an absent drop-in now invalidates the configured namespace before installation to prevent stale cache and network-plugin metadata after re-enable. Failed invalidation refuses configured enable. The explicit local-only path with missing prefix remains allowed. These are private fixture results; other runtime versions and broader production workloads remain unvalidated.
Automatic lease/ticket recovery adds focused local tests; actual Redis retained-state and delayed-writer evidence must be reported for the final exact installed snapshot.