feat: Added separate Database application.#1153
Open
ShogunPanda wants to merge 3 commits into
Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Introduces a “Database Watt” background application and routes PostgreSQL access through Platformatic Watt messaging when available, while preserving a direct pg fallback for non-Watt/local execution.
Changes:
- Convert
watt.jsonto a Platformatic Runtime config with two applications (storage,database) and add per-app configs. - Add Database Watt implementation (pooling, destination resolution, locks, cancellation, validation, metrics) plus unit/integration/acceptance coverage.
- Route internal storage DB access (
getPostgresConnection,multitenantPgExecutor) through Database Watt when Watt messaging is present, and update Platformatic deps.
Reviewed changes
Copilot reviewed 36 out of 38 changed files in this pull request and generated 8 comments.
Show a summary per file
| File | Description |
|---|---|
| watt.storage.json | Adds Watt app config for the storage service entrypoint. |
| watt.json | Switches to Platformatic Runtime schema and defines storage + database applications. |
| watt.database.json | Adds Watt app config for the database background worker (no server). |
| src/internal/database/watt-connection.ts | Implements a pg-like tenant connection/executor over Watt messaging (query/tx/cancel/error mapping). |
| src/internal/database/watt-connection.test.ts | Adds unit tests for the Watt connection adapter behavior. |
| src/internal/database/pg-connection.ts | Introduces *Like interfaces and aligns existing classes to implement them. |
| src/internal/database/multitenant-pg.ts | Routes master DB executor through Database Watt when messaging exists. |
| src/internal/database/multitenant-pg.test.ts | Extends tests to cover Watt-messaging routing behavior. |
| src/internal/database/migrations/migrate.ts | Documents that migrations still use direct pg. |
| src/internal/database/client.ts | Routes getPostgresConnection() through Database Watt when messaging exists and validates tenant host rules. |
| src/internal/database/client.test.ts | Adds tests for Watt vs direct-pg routing and forwarded-host validation. |
| src/database/validation.ts | Adds wire-protocol validation for Database Watt requests. |
| src/database/types.ts | Adds typed wire request/response contracts for Database Watt messages. |
| src/database/tests/validation.test.ts | Tests protocol validation limits and error cases. |
| src/database/tests/result-limits.test.ts | Tests row/byte result limiting behavior. |
| src/database/tests/locks.test.ts | Tests lock registry semantics and serialization of lock-bound work. |
| src/database/tests/index.test.ts | Tests Database Watt messaging handlers end-to-end with loopback messaging + mocked pg. |
| src/database/tests/errors.test.ts | Tests error serialization/mapping contract. |
| src/database/tests/cancellation.test.ts | Tests cancellation registry behavior, including pg cancel path. |
| src/database/ssl.ts | Adds SSL-mode parsing and ssl settings helper for pg pools. |
| src/database/result-limits.ts | Adds result size/row limit enforcement for handler responses. |
| src/database/pools.ts | Implements destination pool registry with budgeting, timeouts, eviction, and stats. |
| src/database/pg-lib-connection.d.ts | Adds TS typings for pg/lib/connection used in cancellation. |
| src/database/metrics.ts | Adds OpenTelemetry gauges for pool/connection/waiting metrics. |
| src/database/locks.ts | Implements pinned-connection lock registry + tx commit/rollback semantics. |
| src/database/index.ts | Implements Database Watt application and registers messaging handlers. |
| src/database/errors.ts | Adds Database Watt error types and safe response mapping. |
| src/database/destinations.ts | Resolves destinations (single-tenant, tenant via master DB, reserved master). |
| src/database/config.ts | Adds Database Watt config (limits/timeouts/budgets, multitenant master config). |
| src/database/cancellation.ts | Adds query cancellation registry and pg cancel execution helper. |
| src/admin-app.ts | Switches Watt-environment detection to hasField('applicationId'). |
| src/admin-app.test.ts | Refactors tests to set/clear Watt globals for pprof registration checks. |
| package.json | Bumps Platformatic packages and adds @platformatic/runtime + a Watt-specific acceptance runner. |
| docs/database-watt-postgresql-scope.md | Documents which DB access is routed via Database Watt vs intentionally left direct. |
| acceptance/specs/database-watt.test.ts | Adds acceptance coverage for key Database Watt behaviors (query/tx/savepoint/cancel/multitenant). |
| acceptance/scripts/run-managed-watt-local.ts | Adds local managed Watt runner for acceptance (starts Watt + waits for apps). |
| acceptance/scripts/run-managed-local.ts | Explicitly disables Database Watt acceptance path for non-Watt managed runs. |
Comments suppressed due to low confidence (6)
src/internal/database/watt-connection.test.ts:1
viandafterEachare used in this file but not imported fromvitest(e.g.,vi.fn(...)insideinstallWattMessagingMockandafterEach(...)at line 33). Add the missing imports to avoid runtime/TS failures.
src/internal/database/watt-connection.test.ts:1viandafterEachare used in this file but not imported fromvitest(e.g.,vi.fn(...)insideinstallWattMessagingMockandafterEach(...)at line 33). Add the missing imports to avoid runtime/TS failures.
src/database/tests/index.test.ts:1- This test file uses
beforeAll,beforeEach, andafterAllbut does not import them fromvitest. If the repo’s Vitest setup doesn’t enable globals, the suite will fail; align imports with other updated tests by adding these hooks to the import list.
import { setupLoopbackMessaging } from '@platformatic/runtime'
src/database/tests/index.test.ts:1
- This test file uses
beforeAll,beforeEach, andafterAllbut does not import them fromvitest. If the repo’s Vitest setup doesn’t enable globals, the suite will fail; align imports with other updated tests by adding these hooks to the import list.
import { setupLoopbackMessaging } from '@platformatic/runtime'
src/database/tests/index.test.ts:1
- This test file uses
beforeAll,beforeEach, andafterAllbut does not import them fromvitest. If the repo’s Vitest setup doesn’t enable globals, the suite will fail; align imports with other updated tests by adding these hooks to the import list.
import { setupLoopbackMessaging } from '@platformatic/runtime'
src/internal/database/watt-connection.ts:1
- For most timeout codes this returns a
pg.DatabaseErrorwitherror.codeset toundefined, which can break downstream logic that expects a stable code/SQLSTATE. Consider either (a) mapping all of these to a meaningful SQLSTATE (and preserving the original timeout code on a separate property), or (b) returning a non-DatabaseErrorwithcodeset to the timeout code (similar to the generic branch below that preservesdatabaseCode/databaseResponse).
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| @@ -0,0 +1,304 @@ | |||
| import { setupLoopbackMessaging } from '@platformatic/runtime' | |||
| import { afterEach, describe, expect, it, vi } from 'vitest' | |||
| @@ -1,23 +1,78 @@ | |||
| import { vi } from 'vitest' | |||
| describe('admin app pprof registration', () => { | ||
| it('does not register pprof endpoints outside Watt', async () => { | ||
| getGlobal.mockReturnValue(undefined) | ||
| beforeEach(async () => { |
| await clearWattGlobals() | ||
| }) | ||
|
|
||
| afterEach(async () => { |
Comment on lines
+17
to
+21
| if (sslMode === 'require' || sslMode === 'prefer') { | ||
| return { | ||
| rejectUnauthorized: false, | ||
| } | ||
| } |
Comment on lines
+36
to
+42
| return { | ||
| connectionString, | ||
| id: destination, | ||
| isExternalPool: Boolean(process.env.DATABASE_POOL_URL), | ||
| maxConnections: this.config.destinationMaxConnections, | ||
| poolMode: this.config.poolMode, | ||
| } |
Comment on lines
+77
to
+94
| getStats(): PoolRegistryStats { | ||
| let inUseConnections = 0 | ||
| let totalConnections = 0 | ||
| let waitingRequests = 0 | ||
|
|
||
| for (const entry of this.pools.values()) { | ||
| inUseConnections += Math.max(entry.pool.totalCount - entry.pool.idleCount, 0) | ||
| totalConnections += entry.pool.totalCount | ||
| waitingRequests += entry.pool.waitingCount | ||
| } | ||
|
|
||
| return { | ||
| inUseConnections, | ||
| pools: this.pools.size, | ||
| totalConnections, | ||
| waitingRequests, | ||
| } | ||
| } |
Comment on lines
+138
to
+143
| private assertCanAcquire(entry: PoolEntry): void { | ||
| const stats = this.getStats() | ||
|
|
||
| if (this.pendingGlobalAcquisitions >= this.config.globalAcquireQueueLimit) { | ||
| throw new DatabaseWattError('BUSY', 'Global acquisition queue is full') | ||
| } |
495856e to
58b8aaf
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR adds a separate Watt
databaseapplication and routes PostgreSQL operations through Platformatic messaging when Watt messaging is available.Main areas:
Review Order
watt.jsonwatt.database.jsonsrc/database/index.tssrc/database/pools.tssrc/database/locks.tssrc/internal/database/client.tssrc/internal/database/watt-connection.tsacceptance/specs/database-watt.test.tsHigh-Risk Areas
WattPgTenantConnectionandWattPgTransactionare cast toPgTenantConnection/PgTransaction, not actual instances. Review anyinstanceof PgTransactionusage.toPgQueryResult()returns emptycommand,fields, andoid:src/internal/database/watt-connection.ts:372. Any caller relying on those fields may regress.src/database/pools.ts:138.pool.connect():src/database/pools.ts:57. Verify no delayed client leak.beginTransactionvalidation does not appear to validateisolationLevel/readOnly:src/database/validation.ts:5.src/internal/database/watt-connection.ts:339. Confirm this is acceptable.watt.jsonuses schema/runtime3.56.0, whilepackage.jsonstill hasplatformaticandwattpmat^3.52.0:package.json:109.Manual Review Focus
Check these behaviors carefully: