Complete Database persistence lifecycles and current Laravel parity#452
Conversation
Record the complete, reviewed implementation plan for the Database audit and its required Redis, Core, Server, Pool, Support, and documentation boundaries.\n\nCapture exact task and fork ownership, pooled Redis transaction state, SQLite classification and single-owner pooling, truthful transaction cleanup, coroutine-safe Eloquent boot publication, current Laravel parity, performance corrections, metadata, documentation, regression coverage, and full validation criteria.\n\nDocument the evidence behind each mechanism, every owner-approved hot-path cost, and the rejected alternatives so implementation can remain complete without accumulating speculative abstractions or compatibility debris.
Add a TaskTerminated event that carries the exact native server and task after task action and result handling completes. Dispatch terminal cleanup through a listener-aware boundary on every success and failure path while preserving the earliest action, finish, or cleanup throwable. Cover both native task signatures, dispatch ordering, no-listener behavior, and combined failure precedence.
Add BeforeServerFork as the final parent-process boundary immediately before the native Swoole server starts and forks its child processes. Allow lifecycle consumers to discard parent-owned sockets, pools, timers, and context without relying on per-port events. Preserve native start failure behavior and cover exact event payload, ordering, listener failure, and false start results.
Retain exact non-coroutine pooled wrappers in ConnectionResolver and detach their context before terminal release or process-safe discard. Replace reflective configured-name cleanup with a concrete lifecycle listener that never resolves unused owners and exhausts independent cleanup phases. Register task, pre-fork, and worker-start boundaries through DatabaseServiceProvider, bind the queue entity resolver at its canonical contract, and cover aliases, read and write roles, publication failures, reentrant cleanup, custom resolvers, unresolved services, and failure precedence.
Register at most one terminal defer per pool and owning coroutine while keeping callback-form transactions and pipelines on their immediate-release path. Use coroutine owner IDs so copied context cannot inherit a defer that the child does not own. Keep WATCH, MULTI, PIPELINE, EXEC, UNWATCH, RESET, and native DISCARD state on the exact wrapper generation. Complete command event handling before ownership handoff, discard abandoned native queue or watch state, and preserve established failure precedence without network checks or a parallel transaction model. Add unit and live Redis coverage for copied contexts, bounded defer retention, callback release, optimistic conflicts, listener failures, selected databases, native mode recovery, and pool generation replacement.
Aggregate already-created proxies through RedisManager so task completion releases their exact pinned wrappers and process boundaries discard them before flushing resolved pools. Make purge use the proxy real pool identity, detach context before pool destruction, continue independent manager and factory cleanup after failures, and avoid resolving unused services. Register the lifecycle only for the applicable task mode and at both pre-fork and worker-start boundaries. Cover non-coroutine MULTI, PIPELINE, SELECT, and WATCH ownership, abandoned transactions, selected-database restoration, divergent manager and pool names, unresolved services, and cleanup failure precedence.
Add a native-faithful SQLiteDatabase classifier for literal memory databases, URI memory forms, and file URIs, then route connection creation, schema loading, integration fixtures, and filesystem management through that single owner. Resolve the canonical attached file before refreshing a live database, preserve its inode, reject URI names at plain-path management boundaries, and surface failed truncation instead of reporting false success. Cover the complete URI matrix, standalone connector behavior, CLI routing, canonical path refresh, invalid filesystem operations, and WAL fixture handling without introducing URI rewriting or another database-name abstraction.
Normalize valid in-memory SQLite pools to one managed wrapper because every wrapper shares the same physical PDO. Reuse the existing pool channel as the only synchronization primitive and preserve PoolOption as the validator for invalid configurations. Canonicalize unsplit base, read, and write aliases around the shared owner in both runtime and testing resolvers. Update concurrency, session-configuration, persistence, query-log, alias-flush, and pool-capacity tests to prove deterministic transfer without adding another lock or coordinator.
Use SQLiteDatabase across RefreshDatabase, application parallel testing, package testing, and Testbench so every supported memory and URI form receives the same lifecycle decision. Cache only physical memory PDOs in mixed transaction sets, keep the live refresh connection override, avoid suffixing memory databases, and fail fast when automatic file management receives a non-memory URI. Preserve assigned ParaTest identity and the existing without-databases escape hatch. Add focused coverage for mixed connections, both parallel systems, Testbench setup and cleanup, plain-path suffixing, URI rejection, and documented test configuration behavior.
Separate callback, committing event, physical commit, logical publication, manager callback, rollback, and disconnect phases so each state changes only after its owning operation succeeds. Rollback before concurrency retries, suppress retries after failed cleanup, preserve the earliest operation failure, detach lost sessions terminally, clear PDO references exhaustively, and invalidate session configuration at every physical rollback boundary. Restore query logging in finally and publish unique-violation metadata from the connection boundary. Detach transaction records before rollback callbacks, exhaust cleanup deepest first, retain commit callback ordering, and cover begin, commit, rollback, savepoint, retry, listener, manager, disconnect, pooled reuse, and failure-precedence edges with deterministic regressions.
Port the supported current Laravel query surface: MySQL straight joins and timeouts, null-safe equality, explicit value ordering, conflict-safe returning inserts, DatePeriod bounds, escaped column operators, PostgreSQL date and full-text behavior, delimited aggregates, and builder-backed update subqueries. Keep unsupported grammars explicit, preserve binding order and modified-record state, and use indexed placeholder substitution so raw SQL rendering is linear. Render live and closed resources through their stable identity string without consuming stream contents. Merge current builder, grammar, relationship, and Telescope coverage for call shapes, SQL dialects, bindings, validation, expressions, unions, conflicts, and resource handling.
Synchronize only the requested class or Attribute cast during ordinary attribute reads instead of walking and serializing every cached cast on the model. Retain full cached-cast merges around legacy and Attribute get and set mutators because those callbacks may inspect sibling state. Preserve mutable and encrypted cast persistence, add ARRAY_AS_PROPS behavior for encrypted array objects, and cover unrelated-cast avoidance alongside sibling-mutator visibility.
Serialize only incomplete first model boot publication with an exact coroutine owner and the existing model-class mutex. Permit post-publication recursion, retry failed pre-publication boot, keep successful publication after later hook failure, and leave the stable construction path at one static owner lookup. Move Scout model-dependent setup after publication and remove NestedSet model construction from boot. Resolve class attributes carried by traits and add RouteKey support without changing explicit overrides. Port model increment and decrement collections, quiet variants, truthful event-veto returns, and saveOrIgnore with conflict-safe state publication. Cover recursive, concurrent, non-coroutine, failed, and post-publication boot together with trait attributes, route keys, model events, casts, IDs, timestamps, and conflict behavior.
Port closure-valued create and update defaults across builders and relations without evaluating them on already-found paths. Propagate removed nested scopes, reject private attributed scopes, touch exact related keys and multiple timestamp columns, and normalize MorphTo dictionary keys. Publish restored events only after a successful save, normalize enum model IDs at the exception string boundary, preserve class-string and callback inference, and guess resources from the complete nested model namespace. Merge the current unit and integration matrix for create-or-first families, relation updates, scope visibility, eager morph matching, soft-delete events, enum IDs, timestamps, and nested resource discovery.
Add model-aware foreign UUIDs, foreign-key inspection, PostgreSQL tsvector columns, and native MariaDB vector indexes while keeping driver support explicit. Correct PostgreSQL pre-9.1 collation inspection and sequence initialization for wrapped custom schemas, expose facade metadata, and retain concise markers for deliberately omitted deprecated forwarding. Port the supported blueprint, builder, MariaDB, PostgreSQL, and SQLite grammar regressions for inferred keys, names and column lists, vector SQL, server versions, and exact sequence expressions.
Attach the offending constraint name and available columns to UniqueConstraintViolationException while preserving the original query, bindings, driver exception, connection details, and read or write classification. Parse native MySQL, MariaDB, PostgreSQL, and SQLite messages at each driver boundary and degrade to null or an empty list when the server omits usable metadata. Also honor the active PostgreSQL read or write PDO configuration when deciding emulated-prepare boolean handling. Cover parsed and unparseable unit messages, live supported-driver violations, multiple columns, named constraints, and read versus write prepare options.
Expose migration filenames on start and end events and allow schema dumps to retain table definitions while omitting migration rows. Keep nullable migration-table state explicit through every schema-state implementation. Let migrate fresh recover through the existing migration path when repository inspection cannot reach a missing database, report the correct prune option, recognize current lost-connection messages, and detect MariaDB client versions with the documented minimum fallback. Refresh callback generic metadata and cover migration names, dump modes, missing databases, command validation, client detection, and schema-state output on supported environments.
Declare every direct Database runtime dependency required by the split package and remove the stale concrete Config dependency after deleting reflective task cleanup. Record Laravel provenance and the deliberate omission of directly deprecated compatibility forwarding. Add source markers at natural upstream sync points and a manifest regression that verifies the complete direct dependency set without relying on the monorepo graph.
Declare direct Swoole, Core lifecycle, and PSR logging dependencies used by Redis source while retaining phpredis as an optional connector capability. Add a split-manifest regression that checks the complete direct runtime dependency set and prevents monorepo-only transitive availability from hiding missing package requirements.
Document MySQL and MariaDB straight joins, null-safe equality, explicit value ordering, per-query timeouts, and conflict-safe returning inserts at their existing task-oriented sections. Use the final public signatures, show realistic application examples, and state driver boundaries without exposing grammar or pooled-connection internals.
Document saveOrIgnore and model-instance incrementEach and decrementEach operations beside the existing persistence and atomic update guidance. Describe event behavior, quiet variants, conflict return values, and supported PostgreSQL and SQLite boundaries without duplicating query-builder material or internal publication mechanics.
Add the RouteKey class attribute beside the existing getRouteKeyName customization and show how it configures implicit model binding with a slug. Keep the explicit method override available and describe the public application-facing behavior without exposing class-attribute caching internals.
Document model-aware foreign UUIDs, foreign-key inspection, PostgreSQL tsvector columns, MariaDB vector indexes, schema dumps without migration rows, and migration event filenames. Place each addition beside the existing schema or event task, preserve distinct PostgreSQL vector guidance, and state supported-driver behavior using the final source signatures.
Finalize the signed implementation plan with every discovered ownership, transaction, Redis, SQLite, Eloquent, parity, metadata, documentation, performance, and anti-overengineering decision reflected in the delivered code. Record database-05 through database-13 and redis-03 through redis-08 in the audit ledger, update cross-package routing and revalidation status, capture the complete validation and review result, and mark the Database package checklist complete.
|
Important Review skippedToo many files! This PR contains 161 files, which is 61 over the limit of 100. To get a review, narrow the scope: Upgrade to a paid plan to raise the limit. This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (163)
You can disable this status message by setting the ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis PR completes a large-scope database and Redis persistence lifecycle audit for Hypervel, bringing connection ownership, transaction correctness, SQLite memory database handling, Eloquent model boot serialization, and query/schema APIs up to date with current Laravel.
Confidence Score: 5/5This PR is safe to merge. The changes are well-scoped to cold lifecycle boundaries and correctness fixes — they do not add work to the normal HTTP request or database query path. Every new mechanism has a clear owner, a verified failure path, and a corresponding test. Transaction state changes are now published only after their physical operations succeed. Redis pool connections left in WATCH or MULTI/PIPELINE mode are discarded rather than returned. Model boot serialization via Mutex prevents the coroutine race that existed before. The lifecycle cleanup is failure-safe and idempotent. No existing public API is removed or renamed. No files require special attention. Important Files Changed
Reviews (2): Last reviewed commit: "test(horizon): bound supervisor process ..." | Re-trigger Greptile |
PostgreSQL may report an active transaction after the backend has already disappeared. During pooled refresh, rolling back that dead generation could throw after replacement PDOs were created, aborting reconnection and discarding the healthy replacements. Treat a lost-classified rollback failure during disconnect as proof that the old physical session is already terminal. Continue transaction-manager cleanup and PDO detachment, surface any manager failure, and retain the existing precedence for non-lost physical failures. Add deterministic coverage for lost rollback cleanup and failure precedence, and align the Database implementation plan and audit ledger with the corrected database-09 invariant.
Supervisor integration cleanup sent SIGTERM, immediately requested a hard stop, and then waited without a timeout. When the child exited from the earlier SIGTERM after Symfony recorded SIGKILL, wait() raised ProcessSignaledException; the unbounded wait could also strand suite shutdown. Use WorkerProcess::kill() as the single synchronous hard-stop and reap boundary. Exhaust cleanup across every active and terminating process, preserve the earliest genuine cleanup failure, and remove the redundant competing signal and wait phases.
|
@greptile-apps I traced all three inline findings against the pre-change Hypervel implementation, current Laravel, and the relevant tests and documentation. Two comments report the same Redis precedence concern.
No source or documentation changes are needed from this review round. |
|
Both points are well-justified — withdrawing the remaining open threads. Redis exception precedence (both threads): Confirmed. The pre-change dispatch-inside-catch ordering means a listener failure could already replace the command exception before this refactor, current Laravel has the same contract, and
No action items remain from this review round. |
Summary
This PR completes the Database persistence lifecycle audit and brings the supported Database surface up to date with current Laravel.
The main goal is simple: a pooled connection must always have one clear owner, and every transaction state change must reflect what actually happened on the underlying connection. The same rules now hold across coroutine requests, non-coroutine Swoole tasks, process forks, test workers, SQLite memory databases, and Redis operations that pin a connection.
For the full design and decision record, see the implementation plan.
Lifecycle ownership
These events are cold lifecycle boundaries. They do not add work to ordinary HTTP requests or Database queries.
Redis connection state
WATCH,MULTI,PIPELINE,EXEC,UNWATCH,RESET, andDISCARDon the correct native connection.DISCARDcommand around the existing pool lifecycle method with the same name.The release check reads local phpredis state only. It does not send another Redis command.
SQLite behavior
The existing pool channel remains the only synchronization primitive. No second lock or SQLite connection coordinator is introduced.
Transaction correctness
finally.This fixes both Hypervel-specific pooled reuse failures and transaction defects shared with upstream behavior.
Eloquent and query updates
#[RouteKey].incrementEach,decrementEach, quiet variants, andsaveOrIgnore.falsewhen model events veto increment or decrement operations.The query builder now includes the supported current Laravel additions:
inOrderOf.Raw SQL placeholder substitution now uses an index rather than repeatedly shifting the bindings array.
Schema, migrations, and exceptions
foreignUuidFor.hasForeignKeyand matching facade metadata.tsvectorcolumns.migrate:fresh.Unsupported drivers and dynamic connection APIs remain intentionally unsupported.
Performance
This work does not add a lock, yield, retry, container lookup, network request, or registry to the normal Database query path.
The recurring correctness costs are small local checks:
The work also removes hot-path work:
Package and documentation updates
No existing supported Laravel API is removed or renamed.
Validation