Skip to content

Commit 9d12fd1

Browse files
committed
feat: improve SDK server start up
Additionally, this change includes a way to run the server embeddedly in another process that may use stdin. Signed-off-by: Donnie Adams <[email protected]>
1 parent 3c29ebe commit 9d12fd1

File tree

2 files changed

+49
-24
lines changed

2 files changed

+49
-24
lines changed

pkg/cli/sdk_server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ func (c *SDKServer) Run(cmd *cobra.Command, _ []string) error {
2929
// Don't use cmd.Context() as we don't want to die on ctrl+c
3030
ctx := context.Background()
3131
if term.IsTerminal(int(os.Stdin.Fd())) {
32-
// Only support CTRL+C if stdin is the terminal. When ran as a SDK it will be a pipe
32+
// Only support CTRL+C if stdin is the terminal. When ran as an SDK it will be a pipe
3333
ctx = cmd.Context()
3434
}
3535

36-
return sdkserver.Start(ctx, sdkserver.Options{
36+
return sdkserver.Run(ctx, sdkserver.Options{
3737
Options: opts,
3838
ListenAddress: c.ListenAddress,
3939
Debug: c.Debug,

pkg/sdkserver/server.go

Lines changed: 47 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55
"errors"
66
"fmt"
77
"io"
8-
"log/slog"
98
"net"
109
"net/http"
1110
"os"
@@ -29,7 +28,15 @@ type Options struct {
2928
Debug bool
3029
}
3130

32-
func Start(ctx context.Context, opts Options) error {
31+
// Run will start the server and block until the server is shut down.
32+
func Run(ctx context.Context, opts Options) error {
33+
listener, err := newListener(opts)
34+
if err != nil {
35+
return err
36+
}
37+
38+
fmt.Println(listener.Addr().String())
39+
3340
sigCtx, cancel := signal.NotifyContext(ctx, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGKILL)
3441
defer cancel()
3542
go func() {
@@ -40,6 +47,32 @@ func Start(ctx context.Context, opts Options) error {
4047
cancel()
4148
}()
4249

50+
return run(sigCtx, listener, opts)
51+
}
52+
53+
// EmbeddedStart allows running the server as an embedded process that may use Stdin for input.
54+
// It returns the address the server is listening on.
55+
func EmbeddedStart(ctx context.Context, opts Options) (string, error) {
56+
listener, err := newListener(opts)
57+
if err != nil {
58+
return "", err
59+
}
60+
61+
go run(ctx, listener, opts)
62+
63+
return listener.Addr().String(), nil
64+
}
65+
66+
func (s *server) close() {
67+
s.client.Close(true)
68+
s.events.Close()
69+
}
70+
71+
func newListener(opts Options) (net.Listener, error) {
72+
return net.Listen("tcp", opts.ListenAddress)
73+
}
74+
75+
func run(ctx context.Context, listener net.Listener, opts Options) error {
4376
if opts.Debug {
4477
mvl.SetDebug()
4578
}
@@ -58,11 +91,6 @@ func Start(ctx context.Context, opts Options) error {
5891
return err
5992
}
6093

61-
listener, err := net.Listen("tcp", opts.ListenAddress)
62-
if err != nil {
63-
return fmt.Errorf("failed to listen on %s: %w", opts.ListenAddress, err)
64-
}
65-
6694
s := &server{
6795
gptscriptOpts: opts.Options,
6896
address: listener.Addr().String(),
@@ -72,11 +100,11 @@ func Start(ctx context.Context, opts Options) error {
72100
waitingToConfirm: make(map[string]chan runner.AuthorizerResponse),
73101
waitingToPrompt: make(map[string]chan map[string]string),
74102
}
75-
defer s.Close()
103+
defer s.close()
76104

77105
s.addRoutes(http.DefaultServeMux)
78106

79-
server := http.Server{
107+
httpServer := &http.Server{
80108
Handler: apply(http.DefaultServeMux,
81109
contentType("application/json"),
82110
addRequestID,
@@ -86,25 +114,22 @@ func Start(ctx context.Context, opts Options) error {
86114
),
87115
}
88116

89-
slog.Info("Starting server", "addr", s.address)
90-
91-
context.AfterFunc(sigCtx, func() {
92-
ctx, cancel := context.WithTimeout(ctx, 15*time.Second)
117+
logger := mvl.Package()
118+
done := make(chan struct{})
119+
context.AfterFunc(ctx, func() {
120+
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
93121
defer cancel()
94122

95-
slog.Info("Shutting down server")
96-
_ = server.Shutdown(ctx)
97-
slog.Info("Server stopped")
123+
logger.Infof("Shutting down server")
124+
_ = httpServer.Shutdown(ctx)
125+
logger.Infof("Server stopped")
126+
close(done)
98127
})
99128

100-
if err := server.Serve(listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
129+
if err = httpServer.Serve(listener); !errors.Is(err, http.ErrServerClosed) {
101130
return fmt.Errorf("server error: %w", err)
102131
}
103132

133+
<-done
104134
return nil
105135
}
106-
107-
func (s *server) Close() {
108-
s.client.Close(true)
109-
s.events.Close()
110-
}

0 commit comments

Comments
 (0)