Repository navigation
feat(postgres): support explicitly configured storage schemas - #517
Conversation
Qualify runtime table access, retain schema selection through server metadata and registry restoration, and scope SQLx migrations to a transaction without changing default search-path behavior. Environment: Datadog workspace Co-Authored-By: Codex GPT-6 <noreply@localhost>
Provide a temporary data directory for the standard server test. Environment: Datadog workspace Co-Authored-By: Codex GPT-6 <noreply@localhost>
| sqlx::query(&format!( | ||
| "SET LOCAL search_path TO {identifier}, pg_catalog" | ||
| )) | ||
| .execute(&mut *tx) | ||
| .await | ||
| .map_err(migration_error)?; | ||
| migrator.run(&mut *tx).await.map_err(migration_error)?; |
There was a problem hiding this comment.
Second schema misses tenant policy When
published_artifacts already has a tenant_isolation policy in another schema, this migration sees that policy through a check that does not filter by schema. It then skips creating the policy in the selected schema, even though row-level security is enabled there. Reads and writes through an RLS-enforcing role are denied.
Knowledge Base Used: PostgreSQL platform store
Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/temper-store-postgres/src/migration.rs
Line: 60-66
Comment:
**Second schema misses tenant policy** When `published_artifacts` already has a `tenant_isolation` policy in another schema, this migration sees that policy through a check that does not filter by schema. It then skips creating the policy in the selected schema, even though row-level security is enabled there. Reads and writes through an RLS-enforcing role are denied.
**Knowledge Base Used:** [PostgreSQL platform store](https://app.greptile.com/arni-labs/-/custom-context/knowledge-base/nerdsane/temper/-/docs/postgres-platform-store.md)
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.| if template.contains("{schema}") { | ||
| Cow::Owned(template.replace("{schema}", &self.prefix)) | ||
| } else { | ||
| Cow::Borrowed(template) | ||
| } |
There was a problem hiding this comment.
Default queries allocate SQL strings
qualify_sql calls String::replace for every template containing {schema}, even when PostgresEventStore::new has no schema prefix. Routine queries, including event appends and segment updates, therefore allocate a SQL string that the previous default path did not need. This adds avoidable work to the persistence hot path.
Prompt To Fix With AI
This is a comment left during a code review.
Path: crates/temper-store-postgres/src/namespace.rs
Line: 45-49
Comment:
**Default queries allocate SQL strings** `qualify_sql` calls `String::replace` for every template containing `{schema}`, even when `PostgresEventStore::new` has no schema prefix. Routine queries, including event appends and segment updates, therefore allocate a SQL string that the previous default path did not need. This adds avoidable work to the persistence hot path.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
Summary
Add optional PostgreSQL schema selection to the kernel.
PostgresEventStore::new(pool)keeps the existing search-path behavior.PostgresEventStore::with_schema(pool, PostgresSchema::new(name)?)explicitly qualifies the store's table references, including events, snapshots, policies, specs, WASM, secrets, catalog queries and indexes.The standard server retains the configured store through its metadata helpers. A new
restore_registry_from_postgres_storeentry point preserves the schema when restoring specs; the existing pool-based entry point remains compatible.run_migrations_in_schemaruns the original SQLx migrations and migration history in the chosen schema within one transaction, with a transaction-scoped advisory lock and transaction-local search path. Existing migration files and checksums are unchanged. Runtime queries require no session settings. Schema names are quoted as one identifier and validated against PostgreSQL's identifier length/NUL restrictions.Motivation
The control plane's tables exist in its own schema, but OrgStore uses transaction pooling and does not retain application session settings between requests. Explicit table qualification lets the application choose its storage schema without changing shared database connection defaults.
Verification
search_path.cargo test --locked -p temper-store-postgres: 57 unit tests and the API documentation example passed (live tests run separately).cargo test --locked -p temper-store-postgres --test schema_selection -- --ignored: both real PostgreSQL regressions passed.cargo test --locked -p temper-server --test postgres_schema -- --ignored: standard-server secret, WASM and specification persistence/restoration passed with the runtime schema excluded fromsearch_path.cargo check -p temper-server: passed. GitHub compile/lint and integrity checks passed on the implementation commit; CI reruns for the test-fixture follow-up.Staging deployment has not yet validated this change against OrgStore. No OrgStore connection defaults are changed by this PR.
Control-plane adoption: https://github.com/ddoghq/temper-cloud/pull/9
The PR should not merge until migrating a second schema reliably creates its
published_artifactstenant policy.Fix with agent prompt
Summary
The PR adds an explicitly selected PostgreSQL schema to the event store, qualifies its runtime SQL, preserves the selected store in server metadata paths, and introduces schema-scoped migrations and integration tests.
Diagram
%%{init: {'theme': 'neutral'}}%% flowchart LR Pool[Shared PostgreSQL pool] --> Store[PostgresEventStore] Store -->|explicit schema| SQL[Qualified runtime queries] Store --> Metadata[Server metadata helpers] Schema[PostgresSchema] --> Store Schema --> Migration[Schema-scoped migration transaction] Migration --> Tables[Tables and migration history] SQL --> Tables Metadata --> TablesReviews (1) · Last reviewed commit: "test(postgres): configure artifact stora..."