Skip to content

Commit 768369f

Browse files
committed
sync.Do
1 parent 0abcc96 commit 768369f

File tree

2 files changed

+110
-69
lines changed

2 files changed

+110
-69
lines changed

internal/sqltest/docker/mysql.go

Lines changed: 55 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@ import (
55
"database/sql"
66
"fmt"
77
"os/exec"
8+
"sync"
89
"time"
910

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

14+
var mysqlSync sync.Once
15+
var mysqlHost string
16+
1317
func StartMySQLServer(c context.Context) (string, error) {
1418
if err := Installed(); err != nil {
1519
return "", err
@@ -22,46 +26,63 @@ func StartMySQLServer(c context.Context) (string, error) {
2226
}
2327
}
2428

25-
ctx, cancel := context.WithTimeout(c, 10*time.Second)
26-
defer cancel()
27-
28-
cmd := exec.Command("docker", "run",
29-
"--name", "sqlc_sqltest_docker_mysql",
30-
"-e", "MYSQL_ROOT_PASSWORD=mysecretpassword",
31-
"-e", "MYSQL_DATABASE=dinotest",
32-
"-p", "3306:3306",
33-
"-d",
34-
"mysql:8",
35-
)
36-
37-
output, err := cmd.CombinedOutput()
38-
fmt.Println(string(output))
39-
if err != nil {
40-
return "", err
41-
}
29+
var syncErr error
30+
mysqlSync.Do(func() {
31+
ctx, cancel := context.WithTimeout(c, 10*time.Second)
32+
defer cancel()
4233

43-
// Create a ticker that fires every 10ms
44-
ticker := time.NewTicker(10 * time.Millisecond)
45-
defer ticker.Stop()
34+
cmd := exec.Command("docker", "run",
35+
"--name", "sqlc_sqltest_docker_mysql",
36+
"-e", "MYSQL_ROOT_PASSWORD=mysecretpassword",
37+
"-e", "MYSQL_DATABASE=dinotest",
38+
"-p", "3306:3306",
39+
"-d",
40+
"mysql:8",
41+
)
4642

47-
uri := "root:mysecretpassword@/dinotest"
43+
output, err := cmd.CombinedOutput()
44+
fmt.Println(string(output))
45+
if err != nil {
46+
syncErr = err
47+
return
48+
}
4849

49-
db, err := sql.Open("mysql", uri)
50-
if err != nil {
51-
return "", fmt.Errorf("sql.Open: %w", err)
52-
}
50+
// Create a ticker that fires every 10ms
51+
ticker := time.NewTicker(10 * time.Millisecond)
52+
defer ticker.Stop()
53+
54+
uri := "root:mysecretpassword@/dinotest"
5355

54-
for {
55-
select {
56-
case <-ctx.Done():
57-
return "", fmt.Errorf("timeout reached: %w", ctx.Err())
56+
db, err := sql.Open("mysql", uri)
57+
if err != nil {
58+
syncErr = fmt.Errorf("sql.Open: %w", err)
59+
return
60+
}
5861

59-
case <-ticker.C:
60-
// Run your function here
61-
if err := db.PingContext(ctx); err != nil {
62-
continue
62+
for {
63+
select {
64+
case <-ctx.Done():
65+
syncErr = fmt.Errorf("timeout reached: %w", ctx.Err())
66+
return
67+
68+
case <-ticker.C:
69+
// Run your function here
70+
if err := db.PingContext(ctx); err != nil {
71+
continue
72+
}
73+
mysqlHost = uri
74+
return
6375
}
64-
return uri, nil
6576
}
77+
})
78+
79+
if syncErr != nil {
80+
return "", syncErr
6681
}
82+
83+
if mysqlHost == "" {
84+
return "", fmt.Errorf("mysql server setup failed")
85+
}
86+
87+
return mysqlHost, nil
6788
}

internal/sqltest/docker/postgres.go

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@ import (
55
"fmt"
66
"log/slog"
77
"os/exec"
8+
"sync"
89
"time"
910

1011
"github.com/jackc/pgx/v5"
1112
)
1213

14+
var postgresSync sync.Once
15+
var postgresHost string
16+
1317
func StartPostgreSQLServer(c context.Context) (string, error) {
1418
if err := Installed(); err != nil {
1519
return "", err
@@ -22,48 +26,64 @@ func StartPostgreSQLServer(c context.Context) (string, error) {
2226
}
2327
}
2428

25-
ctx, cancel := context.WithTimeout(c, 5*time.Second)
26-
defer cancel()
29+
var syncErr error
30+
postgresSync.Do(func() {
31+
ctx, cancel := context.WithTimeout(c, 5*time.Second)
32+
defer cancel()
2733

28-
cmd := exec.Command("docker", "run",
29-
"--name", "sqlc_sqltest_docker_postgres",
30-
"-e", "POSTGRES_PASSWORD=mysecretpassword",
31-
"-e", "POSTGRES_USER=postgres",
32-
"-p", "5432:5432",
33-
"-d",
34-
"postgres:16",
35-
"-c", "max_connections=200",
36-
)
34+
cmd := exec.Command("docker", "run",
35+
"--name", "sqlc_sqltest_docker_postgres",
36+
"-e", "POSTGRES_PASSWORD=mysecretpassword",
37+
"-e", "POSTGRES_USER=postgres",
38+
"-p", "5432:5432",
39+
"-d",
40+
"postgres:16",
41+
"-c", "max_connections=200",
42+
)
3743

38-
output, err := cmd.CombinedOutput()
39-
fmt.Println(string(output))
40-
if err != nil {
41-
return "", err
42-
}
44+
output, err := cmd.CombinedOutput()
45+
fmt.Println(string(output))
46+
if err != nil {
47+
syncErr = err
48+
return
49+
}
4350

44-
// Create a ticker that fires every 10ms
45-
ticker := time.NewTicker(10 * time.Millisecond)
46-
defer ticker.Stop()
51+
// Create a ticker that fires every 10ms
52+
ticker := time.NewTicker(10 * time.Millisecond)
53+
defer ticker.Stop()
4754

48-
uri := "postgres://postgres:mysecretpassword@localhost:5432/postgres?sslmode=disable"
55+
uri := "postgres://postgres:mysecretpassword@localhost:5432/postgres?sslmode=disable"
4956

50-
for {
51-
select {
52-
case <-ctx.Done():
53-
return "", fmt.Errorf("timeout reached: %w", ctx.Err())
57+
for {
58+
select {
59+
case <-ctx.Done():
60+
syncErr = fmt.Errorf("timeout reached: %w", ctx.Err())
61+
return
5462

55-
case <-ticker.C:
56-
// Run your function here
57-
conn, err := pgx.Connect(ctx, uri)
58-
if err != nil {
59-
slog.Debug("sqltest", "connect", err)
60-
continue
63+
case <-ticker.C:
64+
// Run your function here
65+
conn, err := pgx.Connect(ctx, uri)
66+
if err != nil {
67+
slog.Debug("sqltest", "connect", err)
68+
continue
69+
}
70+
if err := conn.Ping(ctx); err != nil {
71+
slog.Error("sqltest", "ping", err)
72+
continue
73+
}
74+
postgresHost = uri
75+
return
6176
}
62-
if err := conn.Ping(ctx); err != nil {
63-
slog.Error("sqltest", "ping", err)
64-
continue
65-
}
66-
return uri, nil
6777
}
78+
})
79+
80+
if syncErr != nil {
81+
return "", syncErr
6882
}
83+
84+
if postgresHost == "" {
85+
return "", fmt.Errorf("postgres server setup failed")
86+
}
87+
88+
return postgresHost, nil
6989
}

0 commit comments

Comments
 (0)