Skip to content

feat(#46): bound the process-wide database cache - #82

Merged
s2x merged 2 commits into
masterfrom
feat/46-bounded-database-cache
Aug 22, 2026
Merged

feat(#46): bound the process-wide database cache#82
s2x merged 2 commits into
masterfrom
feat/46-bounded-database-cache

Conversation

@s2x

@s2x s2x commented Aug 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #46 — bounds the process-wide Database cache so an application opening many distinct cluster files or connection strings no longer retains an unbounded number of live native FDBDatabase handles for the process lifetime.

Changes

  • src/FoundationDB.php: replaced the unbounded static cache with a bounded LRU cache (default capacity 8). open() / openWithConnectionString() reuse cached instances and evict the least-recently-used entry when over capacity. Eviction drops only the cache reference — a Database still held by the application keeps working, and its native handle is released when the last reference disappears (destructor) or on close().
  • New public API: FoundationDB::setMaxDatabases(int) / getMaxDatabases() (rejects 0/negative with InvalidArgumentException; rejected values leave the current bound untouched). FoundationDB::reset() restores the default bound and clears the cache.
  • tests/Unit/FoundationDBDatabaseCacheTest.php: unit tests for LRU eviction, capacity bound, config validation, shrinks, idempotent trim and reset — pure cache logic via reflection, no live cluster needed.
  • docs/advanced.md: new "Database Cache" section documenting lifetime, ownership and the new knob.
  • CHANGELOG.md: [#46] entry under Changed.

Verification

  • composer lint — clean (PHPCS + Rector dry-run + PHPStan)
  • composer test:unit — 469 tests, 946 assertions
  • Integration suite on a live 5-node Docker FDB cluster — 209 tests, 505 assertions

FoundationDB::open()/openWithConnectionString() now keep a bounded LRU
cache (default 8) of Database objects instead of retaining every distinct
database for the process lifetime. Eviction drops only the cache
reference; a Database still held by the app keeps working and its native
handle is released when the last reference disappears or on close().

Adds FoundationDB::setMaxDatabases()/getMaxDatabases() (>=1) and resets
the bound via FoundationDB::reset(). Updates docs/advanced.md and
CHANGELOG.md. Unit coverage in tests/Unit/FoundationDBDatabaseCacheTest.php.
…plicit

CI resolves latest deps because composer.lock is gitignored; phpstan 2.2.9
(2026-08-22) newly flags the overflow-checking '$value < 0' in Tuple::decodePositiveInt
as always-false, and 2.2.9 is also incompatible with rector. Pin the known-good
versions from the last green CI run (#80): phpstan 2.2.8, rector 2.6.3.

decodePositiveInt now detects the >= 2^63 overflow explicitly via the top byte
(8 bytes + MSB set) instead of relying on 64-bit int overflow that static analysis
cannot model. Behavior is identical (an 8-byte value with the MSB clear like
PHP_INT_MAX still returns an int), unit-verified by the tuple roundtrip tests, and
the check is robust against future PHPStan versions.
@s2x
s2x merged commit 1ce859e into master Aug 22, 2026
6 checks passed
@s2x
s2x deleted the feat/46-bounded-database-cache branch August 22, 2026 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Memory] Unbounded static database cache in FoundationDB

1 participant