Skip to content

refactor: PrestConf, Postgres adapter and connection management#972

Merged
arxdsilva merged 14 commits into
mainfrom
prest-conf
Jul 4, 2026
Merged

refactor: PrestConf, Postgres adapter and connection management#972
arxdsilva merged 14 commits into
mainfrom
prest-conf

Conversation

@arxdsilva

@arxdsilva arxdsilva commented Jul 1, 2026

Copy link
Copy Markdown
Member
  • Added a new Postgres adapter with connection pooling and database interaction capabilities.
  • Implemented interfaces for database connection, access, and pinging.
  • Refactored existing mock tests to utilize the new adapter structure.
  • Enhanced error handling and configuration management for database connections.
  • Introduced integration tests for the Postgres adapter to ensure functionality and reliability.
  • Introduced logsafe package to redact sensitive information in error messages.
  • Updated error logging across the Postgres adapter to use logsafe for improved security.
  • Refactored connection management to utilize singleflight for deduplication of database connection requests.
  • Added unit tests for logsafe functionality to ensure proper redaction of sensitive data.
  • Improved connection pool management with RWMutex for better concurrency handling.

Summary by CodeRabbit

  • New Features
    • Improved, config-driven server and adapter startup with clearer errors when a non-Postgres adapter is used.
    • Per-adapter Postgres query/statement caching with correct context-based database selection.
    • Enhanced dynamic plugin loading for both request handlers and Negroni middleware.
    • Context-aware health checks driven by the configured database ping capability.
  • Bug Fixes
    • Reduced reliance on shared global runtime state for more consistent behavior.
    • Sanitized script/template query parameters to prevent unsafe inputs.
    • Redacted database credentials in logged errors and improved health-check error logging.

arxdsilva added 2 commits July 1, 2026 13:35
- Added a new Postgres adapter with connection pooling and database interaction capabilities.
- Implemented interfaces for database connection, access, and pinging.
- Refactored existing mock tests to utilize the new adapter structure.
- Enhanced error handling and configuration management for database connections.
- Introduced integration tests for the Postgres adapter to ensure functionality and reliability.
- Introduced logsafe package to redact sensitive information in error messages.
- Updated error logging across the Postgres adapter to use logsafe for improved security.
- Refactored connection management to utilize singleflight for deduplication of database connection requests.
- Added unit tests for logsafe functionality to ensure proper redaction of sensitive data.
- Improved connection pool management with RWMutex for better concurrency handling.
@arxdsilva arxdsilva self-assigned this Jul 1, 2026
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d2078735-29a9-48b7-9f80-b74c620bcfff

📥 Commits

Reviewing files that changed from the base of the PR and between b946a1f and 602b664.

📒 Files selected for processing (3)
  • cmd/auth.go
  • cmd/prestd/main.go
  • cmd/root.go
💤 Files with no reviewable changes (1)
  • cmd/auth.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • cmd/prestd/main.go
  • cmd/root.go

📝 Walkthrough

Walkthrough

This PR removes global mutable configuration and package-level Postgres/middleware state, replacing them with config-scoped constructors, instance-backed adapters, and a new app composition root. It also updates CLI wiring, controllers, router, plugins, and integration tests to use the new dependency flow.

Changes

Global config removal and dependency-injected wiring

Layer / File(s) Summary
Config and logging
config/config.go, config/config_test.go, internal/logsafe/*, context/keys.go
Config loading now returns a config instance and error, viper parsing is instance-scoped, safe error logging is added, and a new request context key is introduced.
Adapter connectivity and connection manager
adapters/connection.go, adapters/adapter.go, adapters/postgres/adapter.go, adapters/postgres/connection.go, adapters/postgres/internal/connection/*
Database connectivity ports are added, Postgres connection helpers move onto an instance-backed manager, and connection-manager tests and test hooks are updated for pooled singleflight behavior.
Postgres adapter and query execution
adapters/postgres/postgres.go, adapters/postgres/queries.go, adapters/postgres/test_exports.go, adapters/postgres/*_test.go, adapters/mock/*
The Postgres adapter becomes instance-owned, statement caching becomes per database key, query/write helpers move onto adapter receivers, and permission and SQL builder logic read from adapter configuration.
Config-driven middlewares and plugins
middlewares/*.go, plugins/*.go
Middleware constructors now accept explicit settings, global middleware state is removed, and the plugin loader becomes a config-bound Plugins type with handler and middleware entry points.
Router and controller wiring updates
router/router.go, controllers/auth.go, controllers/health_db.go, controllers/healthcheck.go, controllers/deps.go, controllers/script.go (+tests)
Route registration and controller helpers now receive explicit config and adapter inputs, health checks are injected through adapters.DatabasePinger, and script query parameters are sanitized before rendering.
App composition root
app/app.go, app/errors.go, app/app_test.go
The app package now constructs the server graph from config, adapter, plugins, middleware, and router pieces, and adds the adapter mismatch error plus app tests.
CLI command wiring via app package
cmd/*.go
Command startup, migration checks, and auth table helpers now obtain config and DB handles through the app package and explicit context propagation.
Integration test suite updates for config-scoped adapters
integration/**
Integration tests now load per-test config, build handlers and middleware from constructors, and exercise the refactored adapter and plugin APIs instead of global state.
Documentation and build config updates
.github/copilot-instructions.md, Makefile
Repository guidance and the unit test target are updated to reflect the new dependency-injection and timeout conventions.
Estimated code review effort: 5 (Critical) ~120 minutes

Possibly related PRs

  • prest/prest#912: This PR also changes permission handling around adapter-scoped access config and user-specific table permissions.
  • prest/prest#950: It touches the Postgres connection failure path and MustGet logging behavior.
  • prest/prest#967: The repository guidance changes overlap with the Copilot instructions updates in this PR.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning It summarizes changes but doesn't follow the required template or include the issue targeted, branch target, or the mandatory preface/deletion notice. Rewrite the description to match the template: include target branch, contributing-guidelines acknowledgement, issue number, and delete the template text.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed Clear and specific; it summarizes the main refactor across PrestConf, Postgres adapter, and connection management.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch prest-conf

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 19

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
cmd/root.go (1)

53-55: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Redact command errors before sending them to slog.

Subcommands can still return raw DB/bootstrap errors here, so this path can leak credentials into stderr or CI logs unless it goes through logsafe.Error.

💡 Local fix
+	"github.com/prest/prest/v2/internal/logsafe"
+
 	if err := RootCmd.Execute(); err != nil {
-		slog.Error("executing root command", "err", err)
+		slog.Error("executing root command", "err", logsafe.Error(err))
 		os.Exit(1)
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/root.go` around lines 53 - 55, RootCmd.Execute currently logs raw errors
with slog.Error, which can leak sensitive DB/bootstrap details. Update the error
handling in RootCmd.Execute’s failure path to pass the error through
logsafe.Error before logging, and keep the existing command-execution context in
the message while using the redacted value for the error field.
integration/adapters/postgres/postgres_test.go (1)

2456-2481: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Reset AccessConf.Users per case instead of appending to it.

Only Tables is cleared here. Users keeps growing with duplicate foo/bar entries, so later cases can resolve permissions from stale earlier definitions instead of the case under test.

💡 Local fix
-		testCfg.AccessConf.Tables = []config.TablesConf{}
-		testCfg.AccessConf.Tables = append(testCfg.AccessConf.Tables,
-			config.TablesConf{
-				Name:        "test_field_permission",
-				Permissions: []string{"read", "write", "delete"},
-				Fields:      tt.args.fields,
-			})
-
-		testCfg.AccessConf.Users = append(testCfg.AccessConf.Users,
-			config.UsersConf{
+		testCfg.AccessConf.Tables = []config.TablesConf{{
+			Name:        "test_field_permission",
+			Permissions: []string{"read", "write", "delete"},
+			Fields:      tt.args.fields,
+		}}
+
+		testCfg.AccessConf.Users = []config.UsersConf{
+			{
 				Name: "foo",
 				Tables: []config.TablesConf{{
 					Name:        "test_field_permission",
 					Permissions: []string{"read", "write", "delete"},
 					Fields:      tt.args.userFields,
 				}},
 			},
-			config.UsersConf{
+			{
 				Name: "bar",
 				Tables: []config.TablesConf{{
 					Name:        "test_field_permission",
 					Permissions: []string{"read", "write", "delete"},
 					Fields:      tt.args.user2Fields,
 				}},
-			})
+			},
+		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@integration/adapters/postgres/postgres_test.go` around lines 2456 - 2481,
Reset AccessConf.Users for each test case instead of appending to the existing
slice. In the postgres test setup around the field-permission cases, clear
testCfg.AccessConf.Users alongside testCfg.AccessConf.Tables before rebuilding
the per-case config, so the UsersConf entries for foo and bar come only from
tt.args.userFields and tt.args.user2Fields and do not carry over stale
definitions between cases.
adapters/postgres/queries.go (1)

126-145: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

WriteSQLCtx does not execute with the supplied context.

After adapter.dbFromCtx(ctx), this path prepares and executes via non-context calls, so ExecuteScriptsCtx will not respect cancellation or deadlines for write scripts.

Also applies to: 183-188

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@adapters/postgres/queries.go` around lines 126 - 145, WriteSQLCtx is ignoring
the supplied context after dbFromCtx(ctx), so prepare/exec won’t honor
cancellation or deadlines. Update WriteSQLCtx (and the similar ExecuteScriptsCtx
path referenced in the review) to use context-aware database/statement
operations throughout, keeping the context from the call all the way through
prepare and execution. Use the existing postgres methods and
scanner.PrestScanner error handling, but switch the non-context calls in
WriteSQLCtx to their ctx-aware equivalents so cancellation propagates correctly.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@adapters/postgres/internal/connection/conn_test.go`:
- Around line 65-67: The dbConnect test stub in conn_test.go is calling
require.Equal inside a spawned goroutine, which can trigger unsafe FailNow
behavior. Update the dbConnect replacement used by the test so it only captures
the driverName/dataSourceName values or any error inside the goroutine, then
perform the require.Equal assertions back in the parent test goroutine around
the connTest/connection flow.

In `@adapters/postgres/internal/connection/conn.go`:
- Around line 25-30: `Manager` has unsynchronized mutable fields, so concurrent
calls can race when `getPool()` initializes `m.pool` and when `currDatabase` is
read or updated during database switching. Add synchronization in `Manager` (or
guard these fields with the existing pool locking strategy) so `getPool`, the
database selection path, and any methods that read/write `currDatabase` access
shared state safely; use the `Manager` type and `getPool()` as the main fix
points.
- Around line 164-166: The error handling in the database connection path logs a
sanitized error but still panics with the raw err, which can leak sensitive
details. In the connection logic around the existing slog.Error call in conn.go,
update the panic in the same err != nil block to use the redacted/logsafe
version of the error as well, keeping the panic message consistent with the
sanitized logging.

In `@adapters/postgres/postgres.go`:
- Around line 98-105: The lazy initialization in postgres.getStmts() can race
when multiple requests hit the shared adapter instance at first use. Guard the
p.stmts creation with synchronization (for example, reuse an existing mutex on
postgres or add a dedicated init lock) so only one goroutine can initialize the
Stmt struct. Keep the change localized to getStmts() and the postgres / Stmt
fields involved.
- Around line 179-185: The `...Ctx` transaction/write paths still drop the
request context after selecting the DB, so canceled requests can continue via
non-context calls. Update `GetTransactionCtx` and the other affected `...Ctx`
helpers to pass `ctx` through to `BeginTx`, `ExecContext`, `QueryContext`, and
`QueryRowContext` instead of `db.Begin`, `stmt.Exec`, `stmt.Query`, or helper
methods that use non-context variants. Make the same change in the related
write/transaction entrypoints referenced by the review so all context-aware
paths in `postgres` honor cancellation consistently.
- Around line 904-909: The read-path error logging in postgres still emits raw
connection errors, which can leak DSN credentials. Update the error handling in
QueryCtx and the other affected read paths (including the dbFromCtx/conn.Get
call sites in the postgres adapter) to use the same redacted logging approach as
adapters/postgres/queries.go, replacing direct slog.Error(err) logging with
logsafe.Error(err) or equivalent safe redaction. Keep the existing return
behavior unchanged, but ensure the logged error is sanitized wherever these
connection failures can occur.

In `@app/app.go`:
- Around line 26-31: New currently always creates and connects a new Postgres
adapter, which overwrites any adapter already present on cfg.Adapter. Update New
to first check cfg.Adapter and reuse it when non-nil, only calling postgres.New
and postgres.Connect when no adapter has been injected. Keep the cfg.Adapter
assignment in the connect path so the existing adapter reference is preserved
and the new adapter is only created when needed.
- Around line 70-73: The error handling in app initialization is too broad: in
the db, err := postgres.DB(cfg.Adapter) path, only the sentinel type-assertion
failure should become ErrAdapterNotPostgres. Update the error translation in the
DB() setup logic to detect that specific sentinel and return it, while
preserving and returning any other error from the adapter’s DB() implementation
unchanged.

In `@cmd/prestd/main.go`:
- Around line 19-25: The startup flow in main currently calls app.New(cfg)
before Cobra command selection, which eagerly connects to Postgres and breaks
non-serve subcommands. Move app.New creation out of the top-level startup path
and initialize it only in the serve execution path, while keeping DB-dependent
subcommands like migrate and version working off the parsed cfg after Cobra has
selected the command. Use the existing main, cmd.Execute, and app.New symbols to
relocate the initialization lazily.
- Around line 19-22: The startup error logging in main should not write err
directly because it can expose DSNs or credentials. Update the app
initialization failure path around app.New in main to pass the error through the
internal/logsafe redaction helper before calling slog.Error, and keep the
existing exit behavior unchanged.

In `@config/config.go`:
- Around line 134-149: The Load path still only logs when required directories
cannot be created, so startup can continue with an unusable queries/cache setup.
Update the directory preparation logic in Load to fail fast by returning the
MkdirAll error for the queries directory and the cache storage directory,
instead of just calling slog.Error and continuing; if any directory is meant to
be optional, make that behavior explicit in the cfg handling before setupLogger
is called.
- Around line 130-153: The Load flow still relies on the package-level Viper
singleton, so config paths can leak across repeated calls. Update Load to create
a fresh Viper instance with viper.New(), then pass that instance into Parse and
any helper that reads config so each call is isolated. Keep the existing Load,
viperCfg, and Parse flow intact otherwise, but ensure the new instance is used
for all config resolution instead of the shared global state.

In `@controllers/health_db.go`:
- Around line 7-12: The health check setup currently leaves DefaultCheckList
empty, so controllers/deps.go can build a health handler with no DB verification
when NewHandlersFromConfig/NewDepsFromConfig is used outside app.New. Restore
the ping-based DB check by wiring CheckDBHealth(pinger.Ping) into the
dependency/handler construction path, or repopulate DefaultCheckList for
DatabasePinger-backed adapters so every health endpoint includes the DB check.
Use the existing symbols DefaultCheckList, CheckDBHealth, NewHandlersFromConfig,
and NewDepsFromConfig to place the fix.

In `@integration/adapters/postgres/postgres_test.go`:
- Around line 30-44: The shared test config/adapter setup in setupTestDB and
testAdapter is reusing the same mutable *config.Prest and Adapter instance from
helpers.LoadTestConfig(t), which makes the postgres tests order-dependent and
unsafe for parallel execution. Update setupTestDB to clone the loaded config for
each test and construct a fresh adapter instance from that copy instead of
returning testCfg.Adapter directly, so each test gets isolated AccessConf,
cache, and statement-cache state.

In `@integration/helpers/setup.go`:
- Around line 67-98: LoadTestConfig is returning a shared cached *config.Prest
from the package-level loadedCfg, which lets per-test mutations leak across
callers and makes tests order-dependent. Keep the one-time config/database setup
in loadOnce, but have LoadTestConfig create and return a fresh copy of the
initialized config on each call (including the Adapter and Debug settings)
instead of handing out loadedCfg directly. Use the LoadTestConfig function and
the loadedCfg/loadOnce state as the main places to update.

In `@internal/logsafe/logsafe.go`:
- Around line 9-10: The password redaction regex in passwordKV currently stops
matching when the value starts with quotes, so quoted DSN passwords can leak.
Update the pattern and any related masking logic in logsafe.go so values like
password='...' and password="..." are also fully redacted, while preserving the
existing pgURLCreds handling for URL-style credentials. Make sure the change is
applied where the regexes are defined and verified against quoted and unquoted
password forms.

In `@plugins/plugins.go`:
- Around line 67-87: Return an error instead of panicking when plugin symbols
are malformed in plugins.go. In the code path that looks up HTTPVars, URLQuery,
and the handler symbol via p.Lookup and then asserts to func() string / func()
(string, int), switch to the same checked type-assertion pattern used in the
middleware loader so bad plugins flow through the handler error path. Update the
logic around the plugin lookup and the handler selection in the relevant plugin
execution function to validate each symbol before dereferencing or calling it,
and surface a descriptive error when the expected type is not present.
- Around line 43-47: The plugin cache maps in `loadedFunc` and
`loadedMiddlewareFunc` are accessed concurrently by `Handler()` and
`Middleware()` without synchronization, which can trigger concurrent map access
panics. Add a small mutex guard around each cache’s read/write path in the
plugin loading flow, keeping the locking local to the loader logic that consults
and updates these maps.
- Around line 66-87: The request-handling code in the plugin lookup path is
mutating shared plugin globals by assigning mux Vars and URL query data into
HTTPVars and URLQuery, which can be overwritten by concurrent requests. Update
the plugin invocation flow around the Lookup calls in the handler dispatch logic
to avoid writing request-specific data into package-level symbols; instead pass
vars/query into the per-request handler call or protect the entire plugin
invocation with serialization so each request sees isolated data.

---

Outside diff comments:
In `@adapters/postgres/queries.go`:
- Around line 126-145: WriteSQLCtx is ignoring the supplied context after
dbFromCtx(ctx), so prepare/exec won’t honor cancellation or deadlines. Update
WriteSQLCtx (and the similar ExecuteScriptsCtx path referenced in the review) to
use context-aware database/statement operations throughout, keeping the context
from the call all the way through prepare and execution. Use the existing
postgres methods and scanner.PrestScanner error handling, but switch the
non-context calls in WriteSQLCtx to their ctx-aware equivalents so cancellation
propagates correctly.

In `@cmd/root.go`:
- Around line 53-55: RootCmd.Execute currently logs raw errors with slog.Error,
which can leak sensitive DB/bootstrap details. Update the error handling in
RootCmd.Execute’s failure path to pass the error through logsafe.Error before
logging, and keep the existing command-execution context in the message while
using the redacted value for the error field.

In `@integration/adapters/postgres/postgres_test.go`:
- Around line 2456-2481: Reset AccessConf.Users for each test case instead of
appending to the existing slice. In the postgres test setup around the
field-permission cases, clear testCfg.AccessConf.Users alongside
testCfg.AccessConf.Tables before rebuilding the per-case config, so the
UsersConf entries for foo and bar come only from tt.args.userFields and
tt.args.user2Fields and do not carry over stale definitions between cases.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fee4fe9e-331f-4e46-9499-e73ad614bacd

📥 Commits

Reviewing files that changed from the base of the PR and between 9be9009 and 22723ed.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (57)
  • adapters/connection.go
  • adapters/mock/mock.go
  • adapters/mock/mock_test.go
  • adapters/postgres/adapter.go
  • adapters/postgres/connection.go
  • adapters/postgres/internal/connection/conn.go
  • adapters/postgres/internal/connection/conn_test.go
  • adapters/postgres/internal/connection/test_exports.go
  • adapters/postgres/postgres.go
  • adapters/postgres/postgres_exec_test.go
  • adapters/postgres/postgres_test.go
  • adapters/postgres/queries.go
  • adapters/postgres/queries_test.go
  • adapters/postgres/test_exports.go
  • app/app.go
  • app/app_test.go
  • app/errors.go
  • cmd/auth.go
  • cmd/migrate.go
  • cmd/prestd/main.go
  • cmd/root.go
  • config/config.go
  • config/config_test.go
  • controllers/auth.go
  • controllers/auth_test.go
  • controllers/deps.go
  • controllers/health_db.go
  • controllers/healthcheck.go
  • go.mod
  • integration/adapters/connection/conn_test.go
  • integration/adapters/postgres/postgres_test.go
  • integration/adapters/postgres/queries_test.go
  • integration/controllers/auth_test.go
  • integration/controllers/crud_test.go
  • integration/controllers/scripts_test.go
  • integration/helpers/setup.go
  • integration/middlewares/config_test.go
  • integration/plugins/handler_test.go
  • integration/plugins/middleware_test.go
  • integration/router/routes_test.go
  • internal/logsafe/logsafe.go
  • internal/logsafe/logsafe_test.go
  • middlewares/cache.go
  • middlewares/cache_test.go
  • middlewares/config.go
  • middlewares/config_testhooks.go
  • middlewares/crud_stack.go
  • middlewares/crud_stack_test.go
  • middlewares/middlewares.go
  • middlewares/middlewares_test.go
  • middlewares/test_exports.go
  • middlewares/utils.go
  • middlewares/utils_test.go
  • plugins/handler.go
  • plugins/middleware.go
  • plugins/plugins.go
  • router/router.go
💤 Files with no reviewable changes (2)
  • plugins/middleware.go
  • plugins/handler.go

Comment thread adapters/postgres/internal/connection/conn_test.go Outdated
Comment thread adapters/postgres/internal/connection/conn.go
Comment thread adapters/postgres/internal/connection/conn.go Outdated
Comment thread adapters/postgres/postgres.go
Comment thread adapters/postgres/postgres.go Outdated
Comment thread integration/helpers/setup.go
Comment thread internal/logsafe/logsafe.go Outdated
Comment thread plugins/plugins.go Outdated
Comment thread plugins/plugins.go
Comment thread plugins/plugins.go
arxdsilva added 3 commits July 1, 2026 16:34
… handling

- Introduced comprehensive unit tests for plugin HTTP variable and URL query assignment.
- Added tests for invoking plugin handlers with different return types.
- Implemented concurrency tests to ensure thread-safe access to plugin mutexes and loaded function caches.
- Enhanced the plugin loading mechanism with mutexes to prevent race conditions during concurrent access.
- Updated LoadTestConfig to return fresh shallow copies of the configuration to prevent test interference.
- Enhanced the logsafe package to support redaction of passwords in various quoted formats within error messages.
- Added comprehensive unit tests for the logsafe functionality to ensure proper handling of sensitive data.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
config/config.go (1)

163-246: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

configFile remains a mutated package-level global despite the Viper-singleton fix.

viperCfg() still assigns to the package-level configFile var on every call, later read unsynchronized in Parse() (line 262). This is inconsistent with the PR's goal of eliminating global config state and is a latent data race if Load()/viperCfg() is ever called concurrently (e.g. parallel tests). Consider returning the resolved path from viperCfg() (or storing it on the *Prest being built) instead of a package var.

♻️ Possible approach
-func viperCfg() *viper.Viper {
+func viperCfg() (*viper.Viper, string) {
 	v := viper.New()
-	configFile = getPrestConfFile(os.Getenv("PREST_CONF"))
+	configFile := getPrestConfFile(os.Getenv("PREST_CONF"))
 	...
-	return v
+	return v, configFile
 }

Then thread configFile into Parse(v, cfg, configFile) instead of reading the package var.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/config.go` around lines 163 - 246, The config path is still stored in
the package-level configFile global inside viperCfg(), which leaves mutable
shared state and can race with Parse() reading it later. Stop assigning to the
package var in viperCfg(); instead return the resolved config file path from
viperCfg() (or attach it to the Prest/config object being built) and pass that
value into Parse() explicitly so Load(), viperCfg(), and Parse() no longer
depend on unsynchronized global state.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@config/config.go`:
- Around line 163-246: The config path is still stored in the package-level
configFile global inside viperCfg(), which leaves mutable shared state and can
race with Parse() reading it later. Stop assigning to the package var in
viperCfg(); instead return the resolved config file path from viperCfg() (or
attach it to the Prest/config object being built) and pass that value into
Parse() explicitly so Load(), viperCfg(), and Parse() no longer depend on
unsynchronized global state.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 81d586c8-42df-4822-854e-0541912e6ed4

📥 Commits

Reviewing files that changed from the base of the PR and between 22723ed and d3e7d62.

📒 Files selected for processing (18)
  • adapters/postgres/internal/connection/conn.go
  • adapters/postgres/internal/connection/conn_test.go
  • adapters/postgres/internal/connection/test_exports.go
  • adapters/postgres/postgres.go
  • adapters/postgres/queries.go
  • app/app.go
  • cmd/prestd/main.go
  • cmd/root.go
  • config/config.go
  • config/config_test.go
  • controllers/deps.go
  • controllers/health_db.go
  • integration/adapters/postgres/postgres_test.go
  • integration/helpers/setup.go
  • internal/logsafe/logsafe.go
  • internal/logsafe/logsafe_test.go
  • plugins/plugins.go
  • plugins/plugins_test.go
🚧 Files skipped from review as they are similar to previous changes (10)
  • internal/logsafe/logsafe.go
  • adapters/postgres/internal/connection/test_exports.go
  • controllers/health_db.go
  • adapters/postgres/internal/connection/conn_test.go
  • integration/helpers/setup.go
  • adapters/postgres/queries.go
  • adapters/postgres/internal/connection/conn.go
  • internal/logsafe/logsafe_test.go
  • integration/adapters/postgres/postgres_test.go
  • adapters/postgres/postgres.go

…t support

- Introduced PrepareContext method in the Postgres adapter to allow statement preparation with context for cancellation and deadline support.
- Updated existing WriteSQLCtx function to utilize the new PrepareContext method for improved error handling and context management.
- Enhanced the Postgres adapter's concurrency handling by implementing caching for prepared statements.
Comment thread adapters/postgres/postgres.go Dismissed
Comment thread adapters/postgres/postgres.go Dismissed
- Modified the configuration parsing functions to return the configuration path alongside the viper instance.
- Updated all relevant tests to utilize the new configuration path parameter, ensuring consistency in configuration handling.
- Enhanced logging to reflect the correct configuration file being used during parsing.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@adapters/postgres/postgres.go`:
- Around line 158-180: The prepared-statement cache in Stmt.PrepareContext is
keyed only by SQL, so statements can be reused across different selected
databases. Update the cache to be DB-scoped (for example by changing PrepareMap
to use a per-DB key or per-DB nested map) and keep the lookup/insert logic
inside PrepareContext aligned with that key. Also re-check the cache after
preparing under lock, and if another goroutine already stored a statement, close
the duplicate prepared statement before returning the cached one to avoid leaks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: cef55b8c-ab6a-4f85-ac56-69b868568c0f

📥 Commits

Reviewing files that changed from the base of the PR and between d3e7d62 and 8e2e803.

📒 Files selected for processing (4)
  • adapters/postgres/postgres.go
  • adapters/postgres/queries.go
  • cmd/root.go
  • integration/adapters/postgres/postgres_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • adapters/postgres/queries.go
  • cmd/root.go
  • integration/adapters/postgres/postgres_test.go

Comment thread adapters/postgres/postgres.go Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
config/config.go (2)

129-142: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Return non-ENOENT os.Stat errors.

os.Stat failures like EACCES are not IsNotExist, so Load() can continue with an inaccessible queries/cache path.

Proposed fix
-	if _, err := os.Stat(cfg.QueriesPath); os.IsNotExist(err) {
+	if _, err := os.Stat(cfg.QueriesPath); err != nil {
+		if !os.IsNotExist(err) {
+			return nil, fmt.Errorf("stat queries directory %q: %w", cfg.QueriesPath, err)
+		}
 		if err = os.MkdirAll(cfg.QueriesPath, 0700); err != nil {
 			return nil, fmt.Errorf("create queries directory %q: %w", cfg.QueriesPath, err)
 		}
 	}
@@
-	if _, err := os.Stat(cfg.Cache.StoragePath); os.IsNotExist(err) {
+	if _, err := os.Stat(cfg.Cache.StoragePath); err != nil {
+		if !os.IsNotExist(err) {
+			return nil, fmt.Errorf("stat cache directory %q: %w", cfg.Cache.StoragePath, err)
+		}
 		if err = os.MkdirAll(cfg.Cache.StoragePath, 0700); err != nil {
 			return nil, fmt.Errorf("create cache directory %q: %w", cfg.Cache.StoragePath, err)
 		}
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/config.go` around lines 129 - 142, Handle non-ENOENT failures from the
os.Stat checks in Load so inaccessible queries/cache paths do not get ignored.
In the cfg.QueriesPath and cfg.Cache.StoragePath existence checks, only create
the directory when os.IsNotExist(err) is true; if Stat returns any other error,
return it immediately instead of continuing. Keep the existing setupLogger flow
unchanged, and apply the fix in the Load path around the os.Stat/MkdirAll logic.

237-242: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Set a fallback queries.location when home lookup fails.

Without this, cfg.QueriesPath can remain empty and make default startup fail in environments without a resolvable home directory.

Proposed fix
 	hDir, err := homedir.Dir()
 	if err != nil {
 		slog.Error("could not find homedir", "err", err)
+		v.SetDefault("queries.location", "./queries")
 	} else {
 		v.SetDefault("queries.location", filepath.Join(hDir, "queries"))
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/config.go` around lines 237 - 242, The homedir lookup in the config
initialization leaves queries.location unset on failure, which can later make
cfg.QueriesPath empty. Update the logic around homedir.Dir() in the config setup
to always set a fallback default for queries.location when the home directory
cannot be resolved, while still logging the lookup failure with slog.Error. Use
the existing configuration flow that sets v.SetDefault("queries.location", ...)
so startup has a usable path even without a resolvable home directory.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@config/config.go`:
- Line 128: Load() is swallowing config read/parse failures by calling Parse(v,
cfg, configPath) and then continuing, which lets malformed or unreadable config
files fall back to defaults. Update Load() in config/config.go to detect and
return an error for any config read/parse failure, while still allowing only the
missing-config case to proceed with defaults; use the Parse call site and the
Load() flow to locate where to thread the error back to the caller instead of
logging and continuing.

---

Outside diff comments:
In `@config/config.go`:
- Around line 129-142: Handle non-ENOENT failures from the os.Stat checks in
Load so inaccessible queries/cache paths do not get ignored. In the
cfg.QueriesPath and cfg.Cache.StoragePath existence checks, only create the
directory when os.IsNotExist(err) is true; if Stat returns any other error,
return it immediately instead of continuing. Keep the existing setupLogger flow
unchanged, and apply the fix in the Load path around the os.Stat/MkdirAll logic.
- Around line 237-242: The homedir lookup in the config initialization leaves
queries.location unset on failure, which can later make cfg.QueriesPath empty.
Update the logic around homedir.Dir() in the config setup to always set a
fallback default for queries.location when the home directory cannot be
resolved, while still logging the lookup failure with slog.Error. Use the
existing configuration flow that sets v.SetDefault("queries.location", ...) so
startup has a usable path even without a resolvable home directory.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bc2c4847-b4eb-4879-8ade-05d7dafc1019

📥 Commits

Reviewing files that changed from the base of the PR and between 8e2e803 and 3ee2205.

📒 Files selected for processing (2)
  • config/config.go
  • config/config_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • config/config_test.go

Comment thread config/config.go Outdated
arxdsilva added 2 commits July 1, 2026 20:07
…d sanitization

- Updated the Postgres adapter to support caching of prepared statements on a per-database basis, improving performance and resource management.
- Introduced a new method, CacheKeyForDB, to generate stable cache keys for database connections.
- Added unit tests for the new caching behavior and for sanitizing script parameters to prevent SQL injection vulnerabilities.
- Enhanced the extractQueryParameters function to sanitize unsafe query values, ensuring better security in handling user input.
- Improved the Load and Parse functions to handle errors more gracefully, returning specific error messages for configuration issues.
- Added unit tests for handling malformed configuration files and permission errors when accessing directories.
- Refactored tests to utilize a helper function for parsing configurations, ensuring consistency and reducing code duplication.
- Updated documentation for the Load function to clarify its behavior and error handling.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
adapters/postgres/postgres_exec_test.go (1)

267-288: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test verifies per-DB routing but not actual cache reuse.

TestQuery_WithStatementCachePerDatabase confirms Query and QueryCtx hit the correct mock DB, but each mock only expects a single Prepare/Query pair, so it doesn't actually prove the statement is cached and reused across repeated calls to the same database. Consider calling adapter.Query("SELECT 1") twice against defaultMock with only one ExpectPrepare to assert the cache is actually hit on the second call.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@adapters/postgres/postgres_exec_test.go` around lines 267 - 288, The
per-database cache test in TestQuery_WithStatementCachePerDatabase only checks
routing to defaultMock and ctxMock once each, so it does not verify statement
reuse. Update the test to call adapter.Query("SELECT 1") twice for the same
database with only one ExpectPrepare on defaultMock, and similarly ensure
QueryCtx against contextMockDB can reuse the prepared statement on a repeated
call. Keep the existing Query and QueryCtx paths, but make the expectations
prove the cache hit occurs by not allowing a second prepare on the same mock.
config/config_test.go (1)

56-89: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Permission-denial test may be flaky under root or on Windows.

inaccessiblePath relies on os.Chmod(restricted, 0000) to force a permission-denied os.Stat. This breaks down when the test process runs as root (common in Docker-based CI images), since root bypasses Unix permission bits and the Stat would succeed instead of failing with os.ErrPermission; it's also unreliable on Windows, which doesn't enforce POSIX permission bits the same way. Consider skipping these subtests when os.Geteuid() == 0 (Unix) or gating them behind runtime.GOOS != "windows".

🔧 Suggested guard
 func TestLoadStatErrors(t *testing.T) {
+	if runtime.GOOS == "windows" || os.Geteuid() == 0 {
+		t.Skip("permission-denial simulation not reliable as root or on windows")
+	}
 	inaccessiblePath := func(t *testing.T) string {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@config/config_test.go` around lines 56 - 89, The permission-denial assertions
in TestLoadStatErrors are platform-dependent because inaccessiblePath uses
os.Chmod to simulate os.ErrPermission. Update the test setup so the subtests are
skipped or gated when running as root on Unix (using os.Geteuid() == 0) and when
the runtime is Windows, and keep the Load-based error checks only for
environments where permission bits are enforced. Use the existing
TestLoadStatErrors and inaccessiblePath helpers to place the guard cleanly
around both subtests.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@adapters/postgres/postgres_exec_test.go`:
- Around line 267-288: The per-database cache test in
TestQuery_WithStatementCachePerDatabase only checks routing to defaultMock and
ctxMock once each, so it does not verify statement reuse. Update the test to
call adapter.Query("SELECT 1") twice for the same database with only one
ExpectPrepare on defaultMock, and similarly ensure QueryCtx against
contextMockDB can reuse the prepared statement on a repeated call. Keep the
existing Query and QueryCtx paths, but make the expectations prove the cache hit
occurs by not allowing a second prepare on the same mock.

In `@config/config_test.go`:
- Around line 56-89: The permission-denial assertions in TestLoadStatErrors are
platform-dependent because inaccessiblePath uses os.Chmod to simulate
os.ErrPermission. Update the test setup so the subtests are skipped or gated
when running as root on Unix (using os.Geteuid() == 0) and when the runtime is
Windows, and keep the Load-based error checks only for environments where
permission bits are enforced. Use the existing TestLoadStatErrors and
inaccessiblePath helpers to place the guard cleanly around both subtests.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 256e217d-7bda-4684-998b-fb8dda1af160

📥 Commits

Reviewing files that changed from the base of the PR and between 3ee2205 and 7def99a.

📒 Files selected for processing (8)
  • adapters/postgres/internal/connection/conn.go
  • adapters/postgres/postgres.go
  • adapters/postgres/postgres_exec_test.go
  • config/config.go
  • config/config_test.go
  • controllers/script.go
  • controllers/script_test.go
  • integration/adapters/postgres/postgres_test.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • adapters/postgres/internal/connection/conn.go
  • config/config.go
  • adapters/postgres/postgres.go
  • integration/adapters/postgres/postgres_test.go

arxdsilva added 2 commits July 1, 2026 20:54
- Introduced a new test suite for the New function, covering scenarios with both existing and nil adapters.
- Enhanced error handling tests to ensure proper behavior when the database connection cannot be established.
- Updated documentation for the New function to clarify its behavior regarding adapter handling and error conditions.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
adapters/postgres/postgres.go (1)

1167-1219: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Propagate ctx into prepare on the write paths. BatchInsertCopyCtx still uses tx.Prepare(...), and InsertCtx/DeleteCtx/UpdateCtx still flow through fullInsert/Prepare(...) instead of PrepareContext(...), so cancellation can still be dropped before execution.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@adapters/postgres/postgres.go` around lines 1167 - 1219, BatchInsertCopyCtx
and the other write helpers are still preparing statements without honoring
cancellation from the passed context. Update BatchInsertCopyCtx to use the
context-aware prepare path on the tx, and make InsertCtx, DeleteCtx, UpdateCtx,
and the shared fullInsert/Prepare flow use PrepareContext instead of Prepare so
ctx cancellation can propagate before execution. Use the existing symbols
BatchInsertCopyCtx, fullInsert, and the Prepare calls to locate and adjust the
write paths consistently.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@adapters/postgres/postgres.go`:
- Around line 1167-1219: BatchInsertCopyCtx and the other write helpers are
still preparing statements without honoring cancellation from the passed
context. Update BatchInsertCopyCtx to use the context-aware prepare path on the
tx, and make InsertCtx, DeleteCtx, UpdateCtx, and the shared fullInsert/Prepare
flow use PrepareContext instead of Prepare so ctx cancellation can propagate
before execution. Use the existing symbols BatchInsertCopyCtx, fullInsert, and
the Prepare calls to locate and adjust the write paths consistently.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 89b57364-4629-4c7f-bae9-dc1897c88b66

📥 Commits

Reviewing files that changed from the base of the PR and between 3ee2205 and 0bbe7c7.

📒 Files selected for processing (13)
  • adapters/postgres/internal/connection/conn.go
  • adapters/postgres/postgres.go
  • adapters/postgres/postgres_conn_test.go
  • adapters/postgres/postgres_exec_test.go
  • adapters/postgres/postgres_test.go
  • adapters/postgres/queries_test.go
  • app/app.go
  • app/app_test.go
  • config/config.go
  • config/config_test.go
  • controllers/script.go
  • controllers/script_test.go
  • integration/adapters/postgres/postgres_test.go
🚧 Files skipped from review as they are similar to previous changes (9)
  • controllers/script_test.go
  • app/app.go
  • controllers/script.go
  • adapters/postgres/internal/connection/conn.go
  • adapters/postgres/postgres_exec_test.go
  • config/config_test.go
  • config/config.go
  • adapters/postgres/postgres_test.go
  • integration/adapters/postgres/postgres_test.go

@arxdsilva arxdsilva changed the title feat: introduce Postgres adapter and connection management refactor Postgres adapter and connection management Jul 2, 2026
@arxdsilva arxdsilva changed the title refactor Postgres adapter and connection management refactor: PrestConf, Postgres adapter and connection management Jul 2, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@adapters/postgres/testmain_test.go`:
- Around line 10-22: The TestMain timeout in testmain_test.go is duplicating the
same 30s limit already enforced by go test -timeout, causing a race between the
two shutdown paths. Update TestMain’s testSuiteTimeout to leave clear headroom
below the CLI timeout, or remove the custom timeout entirely, so the native go
test timeout remains the primary failure mechanism. Keep the change localized to
TestMain and the testSuiteTimeout constant.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 197646e8-46f4-41a4-8513-ea0fc3783a6d

📥 Commits

Reviewing files that changed from the base of the PR and between 0bbe7c7 and 7cbb00b.

📒 Files selected for processing (11)
  • .github/copilot-instructions.md
  • Makefile
  • adapters/adapter.go
  • adapters/connection.go
  • adapters/postgres/internal/connection/test_exports.go
  • adapters/postgres/postgres.go
  • adapters/postgres/postgres_conn_test.go
  • adapters/postgres/postgres_exec_test.go
  • adapters/postgres/postgres_test.go
  • adapters/postgres/testmain_test.go
  • adapters/query_executor.go
✅ Files skipped from review due to trivial changes (4)
  • adapters/connection.go
  • adapters/adapter.go
  • adapters/query_executor.go
  • .github/copilot-instructions.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • adapters/postgres/postgres_conn_test.go
  • adapters/postgres/postgres_exec_test.go
  • adapters/postgres/internal/connection/test_exports.go
  • adapters/postgres/postgres_test.go
  • adapters/postgres/postgres.go

Comment thread adapters/postgres/testmain_test.go Outdated
- Updated the Makefile to allow parallel test execution based on GOMAXPROCS, improving test performance.
- Enhanced the Postgres adapter by introducing context support in various methods, allowing for better cancellation and deadline management.
- Added a new test suite for connection handling, ensuring proper error reporting for connection failures.
- Improved documentation for adapter interfaces to clarify the separation of connection lifecycle methods from the main Adapter interface.
- Updated command files to utilize a centralized configuration retrieval method, enhancing consistency and reducing code duplication.
- Ensured that all commands now derive configuration from the command context, promoting a stateless design.
- Added a new context key for storing the Prest configuration, facilitating better context management across commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
cmd/root.go (1)

63-63: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Hardcoded context.Background() loses room for cancellation/graceful shutdown.

Execute builds a fresh context.Background() rather than accepting a ctx parameter, which prevents callers (e.g., main.go) from propagating a cancellable context for graceful server shutdown down the line. Not a functional bug today, but worth considering if graceful shutdown is ever added.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/root.go` at line 63, Update Execute in RootCmd so it accepts a
caller-provided ctx instead of always creating a fresh context.Background(),
then pass that ctx into withConfig before SetContext. This lets main.go or other
callers propagate cancellation for future graceful shutdown support while
keeping the RootCmd setup flow unchanged.
cmd/auth.go (1)

18-27: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Redundant EnsureAdapter call before PostgresDB.

app.PostgresDB(cfg) already calls EnsureAdapter(cfg) internally before opening the connection, so the explicit call on Line 19 is redundant. It's harmless since EnsureAdapter is idempotent (returns early if cfg.Adapter != nil), but it duplicates the same guard logic unnecessarily.

♻️ Proposed simplification
 		cfg := configFrom(cmd)
-		if err := app.EnsureAdapter(cfg); err != nil {
-			return err
-		}
 		db, err := app.PostgresDB(cfg)
 		if err != nil {
 			fmt.Fprint(os.Stdout, err.Error())
 			return err
 		}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/auth.go` around lines 18 - 27, The auth command is calling
app.EnsureAdapter(cfg) twice because app.PostgresDB(cfg) already performs that
check internally. Remove the explicit EnsureAdapter call in cmd/auth.go and keep
the adapter setup handled by PostgresDB, using configFrom(cmd), app.PostgresDB,
and the subsequent db.Exec flow as the single path.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@cmd/auth.go`:
- Around line 18-27: The auth command is calling app.EnsureAdapter(cfg) twice
because app.PostgresDB(cfg) already performs that check internally. Remove the
explicit EnsureAdapter call in cmd/auth.go and keep the adapter setup handled by
PostgresDB, using configFrom(cmd), app.PostgresDB, and the subsequent db.Exec
flow as the single path.

In `@cmd/root.go`:
- Line 63: Update Execute in RootCmd so it accepts a caller-provided ctx instead
of always creating a fresh context.Background(), then pass that ctx into
withConfig before SetContext. This lets main.go or other callers propagate
cancellation for future graceful shutdown support while keeping the RootCmd
setup flow unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: fd1543c4-9827-4b60-894f-9c4d7fc3dbbe

📥 Commits

Reviewing files that changed from the base of the PR and between e1da81e and b946a1f.

📒 Files selected for processing (5)
  • .github/copilot-instructions.md
  • cmd/auth.go
  • cmd/migrate.go
  • cmd/root.go
  • context/keys.go
✅ Files skipped from review due to trivial changes (1)
  • .github/copilot-instructions.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • cmd/migrate.go

- Removed redundant adapter checks in auth command execution, simplifying the code.
- Updated the Execute function to accept a context parameter, enhancing flexibility in command execution.
- Adjusted main function to pass a context to the Execute method, promoting better context management across commands.
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

Merging this branch will increase overall coverage

Impacted Packages Coverage Δ 🤖
adapters 0.00% (ø)
adapters/mock 76.10% (ø)
adapters/postgres 80.62% (+30.45%) 🌟
adapters/postgres/internal/connection 51.49% (+51.49%) 🌟
app 82.76% (+82.76%) 🌟
cmd 0.00% (ø)
cmd/prestd 0.00% (ø)
config 88.67% (+1.07%) 👍
context 0.00% (ø)
controllers 72.08% (+0.78%) 👍
integration/adapters/connection 0.00% (ø)
integration/adapters/postgres 0.00% (ø)
integration/controllers 0.00% (ø)
integration/helpers 0.00% (ø)
integration/middlewares 0.00% (ø)
integration/plugins 0.00% (ø)
integration/router 0.00% (ø)
internal/logsafe 100.00% (+100.00%) 🌟
middlewares 90.42% (+0.17%) 👍
plugins 22.64% (+22.64%) 🌟
router 0.00% (ø)

Coverage by file

Changed files (no unit tests)

Changed File Coverage Δ Total Covered Missed 🤖
adapters/adapter.go 0.00% (ø) 0 0 0
adapters/connection.go 0.00% (ø) 0 0 0
adapters/mock/mock.go 77.27% (ø) 154 119 35
adapters/postgres/adapter.go 0.00% (ø) 12 (+12) 0 12 (+12)
adapters/postgres/connection.go 0.00% (ø) 7 0 7
adapters/postgres/internal/connection/conn.go 55.81% (+55.81%) 86 (+36) 48 (+48) 38 (-12) 🌟
adapters/postgres/internal/connection/test_exports.go 26.67% (+26.67%) 15 (+6) 4 (+4) 11 (+2) 🌟
adapters/postgres/postgres.go 84.08% (+35.17%) 1156 (+56) 972 (+434) 184 (-378) 🌟
adapters/postgres/queries.go 77.55% (+8.16%) 98 76 (+8) 22 (-8) 👍
adapters/postgres/test_exports.go 0.00% (ø) 27 (+24) 0 27 (+24)
adapters/query_executor.go 0.00% (ø) 0 0 0
app/app.go 82.76% (+82.76%) 29 (+29) 24 (+24) 5 (+5) 🌟
app/errors.go 0.00% (ø) 0 0 0
cmd/auth.go 0.00% (ø) 20 (-2) 0 20 (-2)
cmd/migrate.go 0.00% (ø) 29 (+1) 0 29 (+1)
cmd/prestd/main.go 0.00% (ø) 5 (+3) 0 5 (+3)
cmd/root.go 0.00% (ø) 45 (+9) 0 45 (+9)
config/config.go 88.67% (+1.07%) 256 (+6) 227 (+8) 29 (-2) 👍
context/keys.go 0.00% (ø) 0 0 0
controllers/auth.go 80.81% (ø) 99 80 19
controllers/deps.go 88.89% (-11.11%) 9 (+3) 8 (+2) 1 (+1) 💀
controllers/health_db.go 0.00% (ø) 1 (-4) 0 1 (-4)
controllers/healthcheck.go 100.00% (ø) 11 11 0
controllers/script.go 92.16% (+1.05%) 51 (+6) 47 (+6) 4 👍
integration/helpers/setup.go 0.00% (ø) 0 0 0
internal/logsafe/logsafe.go 100.00% (+100.00%) 7 (+7) 7 (+7) 0 🌟
middlewares/cache.go 100.00% (ø) 10 10 0
middlewares/config.go 81.82% (-5.68%) 11 (-5) 9 (-5) 2 👎
middlewares/config_testhooks.go 0.00% (ø) 0 (-1) 0 0 (-1)
middlewares/crud_stack.go 100.00% (ø) 4 4 0
middlewares/middlewares.go 87.42% (-0.08%) 151 (-1) 132 (-1) 19 👎
middlewares/test_exports.go 100.00% (ø) 8 (+1) 8 (+1) 0
middlewares/utils.go 96.43% (ø) 56 54 2
plugins/handler.go 0.00% (ø) 0 (-45) 0 0 (-45)
plugins/middleware.go 0.00% (ø) 0 (-29) 0 0 (-29)
plugins/plugins.go 22.64% (+22.64%) 106 (+106) 24 (+24) 82 (+82) 🌟
router/router.go 0.00% (ø) 17 (-8) 0 17 (-8)

Please note that the "Total", "Covered", and "Missed" counts above refer to code statements instead of lines of code. The value in brackets refers to the test coverage of that file in the old version of the code.

Changed unit test files

  • adapters/mock/mock_test.go
  • adapters/postgres/internal/connection/conn_test.go
  • adapters/postgres/postgres_conn_test.go
  • adapters/postgres/postgres_exec_test.go
  • adapters/postgres/postgres_test.go
  • adapters/postgres/queries_test.go
  • app/app_test.go
  • config/config_test.go
  • controllers/auth_test.go
  • controllers/script_test.go
  • integration/adapters/connection/conn_test.go
  • integration/adapters/postgres/postgres_test.go
  • integration/adapters/postgres/queries_test.go
  • integration/controllers/auth_test.go
  • integration/controllers/crud_test.go
  • integration/controllers/scripts_test.go
  • integration/middlewares/config_test.go
  • integration/plugins/handler_test.go
  • integration/plugins/middleware_test.go
  • integration/router/routes_test.go
  • internal/logsafe/logsafe_test.go
  • middlewares/cache_test.go
  • middlewares/crud_stack_test.go
  • middlewares/middlewares_test.go
  • middlewares/utils_test.go
  • plugins/plugins_test.go

@arxdsilva
arxdsilva merged commit c54b7dd into main Jul 4, 2026
15 checks passed
@arxdsilva
arxdsilva deleted the prest-conf branch July 4, 2026 03:07
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.

2 participants