Chapter 11: postjevsql-sidecar/src, config, secrets and a plan
Everything the sidecar decides, with nothing that talks to a database. Three
files, each one a rule you can test with plain cargo test.
One config file. config.rs reads the TOML every launcher writes:
[target]
server = "target" # the foreign server's local name (the default)
host = "db.example.com"
port = 5432 # the default
dbname = "app"
sslmode = "verify-full" # the default
use_remote_estimate = true # the default
schemas = ["public"] # imported into same-named local schemas
[[mapping]]
local_user = "app"
remote_user = "app_ro"
password_file = "/run/secrets/app_ro" # or $POSTJEVSQL_TARGET_PASSWORD
[jev]
api_key_file = "/run/secrets/typesafe" # or $TYPESAFE_API_KEY
It also takes sslrootcert, fetch_size (default 100, the scan's in-flight
window, so each window is one round trip), and a mapping's password_env.
An unknown key is an error, not a typo quietly ignored.
Every secret from exactly one place. secret.rs resolves each secret
from a file or an env var. Both set is an error, because a precedence rule
would silently use the wrong credential, and so is neither, for a secret the
command needs. (A mapping with no password at all is how PG18's
use_scram_passthrough is asked for.) An empty file or variable is an error
too. The error names
the file and the variable, never the value.
A plan, not a rebuild. sync.rs compares the target's tables with the
sidecar's foreign tables and plans the changes, one at a time: create a
table, drop one, add, drop or rename a column, change a type or a NOT NULL.
It never drops a table to import it again, because the sidecar's own views,
grants and functions over a foreign table would go with it.
flowchart LR T["the target's catalog"] --> P["sync::plan"] L["the sidecar's foreign tables"] --> P P --> C["CreateTable · DropTable · AddColumn · DropColumn · RenameColumn · AlterType · SetNotNull"]
Aside: how a rename is told from a drop. A column is matched by its remote name. When exactly one column disappeared and one appeared at the same position, with the same type and nullability, that is a rename. Anything else is a drop and an add, and the CLI's dependency check refuses the drop if a view uses the column. Guessing generously here would rename the wrong thing; guessing stingily only ever refuses.
Try it.
cargo test -p postjevsql-sidecarruns these files' tests in a fraction of a second.
For the people who maintain it
| File | What |
|---|---|
| lib.rs | The three modules. |
| config.rs | Config, Target, SslMode (verify-full by default; the weaker modes are for loopback tests), Mapping, Jev. |
| secret.rs | Sources and Source: a secret from a file or an env var, exactly one, and SecretError, which names the sources. |
| sync.rs | Table, Column, Change, Touches (what a change can break), plan, and ident/lit for quoting. |
← Previous: Chapter 10, postjevsql-sidecar/ · Up: postjevsql-sidecar · Next: Chapter 12, cli/ →