Skip to content

Commit 46c7d02

Browse files
authored
Merge pull request #185 from fly-apps/scale_to_zero
Let users scale a pg to zero
2 parents c90a15b + 2d183bf commit 46c7d02

File tree

1 file changed

+57
-0
lines changed

1 file changed

+57
-0
lines changed

cmd/start/main.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,13 @@ func main() {
4949

5050
svisor := supervisor.New("flypg", 5*time.Minute)
5151

52+
go func() {
53+
if err := scaleToZeroWorker(ctx, node); err != nil {
54+
svisor.Stop()
55+
os.Exit(0)
56+
}
57+
}()
58+
5259
svisor.AddProcess("postgres", fmt.Sprintf("gosu postgres postgres -D %s -p %d", node.DataDir, node.Port))
5360

5461
proxyEnv := map[string]string{
@@ -89,6 +96,56 @@ func main() {
8996
}
9097
}
9198

99+
func scaleToZeroWorker(ctx context.Context, node *flypg.Node) error {
100+
rawTimeout, exists := os.LookupEnv("FLY_SCALE_TO_ZERO")
101+
if !exists {
102+
return nil
103+
}
104+
105+
duration, err := time.ParseDuration(rawTimeout)
106+
if err != nil {
107+
fmt.Printf("failed to parse FLY_SCALE_TO_ZERO duration %s\n", err)
108+
return nil
109+
}
110+
111+
fmt.Printf("Configured scale to zero with duration of %s\n", duration.String())
112+
113+
ticker := time.NewTicker(duration)
114+
defer ticker.Stop()
115+
for {
116+
select {
117+
case <-ctx.Done():
118+
return nil
119+
case <-ticker.C:
120+
current, err := getCurrentConnCount(ctx, node)
121+
if err != nil {
122+
fmt.Printf("Failed to get current connection count will try again in %s\n", duration.String())
123+
continue
124+
}
125+
fmt.Printf("Current connection count is %d\n", current)
126+
if current > 1 {
127+
continue
128+
}
129+
return fmt.Errorf("scale to zero condition hit")
130+
}
131+
}
132+
}
133+
134+
func getCurrentConnCount(ctx context.Context, node *flypg.Node) (int, error) {
135+
const sql = "select count(*) from pg_stat_activity where usename != 'repmgr' and usename != 'flypgadmin' and backend_type = 'client backend';"
136+
conn, err := node.NewLocalConnection(ctx, "postgres", node.OperatorCredentials)
137+
if err != nil {
138+
return 0, err
139+
}
140+
defer func() { _ = conn.Close(ctx) }()
141+
142+
var current int
143+
if err := conn.QueryRow(ctx, sql).Scan(&current); err != nil {
144+
return 0, err
145+
}
146+
return current, nil
147+
}
148+
92149
func panicHandler(err error) {
93150
debug := os.Getenv("DEBUG")
94151
if debug != "" {

0 commit comments

Comments
 (0)