Skip to content

Commit 1c2b2a7

Browse files
joe4devclaude
andcommitted
chore(init): close HTTP response bodies and minor cleanups
- Close response bodies in SendStatus/SendLogs/SendResult so idle connections are released instead of leaked. - Use errors.New instead of fmt.Errorf with no format arguments. - Document the single-invoke assumption behind the unsynchronized initStart/warmStart fields. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 59e6a2f commit 1c2b2a7

2 files changed

Lines changed: 25 additions & 12 deletions

File tree

cmd/localstack/custom_interop.go

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@ type CustomInteropServer struct {
2727
localStackAdapter *LocalStackAdapter
2828
port string
2929
upstreamEndpoint string
30-
initStart time.Time
31-
warmStart bool
30+
// initStart is set once in Init() and warmStart is flipped on the first invoke.
31+
// Both are accessed only from the single sequential init -> invoke flow (the RIE
32+
// processes one invocation at a time), so they need no additional synchronization.
33+
initStart time.Time
34+
warmStart bool
3235
}
3336

3437
type LocalStackAdapter struct {
@@ -45,10 +48,11 @@ const (
4548

4649
func (l *LocalStackAdapter) SendStatus(status LocalStackStatus, payload []byte) error {
4750
statusUrl := fmt.Sprintf("%s/status/%s/%s", l.UpstreamEndpoint, l.RuntimeId, status)
48-
_, err := http.Post(statusUrl, "application/json", bytes.NewReader(payload))
51+
resp, err := http.Post(statusUrl, "application/json", bytes.NewReader(payload))
4952
if err != nil {
5053
return err
5154
}
55+
defer resp.Body.Close()
5256
return nil
5357
}
5458

@@ -58,8 +62,12 @@ func (l *LocalStackAdapter) SendLogs(invokeId string, logs LogResponse) error {
5862
if err != nil {
5963
return err
6064
}
61-
_, err = http.Post(l.UpstreamEndpoint+"/invocations/"+invokeId+"/logs", "application/json", bytes.NewReader(serialized))
62-
return err
65+
resp, err := http.Post(l.UpstreamEndpoint+"/invocations/"+invokeId+"/logs", "application/json", bytes.NewReader(serialized))
66+
if err != nil {
67+
return err
68+
}
69+
defer resp.Body.Close()
70+
return nil
6371
}
6472

6573
// SendResult posts the invocation result body to LocalStack.
@@ -79,8 +87,12 @@ func (l *LocalStackAdapter) SendResult(invokeId string, body []byte, isError boo
7987
} else {
8088
log.Infoln("Sending to /response")
8189
}
82-
_, err := http.Post(l.UpstreamEndpoint+endpoint, "application/json", bytes.NewReader(body))
83-
return err
90+
resp, err := http.Post(l.UpstreamEndpoint+endpoint, "application/json", bytes.NewReader(body))
91+
if err != nil {
92+
return err
93+
}
94+
defer resp.Body.Close()
95+
return nil
8496
}
8597

8698
// The InvokeRequest is sent by LocalStack to trigger an invocation
@@ -94,12 +106,12 @@ type InvokeRequest struct {
94106

95107
// The ErrorResponse is sent TO LocalStack when encountering an error
96108
type ErrorResponse struct {
97-
ErrorMessage string `json:"errorMessage"`
98-
ErrorType string `json:"errorType,omitempty"`
109+
ErrorMessage string `json:"errorMessage"`
110+
ErrorType string `json:"errorType,omitempty"`
99111
// RequestId uses *string so that an empty string "" is serialized (not omitted),
100112
// while nil is omitted — init errors always set this field, fault events leave it nil.
101-
RequestId *string `json:"requestId,omitempty"`
102-
StackTrace []string `json:"stackTrace,omitempty"`
113+
RequestId *string `json:"requestId,omitempty"`
114+
StackTrace []string `json:"stackTrace,omitempty"`
103115
}
104116

105117
func NewCustomInteropServer(lsOpts *LsOpts, adapter *LocalStackAdapter, delegate interop.Server, logCollector *LogCollector) (server *CustomInteropServer) {

cmd/localstack/supervisor.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"strings"
78
"sync/atomic"
@@ -78,7 +79,7 @@ func (ls *LocalStackSupervisor) loop(ctx context.Context) {
7879

7980
faultData := interop.FaultData{
8081
RequestID: interop.RequestID(uuid.NewString()),
81-
ErrorMessage: fmt.Errorf("Runtime exited without providing a reason"),
82+
ErrorMessage: errors.New("Runtime exited without providing a reason"),
8283
ErrorType: fatalerror.RuntimeExit,
8384
}
8485
if !termination.Success() {

0 commit comments

Comments
 (0)