Skip to content

feat(orchestrator): add database integration support#43

Open
erenaslandev wants to merge 11 commits into
mainfrom
DT-866
Open

feat(orchestrator): add database integration support#43
erenaslandev wants to merge 11 commits into
mainfrom
DT-866

Conversation

@erenaslandev

@erenaslandev erenaslandev commented Jul 6, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • New Features
    • Added optional per-test database backend with engine defaults, seed_sql initialization, and one-shot database-init compose support (mssql/mysql/postgres/oracle).
    • Added optional database TLS with auto-generated certificates and compose wiring.
  • Bug Fixes
    • Improved interruption handling: canceled runs stop scheduling sooner, wait loops exit early, and partial results are no longer persisted.
    • Updated clean to remove all bench-* containers and related bench networks.
  • Tests
    • Expanded database engine/defaulting/TLS validation and init-command tests.
    • Added cancellation-aware sleep tests and collector memory-usage unit tests.

@coderabbitai

coderabbitai Bot commented Jul 6, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

This PR adds configurable database backends with engine-specific initialization and TLS, cancellation-aware CLI and runner execution, broader cleanup, and cgroup-aware container memory accounting.

Changes

Database backend support

Layer / File(s) Summary
Database config schema and validation
internal/config/case.go, internal/config/database_config_test.go
Adds database configuration, defaults, usage helpers, validation, and tests.
Database engine registry and TLS config
internal/config/database_engines.go
Adds mssql, mysql, postgres, and oracle engine commands and TLS hooks.
Database seed and TLS preparation
internal/orchestrator/database.go, internal/orchestrator/tls.go
Creates seed files and per-run database certificates and TLS configuration.
Compose wiring for database services
internal/orchestrator/docker.go
Renders database and database-init services, dependencies, seed mounts, and TLS mounts.

Cancellation-aware execution flow

Layer / File(s) Summary
CLI cancellation and cleanup
cmd/harness/main.go
Adds signal cancellation, interrupted-run handling, and broad container/network cleanup.
Runner context and cancellation helpers
internal/runner/runner.go
Propagates contexts through polling and Compose flows, interrupts waits, and avoids saving canceled results.
sleepCtx tests
internal/runner/sleep_test.go
Tests cancellation-aware sleeping behavior.

Container memory metrics

Layer / File(s) Summary
Cgroup-aware memory accounting
containers/collector/main.go, containers/collector/main_test.go
Adds cgroup v1/v2 memory usage calculation and table-driven tests.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TestCase
  participant NewComposeRunner
  participant database
  participant database-init
  participant subject

  TestCase->>NewComposeRunner: configure database case
  NewComposeRunner->>database: render engine and TLS settings
  database->>database-init: report healthy
  database-init->>database: execute seed SQL
  subject->>database-init: wait for successful completion
Loading
sequenceDiagram
  participant CLI
  participant Runner
  participant ComposeRunner
  participant PollingLoop

  CLI->>Runner: propagate signal cancellation
  Runner->>ComposeRunner: cancel run context
  ComposeRunner->>PollingLoop: stop waits and polling
  Runner->>Runner: skip persistence for canceled run
Loading

Possibly related PRs

Suggested reviewers: yusufozturk

Poem

I hopped through seeds and TLS bright,
Then chased SIGINT into the night.
Canceled runs leave no trace,
Memory counters find their place.
Hop, hop—the harness runs right! 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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.
Title check ✅ Passed The title accurately summarizes the main change: adding database integration support, especially in orchestrator flow.
✨ 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 DT-866

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
internal/config/case.go (1)

2249-2280: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Consider validating SA password strength for mssql at config-load time.

validateDatabase() checks engine, seed_sql, and database-name charset, but never validates Password when a case overrides the default. MSSQL enforces SA password complexity (8+ chars, upper/lower/digit/symbol per the DefaultPassword comment in database_engines.go); a case author overriding with a weak password will fail silently at container startup, surfacing only as an opaque healthcheck timeout after ~4 minutes of retries — hard to diagnose without digging into docker logs.

Since only mssql exists today, a simple length/charset check here (or as a ValidatePassword hook on DatabaseEngine) would fail fast with a clear error instead.

♻️ Sketch of a minimal check
 	if tc.Database.SeedSQL == "" {
 		return fmt.Errorf("case %q: database block requires `seed_sql`", tc.Name)
 	}
+	if tc.Database.Password != "" && len(tc.Database.Password) < 8 {
+		return fmt.Errorf("case %q: database.password must be at least 8 characters (mssql SA complexity policy)", tc.Name)
+	}
 	if !databaseNameRe.MatchString(tc.Database.DatabaseOrDefault()) {
🤖 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 `@internal/config/case.go` around lines 2249 - 2280, Add fast-fail validation
for overridden database passwords in validateDatabase so weak MSSQL SA passwords
are rejected at config load instead of surfacing later at container startup.
Update the TestCase.validateDatabase path to inspect tc.Database.Password when
present, and use a database-engine-specific check for mssql (ideally via a
ValidatePassword hook on DatabaseEngines or a small helper near databaseNameRe)
that enforces the existing password policy. Make sure the error mentions the
case name and the database engine so authors can locate the bad override
quickly.
internal/orchestrator/docker.go (1)

2304-2327: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a database compose-rendering test
writeCompose already has render coverage for vault, Kafka, AWS, Azure, agent, and verifier paths, but the new database: block still has no compose assertion. Add a database:-enabled case that checks the database/database-init services, the subject depends_on edge, and the seed mount path.

🤖 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 `@internal/orchestrator/docker.go` around lines 2304 - 2327, The new database
rendering branch in writeCompose lacks test coverage. Add a database-enabled
compose-rendering test that exercises tc.UsesDatabase() and verifies the
rendered database and database-init services, the subject service’s depends_on
relationship to seeding completion, and the seed volume/mount path derived from
cfg.DatabaseSeedHost. Use the existing compose assertion patterns in
writeCompose tests to locate and extend the coverage.
🤖 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 `@internal/config/case.go`:
- Around line 2249-2280: Add fast-fail validation for overridden database
passwords in validateDatabase so weak MSSQL SA passwords are rejected at config
load instead of surfacing later at container startup. Update the
TestCase.validateDatabase path to inspect tc.Database.Password when present, and
use a database-engine-specific check for mssql (ideally via a ValidatePassword
hook on DatabaseEngines or a small helper near databaseNameRe) that enforces the
existing password policy. Make sure the error mentions the case name and the
database engine so authors can locate the bad override quickly.

In `@internal/orchestrator/docker.go`:
- Around line 2304-2327: The new database rendering branch in writeCompose lacks
test coverage. Add a database-enabled compose-rendering test that exercises
tc.UsesDatabase() and verifies the rendered database and database-init services,
the subject service’s depends_on relationship to seeding completion, and the
seed volume/mount path derived from cfg.DatabaseSeedHost. Use the existing
compose assertion patterns in writeCompose tests to locate and extend the
coverage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 9ef19b4f-019e-41ea-950e-d55a3ed4e986

📥 Commits

Reviewing files that changed from the base of the PR and between d5faedc and 3691c94.

📒 Files selected for processing (5)
  • internal/config/case.go
  • internal/config/database_config_test.go
  • internal/config/database_engines.go
  • internal/orchestrator/database.go
  • internal/orchestrator/docker.go

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 6, 2026

Copy link
Copy Markdown

Deploying pipebench with  Cloudflare Pages  Cloudflare Pages

Latest commit: 9ca33fb
Status: ✅  Deploy successful!
Preview URL: https://ef1442f3.pipebench.pages.dev
Branch Preview URL: https://dt-866.pipebench.pages.dev

View logs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
internal/orchestrator/tls.go (1)

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

writeRSAKey swallows the Close error.

Unlike writePEMCert (Lines 447-458), which propagates a deferred Close error, this helper uses defer f.Close() and discards it — a flush failure on the private-key write would go unnoticed. Optional, for consistency.

♻️ Align Close-error handling with writePEMCert
-func writeRSAKey(path string, key *rsa.PrivateKey, perm os.FileMode) error {
+func writeRSAKey(path string, key *rsa.PrivateKey, perm os.FileMode) (err error) {
 	f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, perm)
 	if err != nil {
 		return err
 	}
-	defer f.Close()
+	defer func() {
+		if closeErr := f.Close(); err == nil && closeErr != nil {
+			err = closeErr
+		}
+	}()
 	return pem.Encode(f, &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(key)})
 }
🤖 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 `@internal/orchestrator/tls.go` around lines 215 - 222, The writeRSAKey helper
is dropping any error returned by closing the file handle, unlike writePEMCert
which propagates deferred Close failures. Update writeRSAKey to use the same
Close-error handling pattern as writePEMCert so that any flush or close failure
after pem.Encode is returned, and keep the change localized to writeRSAKey in
tls.go.
🤖 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 `@internal/orchestrator/tls.go`:
- Line 206: The server.key file is being written with permissions that are too
permissive in the TLS setup path. Update the key-writing call in the tls
generation flow around writeRSAKey in internal/orchestrator/tls.go so the
private key is created with non-world-readable permissions such as 0400 or 0600,
while keeping ownership/access compatible with the mssql process.

---

Nitpick comments:
In `@internal/orchestrator/tls.go`:
- Around line 215-222: The writeRSAKey helper is dropping any error returned by
closing the file handle, unlike writePEMCert which propagates deferred Close
failures. Update writeRSAKey to use the same Close-error handling pattern as
writePEMCert so that any flush or close failure after pem.Encode is returned,
and keep the change localized to writeRSAKey in tls.go.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e2917d0c-84cf-481f-8080-d652b79b984b

📥 Commits

Reviewing files that changed from the base of the PR and between 3691c94 and 54dbccd.

📒 Files selected for processing (5)
  • internal/config/case.go
  • internal/config/database_engines.go
  • internal/orchestrator/database.go
  • internal/orchestrator/docker.go
  • internal/orchestrator/tls.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • internal/config/case.go

Comment thread internal/orchestrator/tls.go
@erenaslandev erenaslandev added wip and removed wip labels Jul 7, 2026
* feat(orchestrator): implement postgres database engine support

* fix(config): force TCP in pg_isready to avoid startup race
@erenaslandev erenaslandev removed the wip label Jul 8, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 `@internal/config/database_engines.go`:
- Around line 209-246: Update validateDatabase() so the oracle engine explicitly
rejects database.tls being enabled, since the oracle config in
database_engines.go has no TLS support wiring (no TLSServerCertPath,
TLSServerKeyPath, or BuildTLSConf). Add the check alongside the existing oracle
validation path and return a validation error when database.tls is true, using
the engine name “oracle” and validateDatabase() as the key symbols to locate the
change.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3df20c6a-e02d-4e31-96b4-1232ce38ba06

📥 Commits

Reviewing files that changed from the base of the PR and between a1001c3 and d9dcc26.

📒 Files selected for processing (2)
  • internal/config/database_config_test.go
  • internal/config/database_engines.go

Comment thread internal/config/database_engines.go
@erenaslandev

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (1)
cmd/harness/main.go (1)

601-631: 📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Satisfy the noctx linter on the new exec.Command calls.

golangci-lint (noctx) flags Lines 605 and 608 (os/exec.Command must not be called. use os/exec.CommandContext), which will fail the pipeline. The new network-cleanup calls at Lines 627/629 share the same pattern. cleanCmd's RunE has cmd in scope, so cmd.Context() is available and ties cleanup to the root cancellable context introduced by this PR.

🔧 Proposed fix
-			if out, err := exec.Command("docker", "ps", "-aq", "--filter", "name=^bench-").Output(); err == nil {
+			if out, err := exec.CommandContext(cmd.Context(), "docker", "ps", "-aq", "--filter", "name=^bench-").Output(); err == nil {
 				if ids := strings.Fields(string(out)); len(ids) > 0 {
 					rmArgs := append([]string{"rm", "-f"}, ids...)
-					_ = exec.Command("docker", rmArgs...).Run()
+					_ = exec.CommandContext(cmd.Context(), "docker", rmArgs...).Run()
 				}
 			}

Apply the same CommandContext change to the network ls/rm calls at Lines 627 and 629.

🤖 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/harness/main.go` around lines 601 - 631, The new cleanup path in main’s
bench teardown uses exec.Command directly, which triggers the noctx linter and
ignores the root cancellation context. Update the docker ps/network ls and rm
calls in the cleanup block to use the existing command context available from
cleanCmd.RunE via cmd.Context(), matching the rest of the cleanup logic in
cmd/harness/main.go. Keep the same behavior, just thread the context through all
newly added exec invocations so the network cleanup is cancellable and
lint-clean.

Source: Linters/SAST tools

🤖 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 `@internal/orchestrator/docker.go`:
- Around line 1484-1488: `WaitForVerifierExit` is wrapping interrupt
cancellation as a verifier error instead of passing it through. In the verifier
wait path in `docker.go`, special-case `errors.Is(err, context.Canceled)` just
like the generator handling in `runner.go`, and return the cancellation directly
without adding the “verifier logs” wrapper; keep the existing wrapped error path
for all other failures.

---

Outside diff comments:
In `@cmd/harness/main.go`:
- Around line 601-631: The new cleanup path in main’s bench teardown uses
exec.Command directly, which triggers the noctx linter and ignores the root
cancellation context. Update the docker ps/network ls and rm calls in the
cleanup block to use the existing command context available from cleanCmd.RunE
via cmd.Context(), matching the rest of the cleanup logic in
cmd/harness/main.go. Keep the same behavior, just thread the context through all
newly added exec invocations so the network cleanup is cancellable and
lint-clean.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e104f44e-a616-4bf3-aa71-0d237917dc3d

📥 Commits

Reviewing files that changed from the base of the PR and between e72ccb6 and f606071.

📒 Files selected for processing (4)
  • cmd/harness/main.go
  • internal/orchestrator/docker.go
  • internal/runner/runner.go
  • internal/runner/sleep_test.go

Comment on lines +1484 to +1488
select {
case <-r.runCtx.Done():
return fmt.Errorf("interrupted while waiting for verifier: %w", r.runCtx.Err())
case <-time.After(2 * time.Second):
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect the verifier wait caller for context.Canceled handling
rg -nP -C6 'WaitForVerifierExit' internal/runner/runner.go

Repository: VirtualMetric/PipeBench

Length of output: 657


🏁 Script executed:

#!/bin/bash
sed -n '1468,1496p' internal/orchestrator/docker.go
printf '\n---\n'
sed -n '7040,7065p' internal/runner/runner.go
printf '\n---\n'
rg -n 'context\.Canceled|errors\.Is\(err, context\.Canceled\)|WaitForGeneratorExit|WaitForVerifierExit' internal/runner/runner.go internal/orchestrator/docker.go

Repository: VirtualMetric/PipeBench

Length of output: 4044


🏁 Script executed:

#!/bin/bash
sed -n '1,170p' internal/runner/runner.go
printf '\n---\n'
sed -n '392,445p' internal/runner/runner.go
printf '\n---\n'
sed -n '1738,1768p' internal/runner/runner.go
printf '\n---\n'
sed -n '6538,6568p' internal/runner/runner.go
printf '\n---\n'
sed -n '6836,6865p' internal/runner/runner.go

Repository: VirtualMetric/PipeBench

Length of output: 11484


🏁 Script executed:

#!/bin/bash
rg -n -C4 'errors\.Is\(.*context\.Canceled|context\.Canceled' internal/runner internal

Repository: VirtualMetric/PipeBench

Length of output: 9172


Handle verifier cancellation like the generator path internal/runner/runner.go:7057-7058

WaitForVerifierExit can return a wrapped context.Canceled, but this call always wraps the error with verifier logs, so a user interrupt shows up as a verifier failure with extra noise. Special-case errors.Is(err, context.Canceled) here and return it directly.

🤖 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 `@internal/orchestrator/docker.go` around lines 1484 - 1488,
`WaitForVerifierExit` is wrapping interrupt cancellation as a verifier error
instead of passing it through. In the verifier wait path in `docker.go`,
special-case `errors.Is(err, context.Canceled)` just like the generator handling
in `runner.go`, and return the cancellation directly without adding the
“verifier logs” wrapper; keep the existing wrapped error path for all other
failures.

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.

1 participant