@@ -4,22 +4,32 @@ package main
4
4
5
5
import (
6
6
"context"
7
+ "fmt"
8
+ "net"
7
9
"os"
10
+ "os/signal"
8
11
"runtime/debug"
9
12
"strconv"
10
13
"strings"
14
+ "sync"
11
15
12
16
"github.com/aws/aws-sdk-go-v2/config"
13
17
"github.com/localstack/lambda-runtime-init/internal/aws/xray"
14
18
"github.com/localstack/lambda-runtime-init/internal/bootstrap"
19
+ "github.com/localstack/lambda-runtime-init/internal/events"
15
20
"github.com/localstack/lambda-runtime-init/internal/hotreloading"
16
21
"github.com/localstack/lambda-runtime-init/internal/logging"
17
22
"github.com/localstack/lambda-runtime-init/internal/server"
23
+
24
+ "github.com/localstack/lambda-runtime-init/internal/supervisor"
18
25
"github.com/localstack/lambda-runtime-init/internal/tracing"
19
26
"github.com/localstack/lambda-runtime-init/internal/utils"
20
27
log "github.com/sirupsen/logrus"
21
28
"go.amzn.com/lambda/core/directinvoke"
29
+ "go.amzn.com/lambda/interop"
22
30
"go.amzn.com/lambda/rapidcore"
31
+ supv "go.amzn.com/lambda/supervisor"
32
+ "go.amzn.com/lambda/telemetry"
23
33
)
24
34
25
35
func InitLsOpts () * server.LsOpts {
@@ -97,6 +107,7 @@ func main() {
97
107
lsOpts := InitLsOpts ()
98
108
functionConf := InitFunctionConfig ()
99
109
awsEnvConf , _ := config .NewEnvConfig ()
110
+ awsEnvConf .Credentials .AccountID = lsOpts .AccountId
100
111
101
112
UnsetLsEnvs ()
102
113
@@ -136,6 +147,10 @@ func main() {
136
147
log .Panicln ("Please specify a number for LOCALSTACK_MAX_PAYLOAD_SIZE" )
137
148
}
138
149
directinvoke .MaxDirectResponseSize = int64 (payloadSize )
150
+ if directinvoke .MaxDirectResponseSize > interop .MaxPayloadSize {
151
+ log .Infof ("Large response size detected (%d bytes), forcing streaming mode" , directinvoke .MaxDirectResponseSize )
152
+ directinvoke .InvokeResponseMode = interop .InvokeResponseModeStreaming
153
+ }
139
154
140
155
// download code archive if env variable is set
141
156
if err := utils .DownloadCodeArchives (lsOpts .CodeArchives ); err != nil {
@@ -166,13 +181,26 @@ func main() {
166
181
}
167
182
}
168
183
184
+ ctx , stop := signal .NotifyContext (context .Background (), os .Interrupt )
185
+ defer stop ()
186
+
169
187
// file watcher for hot-reloading
170
- fileWatcherContext , cancelFileWatcher := context .WithCancel (context .Background ())
188
+ fileWatcherContext , cancelFileWatcher := context .WithCancel (ctx )
189
+ defer cancelFileWatcher ()
171
190
191
+ // Custom Interop Server
192
+ defaultServer := rapidcore .NewServer ()
193
+ lsAdapter := server .NewLocalStackAdapter (lsOpts .RuntimeEndpoint , lsOpts .RuntimeId )
194
+ interopServer := server .NewInteropServer (defaultServer , lsAdapter )
195
+
196
+ // Services required for Sandbox environment
172
197
logCollector := logging .NewLogCollector ()
173
198
localStackLogsEgressApi := logging .NewLocalStackLogsEgressAPI (logCollector )
174
199
tracer := tracing .NewLocalStackTracer ()
175
- // localSupervisor := supervisor.NewLocalSupervisor()
200
+ eventsListener := events .NewEventsListener (lsAdapter , & telemetry.NoOpEventsAPI {})
201
+
202
+ defaultSupv := supv .NewLocalSupervisor ()
203
+ wrappedSupv := supervisor .NewLocalStackSupervisor (ctx , defaultSupv , eventsListener , interopServer .InternalState )
176
204
177
205
// build sandbox
178
206
sandbox := rapidcore .
@@ -185,22 +213,26 @@ func main() {
185
213
SetExtensionsFlag (true ).
186
214
SetInitCachingFlag (true ).
187
215
SetLogsEgressAPI (localStackLogsEgressApi ).
188
- SetTracer (tracer )
216
+ SetTracer (tracer ).
217
+ SetInteropServer (interopServer ).
218
+ SetSupervisor (wrappedSupv )
219
+
220
+ // SetEventsAPI(eventsListener)
189
221
190
222
// Externally set supervisor for metrics tracking
191
223
// sandbox.SetSupervisor(localSupervisor)
192
224
// sandbox.SetRuntimeFsRootPath(localSupervisor.RootPath)
193
225
194
226
// xray daemon
195
- endpoint := "http://" + lsOpts .LocalstackIP + ":" + lsOpts .EdgePort
227
+ endpoint := "http://" + net . JoinHostPort ( lsOpts .LocalstackIP , lsOpts .EdgePort )
196
228
xrayConfig := xray .NewConfig (endpoint , xRayLogLevel )
197
229
d := xray .NewDaemon (xrayConfig , lsOpts .EnableXRayTelemetry == "1" )
198
- sandbox . AddShutdownFunc ( func () {
230
+ defer func () {
199
231
log .Debugln ("Shutting down xray daemon" )
200
232
d .Stop ()
201
233
log .Debugln ("Flushing segments in xray daemon" )
202
234
d .Close ()
203
- })
235
+ }( )
204
236
d .Run () // async
205
237
206
238
if len (handler ) > 0 {
@@ -214,37 +246,63 @@ func main() {
214
246
// initialize all flows and start runtime API
215
247
sandboxContext , internalStateFn := sandbox .Create ()
216
248
// Populate our interop server
217
- sandbox . DefaultInteropServer () .SetSandboxContext (sandboxContext )
218
- sandbox . DefaultInteropServer () .SetInternalStateGetter (internalStateFn )
249
+ interopServer .SetSandboxContext (sandboxContext )
250
+ interopServer .SetInternalStateGetter (internalStateFn )
219
251
220
- localStackService := server .NewLocalStackAPI ( sandbox . LambdaInvokeAPI (), bootstrap , logCollector , xrayConfig .Endpoint , lsOpts , functionConf , awsEnvConf )
252
+ localStackService := server .NewLocalStackService ( interopServer , logCollector , lsAdapter , xrayConfig .Endpoint , lsOpts , functionConf , awsEnvConf )
221
253
222
254
// start runtime init. It is important to start `InitHandler` synchronously because we need to ensure the
223
255
// notification channels and status fields are properly initialized before `AwaitInitialized`
224
256
log .Debugln ("Starting runtime init." )
225
- localStackService .Initialize ()
257
+ if err := localStackService .Initialize (bootstrap ); err != nil {
258
+ log .Fatalf ("Failed to initialize runtime: %s" , err )
259
+ return
260
+ }
226
261
227
262
invokeServer := server .NewServer (lsOpts .InteropPort , localStackService )
228
263
invokeServer .RegisterOnShutdown (localStackService .Close )
229
264
230
265
defer invokeServer .Shutdown (context .Background ())
231
266
232
- go invokeServer .ListenAndServe ()
233
- go hotreloading .RunHotReloadingListener (sandbox .DefaultInteropServer (), lsOpts .HotReloadingPaths , fileWatcherContext , lsOpts .FileWatcherStrategy )
267
+ var wg sync.WaitGroup
268
+
269
+ wg .Add (1 )
270
+ go func () {
271
+ defer wg .Done ()
272
+ listener , err := net .Listen ("tcp" , fmt .Sprintf (":%s" , lsOpts .InteropPort ))
273
+
274
+ if err != nil {
275
+ log .Fatalf ("failed to start listener for custom interops server: %s" , err )
276
+ }
277
+ go invokeServer .Serve (listener )
278
+ log .Debugf ("LocalStack API gateway listening on %s" , listener .Addr ().String ())
279
+ }()
280
+
281
+ wg .Add (1 )
282
+ go func () {
283
+ defer wg .Done ()
284
+ hotreloading .RunHotReloadingListener (interopServer , lsOpts .HotReloadingPaths , fileWatcherContext , lsOpts .FileWatcherStrategy )
285
+ }()
286
+
287
+ wg .Wait ()
234
288
235
289
log .Debugln ("Awaiting initialization of runtime init." )
236
- if err := sandbox . DefaultInteropServer () .AwaitInitialized (); err != nil {
290
+ if err := interopServer .AwaitInitialized (); err != nil {
237
291
// Error cases: ErrInitDoneFailed or ErrInitResetReceived
238
292
log .Errorln ("Runtime init failed to initialize: " + err .Error () + ". Exiting." )
239
293
// NOTE: Sending the error status to LocalStack is handled beforehand in the custom_interop.go through the
240
294
// callback SendInitErrorResponse because it contains the correct error response payload.
241
- return
295
+ // return
296
+ } else {
297
+ log .Debugln ("Completed initialization of runtime init. Sending status ready to LocalStack." )
298
+ if err := localStackService .SendStatus (server .Ready , []byte {}); err != nil {
299
+ log .Fatalln ("Failed to send status ready to LocalStack " + err .Error () + ". Exiting." )
300
+ }
242
301
}
243
302
244
- log . Debugln ( "Completed initialization of runtime init. Sending status ready to LocalStack." )
245
- if err := localStackService . SendStatus ( server . Ready , [] byte {}); err != nil {
246
- log . Fatalln ( "Failed to send status ready to LocalStack " + err . Error () + ". Exiting." )
303
+ select {
304
+ case <- ctx . Done ():
305
+ case <- exitChan :
247
306
}
248
307
249
- <- exitChan
250
308
}
0 commit comments