Skip to content

Commit f91bce7

Browse files
committed
Apply fast PostgreSQL settings to sqlc-test-setup and native test helper
Both the sqlc-test-setup CLI tool and the native test helper now detect postgresql.conf at runtime and append the same speed-optimized settings used in Dockerfile.postgres: fsync=off, synchronous_commit=off, full_page_writes=off, wal_level=minimal, etc. Settings are applied idempotently (a marker comment prevents duplicate entries) and trigger a full restart since wal_level and max_connections require it. This brings CI and non-Docker test environments to parity with the Docker fast-startup image. https://claude.ai/code/session_018Godbm3DFdWJf5jc7NU8Uq
1 parent 0b7069a commit f91bce7

File tree

2 files changed

+168
-0
lines changed

2 files changed

+168
-0
lines changed

cmd/sqlc-test-setup/main.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,10 @@ func startPostgreSQL() error {
266266
return fmt.Errorf("configuring pg_hba.conf: %w", err)
267267
}
268268

269+
if err := applyFastSettings(); err != nil {
270+
return fmt.Errorf("applying fast postgresql settings: %w", err)
271+
}
272+
269273
log.Println("reloading postgresql configuration")
270274
if err := run("sudo", "service", "postgresql", "reload"); err != nil {
271275
return fmt.Errorf("reloading postgresql: %w", err)
@@ -313,6 +317,78 @@ func ensurePgHBAEntry(hbaPath string) error {
313317
return run("bash", "-c", cmd)
314318
}
315319

320+
// pgFastSettings are PostgreSQL settings that sacrifice durability for speed.
321+
// They are unsafe for production but ideal for test databases.
322+
var pgFastSettings = map[string]string{
323+
"fsync": "off",
324+
"synchronous_commit": "off",
325+
"full_page_writes": "off",
326+
"max_connections": "200",
327+
"wal_level": "minimal",
328+
"max_wal_senders": "0",
329+
"max_wal_size": "256MB",
330+
"checkpoint_timeout": "30min",
331+
"log_min_messages": "FATAL",
332+
"log_statement": "none",
333+
}
334+
335+
// detectPgConfigPath returns the path to postgresql.conf by querying the running server.
336+
func detectPgConfigPath() (string, error) {
337+
out, err := runOutput("bash", "-c", "sudo -u postgres psql -t -c 'SHOW config_file;'")
338+
if err != nil {
339+
return "", fmt.Errorf("querying config_file: %w (output: %s)", err, out)
340+
}
341+
path := strings.TrimSpace(out)
342+
if path == "" {
343+
return "", fmt.Errorf("postgresql.conf path is empty")
344+
}
345+
log.Printf("found postgresql.conf at %s", path)
346+
return path, nil
347+
}
348+
349+
// applyFastSettings detects postgresql.conf and appends speed-optimized settings
350+
// for test workloads. Settings that are already present are skipped. A restart
351+
// is needed for some settings (e.g. wal_level, max_connections) to take effect.
352+
func applyFastSettings() error {
353+
confPath, err := detectPgConfigPath()
354+
if err != nil {
355+
return err
356+
}
357+
358+
out, err := runOutput("sudo", "cat", confPath)
359+
if err != nil {
360+
return fmt.Errorf("reading postgresql.conf: %w", err)
361+
}
362+
363+
// Check if we've already applied settings by looking for our marker comment.
364+
if strings.Contains(out, "# sqlc test optimizations") {
365+
log.Println("fast postgresql settings already applied, skipping")
366+
return nil
367+
}
368+
369+
log.Println("applying fast postgresql settings for test workloads")
370+
371+
var block strings.Builder
372+
block.WriteString("\n# sqlc test optimizations\n")
373+
for key, value := range pgFastSettings {
374+
block.WriteString(fmt.Sprintf("%s = %s\n", key, value))
375+
}
376+
377+
cmd := fmt.Sprintf("echo '%s' | sudo tee -a %s", block.String(), confPath)
378+
if err := run("bash", "-c", cmd); err != nil {
379+
return fmt.Errorf("appending settings to postgresql.conf: %w", err)
380+
}
381+
382+
// Some settings (wal_level, max_connections, shared_buffers) require a
383+
// full restart rather than just a reload.
384+
log.Println("restarting postgresql for settings that require a restart")
385+
if err := run("sudo", "service", "postgresql", "restart"); err != nil {
386+
return fmt.Errorf("restarting postgresql: %w", err)
387+
}
388+
389+
return nil
390+
}
391+
316392
func startMySQL() error {
317393
log.Println("--- Starting MySQL ---")
318394

internal/sqltest/native/postgres.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,21 @@ func startPostgresService() error {
114114
return nil
115115
}
116116

117+
// pgFastSettings are PostgreSQL settings that sacrifice durability for speed.
118+
// They are unsafe for production but ideal for test databases.
119+
var pgFastSettings = [][2]string{
120+
{"fsync", "off"},
121+
{"synchronous_commit", "off"},
122+
{"full_page_writes", "off"},
123+
{"max_connections", "200"},
124+
{"wal_level", "minimal"},
125+
{"max_wal_senders", "0"},
126+
{"max_wal_size", "256MB"},
127+
{"checkpoint_timeout", "30min"},
128+
{"log_min_messages", "FATAL"},
129+
{"log_statement", "none"},
130+
}
131+
117132
func configurePostgres() error {
118133
// Set password for postgres user using sudo -u postgres
119134
cmd := exec.Command("sudo", "-u", "postgres", "psql", "-c", "ALTER USER postgres PASSWORD 'postgres';")
@@ -162,9 +177,86 @@ func configurePostgres() error {
162177
}
163178
}
164179

180+
// Apply speed-optimized settings for test workloads
181+
if err := applyFastSettings(); err != nil {
182+
slog.Warn("native/postgres", "fast-settings-error", err)
183+
}
184+
165185
return nil
166186
}
167187

188+
// applyFastSettings appends speed-optimized settings to postgresql.conf for
189+
// test workloads. Settings that sacrifice durability for speed (fsync=off, etc.)
190+
// are applied once and require a restart to take effect.
191+
func applyFastSettings() error {
192+
output, err := exec.Command("sudo", "-u", "postgres", "psql", "-t", "-c", "SHOW config_file;").CombinedOutput()
193+
if err != nil {
194+
return fmt.Errorf("could not find config_file: %w", err)
195+
}
196+
197+
confFile := strings.TrimSpace(string(output))
198+
if confFile == "" {
199+
return fmt.Errorf("empty config_file path")
200+
}
201+
202+
catOutput, err := exec.Command("sudo", "cat", confFile).CombinedOutput()
203+
if err != nil {
204+
return fmt.Errorf("could not read %s: %w", confFile, err)
205+
}
206+
207+
// Check if we've already applied settings.
208+
if strings.Contains(string(catOutput), "# sqlc test optimizations") {
209+
slog.Debug("native/postgres", "fast-settings", "already applied")
210+
return nil
211+
}
212+
213+
slog.Info("native/postgres", "status", "applying fast settings to postgresql.conf")
214+
215+
var block strings.Builder
216+
block.WriteString("\n# sqlc test optimizations\n")
217+
for _, kv := range pgFastSettings {
218+
fmt.Fprintf(&block, "%s = %s\n", kv[0], kv[1])
219+
}
220+
221+
cmd := exec.Command("sudo", "bash", "-c",
222+
fmt.Sprintf("echo '%s' | sudo tee -a %s", block.String(), confFile))
223+
if out, err := cmd.CombinedOutput(); err != nil {
224+
return fmt.Errorf("appending settings to postgresql.conf: %w\n%s", err, out)
225+
}
226+
227+
// Some settings (wal_level, max_connections) require a full restart.
228+
slog.Info("native/postgres", "status", "restarting postgresql for fast settings")
229+
if err := restartPostgres(); err != nil {
230+
return fmt.Errorf("restart for fast settings: %w", err)
231+
}
232+
233+
return nil
234+
}
235+
236+
func restartPostgres() error {
237+
// Try systemctl restart
238+
cmd := exec.Command("sudo", "systemctl", "restart", "postgresql")
239+
if err := cmd.Run(); err == nil {
240+
return nil
241+
}
242+
243+
// Try service restart
244+
cmd = exec.Command("sudo", "service", "postgresql", "restart")
245+
if err := cmd.Run(); err == nil {
246+
return nil
247+
}
248+
249+
// Try pg_ctlcluster restart
250+
output, _ := exec.Command("ls", "/etc/postgresql/").CombinedOutput()
251+
versions := strings.Fields(string(output))
252+
if len(versions) > 0 {
253+
cmd = exec.Command("sudo", "pg_ctlcluster", versions[0], "main", "restart")
254+
return cmd.Run()
255+
}
256+
257+
return fmt.Errorf("could not restart PostgreSQL")
258+
}
259+
168260
func reloadPostgres() error {
169261
// Try systemctl reload
170262
cmd := exec.Command("sudo", "systemctl", "reload", "postgresql")

0 commit comments

Comments
 (0)