Skip to content

Commit 7b369b4

Browse files
feat: Start the relayproxy as a unix socket. (#4261)
* Change format to configure server listening port * Adding comments * adding a log to mention the deprecation * remove duplicated package * Support multiple starting modes * Adding test for server accessors * Change the way to start the API * Use logger pass in function * Add test unix socket * Replace LISTEN * Use zap fatal instead of log * set logger * GetServerPort never return 0 * Use background instead of TODO for context * Log and exit if impossible to remove existing socket * log error when closing the unix socket * better way for the socket to be created * checking errors in tests * use directly the logger passed in the function * better waiting mechanism * move server validation logic to Config object * add test to validate error socket
1 parent 5596094 commit 7b369b4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1877
-334
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,9 @@ This flag split the usage of this flag, 20% will use the variation `my-new-featu
134134
Create a new `YAML` file containing the configuration of your relay proxy.
135135

136136
```yaml title="goff-proxy.yaml"
137-
listen: 1031
137+
server:
138+
mode: http
139+
port: 1031
138140
pollingInterval: 1000
139141
startWithRetrieverError: false
140142
retriever:

cmd/relayproxy/api/routes_monitoring.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
)
1212

1313
func (s *Server) addMonitoringRoutes() {
14-
if s.config.MonitoringPort != 0 {
14+
if s.config.GetMonitoringPort(s.zapLog) != 0 {
1515
s.monitoringEcho = echo.New()
1616
s.monitoringEcho.HideBanner = true
1717
s.monitoringEcho.HidePort = true

cmd/relayproxy/api/routes_monitoring_test.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,11 @@ func TestPprofEndpointsStarts(t *testing.T) {
5151
},
5252
},
5353
},
54+
Server: config.Server{
55+
Mode: config.ServerModeHTTP,
56+
Port: 1031,
57+
},
5458
MonitoringPort: tt.MonitoringPort,
55-
ListenPort: 1031,
5659
EnablePprof: tt.EnablePprof,
5760
}
5861

@@ -65,12 +68,12 @@ func TestPprofEndpointsStarts(t *testing.T) {
6568
Metrics: metric.Metrics{},
6669
}, z)
6770

68-
portToCheck := c.ListenPort
71+
portToCheck := c.GetServerPort(z)
6972
if tt.MonitoringPort != 0 {
7073
portToCheck = tt.MonitoringPort
7174
}
7275

73-
go apiServer.Start()
76+
go apiServer.StartWithContext(context.Background())
7477
defer apiServer.Stop(context.Background())
7578
time.Sleep(1 * time.Second) // waiting for the apiServer to start
7679
resp, err := http.Get(fmt.Sprintf("http://localhost:%d/debug/pprof/heap", portToCheck))

cmd/relayproxy/api/server.go

Lines changed: 75 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"net"
78
"net/http"
9+
"os"
810
"strings"
911

1012
"github.com/aws/aws-lambda-go/lambda"
@@ -111,12 +113,68 @@ func (s *Server) initRoutes() {
111113
s.addAdminRoutes(cRetrieverRefresh)
112114
}
113115

114-
// Start launch the API server
115-
func (s *Server) Start() {
116+
func (s *Server) StartWithContext(ctx context.Context) {
117+
// start the OpenTelemetry tracing service
118+
err := s.otelService.Init(ctx, s.zapLog, s.config)
119+
if err != nil {
120+
s.zapLog.Error(
121+
"error while initializing OTel, continuing without tracing enabled",
122+
zap.Error(err),
123+
)
124+
// we can continue because otel is not mandatory to start the server
125+
}
126+
127+
switch s.config.GetServerMode(s.zapLog) {
128+
case config.ServerModeLambda:
129+
s.startAwsLambda()
130+
case config.ServerModeUnixSocket:
131+
s.startUnixSocketServer(ctx)
132+
default:
133+
s.startAsHTTPServer()
134+
}
135+
}
136+
137+
// startUnixSocketServer launch the API server as a unix socket.
138+
func (s *Server) startUnixSocketServer(ctx context.Context) {
139+
socketPath := s.config.GetUnixSocketPath()
140+
141+
// Clean up the old socket file if it exists (important for graceful restarts)
142+
if _, err := os.Stat(socketPath); err == nil {
143+
if err := os.Remove(socketPath); err != nil {
144+
s.zapLog.Fatal("Could not remove old socket file", zap.String("path", socketPath), zap.Error(err))
145+
}
146+
}
147+
148+
lc := net.ListenConfig{}
149+
listener, err := lc.Listen(ctx, "unix", socketPath)
150+
if err != nil {
151+
s.zapLog.Fatal("Error creating Unix listener", zap.Error(err))
152+
}
153+
154+
defer func() {
155+
if err := listener.Close(); err != nil {
156+
s.zapLog.Error("error closing unix socket listener", zap.Error(err))
157+
}
158+
}()
159+
s.apiEcho.Listener = listener
160+
161+
s.zapLog.Info(
162+
"Starting go-feature-flag relay proxy as unix socket...",
163+
zap.String("socket", socketPath),
164+
zap.String("version", s.config.Version))
165+
166+
err = s.apiEcho.StartServer(new(http.Server))
167+
if err != nil && !errors.Is(err, http.ErrServerClosed) {
168+
s.zapLog.Fatal("Error starting relay proxy as unix socket", zap.Error(err))
169+
}
170+
}
171+
172+
// startAsHTTPServer launch the API server
173+
func (s *Server) startAsHTTPServer() {
116174
// starting the monitoring server on a different port if configured
117175
if s.monitoringEcho != nil {
118176
go func() {
119-
addressMonitoring := fmt.Sprintf("0.0.0.0:%d", s.config.MonitoringPort)
177+
addressMonitoring := fmt.Sprintf("%s:%d", s.config.GetServerHost(), s.config.GetMonitoringPort(s.zapLog))
120178
s.zapLog.Info(
121179
"Starting monitoring",
122180
zap.String("address", addressMonitoring))
@@ -128,40 +186,29 @@ func (s *Server) Start() {
128186
defer func() { _ = s.monitoringEcho.Close() }()
129187
}
130188

131-
// start the OpenTelemetry tracing service
132-
err := s.otelService.Init(context.Background(), s.zapLog, s.config)
133-
if err != nil {
134-
s.zapLog.Error(
135-
"error while initializing OTel, continuing without tracing enabled",
136-
zap.Error(err),
137-
)
138-
// we can continue because otel is not mandatory to start the server
139-
}
140-
141-
// starting the main application
142-
if s.config.ListenPort == 0 {
143-
s.config.ListenPort = 1031
144-
}
145-
address := fmt.Sprintf("0.0.0.0:%d", s.config.ListenPort)
189+
address := fmt.Sprintf("%s:%d", s.config.GetServerHost(), s.config.GetServerPort(s.zapLog))
146190
s.zapLog.Info(
147191
"Starting go-feature-flag relay proxy ...",
148192
zap.String("address", address),
149193
zap.String("version", s.config.Version))
150194

151-
err = s.apiEcho.Start(address)
195+
err := s.apiEcho.Start(address)
152196
if err != nil && !errors.Is(err, http.ErrServerClosed) {
153197
s.zapLog.Fatal("Error starting relay proxy", zap.Error(err))
154198
}
155199
}
156200

157-
// StartAwsLambda is starting the relay proxy as an AWS Lambda
158-
func (s *Server) StartAwsLambda() {
201+
// startAwsLambda is starting the relay proxy as an AWS Lambda
202+
func (s *Server) startAwsLambda() {
159203
lambda.Start(s.getLambdaHandler())
160204
}
161205

206+
// getLambdaHandler returns the appropriate lambda handler based on the configuration.
207+
// We need a dedicated function because it is called from tests as well, this is the
208+
// reason why we can't merged it in startAwsLambda.
162209
func (s *Server) getLambdaHandler() interface{} {
163-
handlerMngr := newAwsLambdaHandlerManager(s.apiEcho, s.config.AwsApiGatewayBasePath)
164-
return handlerMngr.GetAdapter(s.config.AwsLambdaAdapter)
210+
handlerMngr := newAwsLambdaHandlerManager(s.apiEcho, s.config.GetAwsApiGatewayBasePath(s.zapLog))
211+
return handlerMngr.GetAdapter(s.config.GetLambdaAdapter(s.zapLog))
165212
}
166213

167214
// Stop shutdown the API server
@@ -178,8 +225,10 @@ func (s *Server) Stop(ctx context.Context) {
178225
}
179226
}
180227

181-
err = s.apiEcho.Close()
182-
if err != nil {
183-
s.zapLog.Fatal("impossible to stop go-feature-flag relay proxy", zap.Error(err))
228+
if s.apiEcho != nil {
229+
err = s.apiEcho.Close()
230+
if err != nil {
231+
s.zapLog.Fatal("impossible to stop go-feature-flag relay proxy", zap.Error(err))
232+
}
184233
}
185234
}

0 commit comments

Comments
 (0)