Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
sync.Do
  • Loading branch information
kyleconroy committed Aug 25, 2025
commit 768369fd9f7db1fdcc4ca722157152b9c47e2262
89 changes: 55 additions & 34 deletions internal/sqltest/docker/mysql.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ import (
"database/sql"
"fmt"
"os/exec"
"sync"
"time"

_ "github.com/go-sql-driver/mysql"
)

var mysqlSync sync.Once
var mysqlHost string

func StartMySQLServer(c context.Context) (string, error) {
if err := Installed(); err != nil {
return "", err
Expand All @@ -22,46 +26,63 @@ func StartMySQLServer(c context.Context) (string, error) {
}
}

ctx, cancel := context.WithTimeout(c, 10*time.Second)
defer cancel()

cmd := exec.Command("docker", "run",
"--name", "sqlc_sqltest_docker_mysql",
"-e", "MYSQL_ROOT_PASSWORD=mysecretpassword",
"-e", "MYSQL_DATABASE=dinotest",
"-p", "3306:3306",
"-d",
"mysql:8",
)

output, err := cmd.CombinedOutput()
fmt.Println(string(output))
if err != nil {
return "", err
}
var syncErr error
mysqlSync.Do(func() {
ctx, cancel := context.WithTimeout(c, 10*time.Second)
defer cancel()

// Create a ticker that fires every 10ms
ticker := time.NewTicker(10 * time.Millisecond)
defer ticker.Stop()
cmd := exec.Command("docker", "run",
"--name", "sqlc_sqltest_docker_mysql",
"-e", "MYSQL_ROOT_PASSWORD=mysecretpassword",
"-e", "MYSQL_DATABASE=dinotest",
"-p", "3306:3306",
"-d",
"mysql:8",
)

uri := "root:mysecretpassword@/dinotest"
output, err := cmd.CombinedOutput()
fmt.Println(string(output))
if err != nil {
syncErr = err
return
}

db, err := sql.Open("mysql", uri)
if err != nil {
return "", fmt.Errorf("sql.Open: %w", err)
}
// Create a ticker that fires every 10ms
ticker := time.NewTicker(10 * time.Millisecond)
defer ticker.Stop()

uri := "root:mysecretpassword@/dinotest"

for {
select {
case <-ctx.Done():
return "", fmt.Errorf("timeout reached: %w", ctx.Err())
db, err := sql.Open("mysql", uri)
if err != nil {
syncErr = fmt.Errorf("sql.Open: %w", err)
return
}

case <-ticker.C:
// Run your function here
if err := db.PingContext(ctx); err != nil {
continue
for {
select {
case <-ctx.Done():
syncErr = fmt.Errorf("timeout reached: %w", ctx.Err())
return

case <-ticker.C:
// Run your function here
if err := db.PingContext(ctx); err != nil {
continue
}
mysqlHost = uri
return
}
return uri, nil
}
})

if syncErr != nil {
return "", syncErr
}

if mysqlHost == "" {
return "", fmt.Errorf("mysql server setup failed")
}

return mysqlHost, nil
}
90 changes: 55 additions & 35 deletions internal/sqltest/docker/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ import (
"fmt"
"log/slog"
"os/exec"
"sync"
"time"

"github.com/jackc/pgx/v5"
)

var postgresSync sync.Once
var postgresHost string

func StartPostgreSQLServer(c context.Context) (string, error) {
if err := Installed(); err != nil {
return "", err
Expand All @@ -22,48 +26,64 @@ func StartPostgreSQLServer(c context.Context) (string, error) {
}
}

ctx, cancel := context.WithTimeout(c, 5*time.Second)
defer cancel()
var syncErr error
postgresSync.Do(func() {
ctx, cancel := context.WithTimeout(c, 5*time.Second)
defer cancel()

cmd := exec.Command("docker", "run",
"--name", "sqlc_sqltest_docker_postgres",
"-e", "POSTGRES_PASSWORD=mysecretpassword",
"-e", "POSTGRES_USER=postgres",
"-p", "5432:5432",
"-d",
"postgres:16",
"-c", "max_connections=200",
)
cmd := exec.Command("docker", "run",
"--name", "sqlc_sqltest_docker_postgres",
"-e", "POSTGRES_PASSWORD=mysecretpassword",
"-e", "POSTGRES_USER=postgres",
"-p", "5432:5432",
"-d",
"postgres:16",
"-c", "max_connections=200",
)

output, err := cmd.CombinedOutput()
fmt.Println(string(output))
if err != nil {
return "", err
}
output, err := cmd.CombinedOutput()
fmt.Println(string(output))
if err != nil {
syncErr = err
return
}

// Create a ticker that fires every 10ms
ticker := time.NewTicker(10 * time.Millisecond)
defer ticker.Stop()
// Create a ticker that fires every 10ms
ticker := time.NewTicker(10 * time.Millisecond)
defer ticker.Stop()

uri := "postgres://postgres:mysecretpassword@localhost:5432/postgres?sslmode=disable"
uri := "postgres://postgres:mysecretpassword@localhost:5432/postgres?sslmode=disable"

for {
select {
case <-ctx.Done():
return "", fmt.Errorf("timeout reached: %w", ctx.Err())
for {
select {
case <-ctx.Done():
syncErr = fmt.Errorf("timeout reached: %w", ctx.Err())
return

case <-ticker.C:
// Run your function here
conn, err := pgx.Connect(ctx, uri)
if err != nil {
slog.Debug("sqltest", "connect", err)
continue
case <-ticker.C:
// Run your function here
conn, err := pgx.Connect(ctx, uri)
if err != nil {
slog.Debug("sqltest", "connect", err)
continue
}
if err := conn.Ping(ctx); err != nil {
slog.Error("sqltest", "ping", err)
continue
}
postgresHost = uri
return
}
if err := conn.Ping(ctx); err != nil {
slog.Error("sqltest", "ping", err)
continue
}
return uri, nil
}
})

if syncErr != nil {
return "", syncErr
}

if postgresHost == "" {
return "", fmt.Errorf("postgres server setup failed")
}

return postgresHost, nil
}
Loading