@@ -49,6 +49,13 @@ func main() {
49
49
50
50
svisor := supervisor .New ("flypg" , 5 * time .Minute )
51
51
52
+ go func () {
53
+ if err := scaleToZeroWorker (ctx , node ); err != nil {
54
+ svisor .Stop ()
55
+ os .Exit (0 )
56
+ }
57
+ }()
58
+
52
59
svisor .AddProcess ("postgres" , fmt .Sprintf ("gosu postgres postgres -D %s -p %d" , node .DataDir , node .Port ))
53
60
54
61
proxyEnv := map [string ]string {
@@ -89,6 +96,56 @@ func main() {
89
96
}
90
97
}
91
98
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
+
92
149
func panicHandler (err error ) {
93
150
debug := os .Getenv ("DEBUG" )
94
151
if debug != "" {
0 commit comments