1
- //
2
- // AWSLambda.java
3
- //
4
- // Copyright (c) 2013 Amazon. All rights reserved.
5
- //
1
+ /*
2
+ Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3
+ SPDX-License-Identifier: Apache-2.0
4
+ */
6
5
package com .amazonaws .services .lambda .runtime .api .client ;
7
6
8
7
import com .amazonaws .services .lambda .crac .Core ;
12
11
import com .amazonaws .services .lambda .runtime .api .client .logging .LambdaContextLogger ;
13
12
import com .amazonaws .services .lambda .runtime .api .client .logging .LogSink ;
14
13
import com .amazonaws .services .lambda .runtime .api .client .logging .StdOutLogSink ;
15
- import com .amazonaws .services .lambda .runtime .api .client .runtimeapi .InvocationRequest ;
16
- import com .amazonaws .services .lambda .runtime .api .client .runtimeapi .LambdaRuntimeClient ;
14
+ import com .amazonaws .services .lambda .runtime .api .client .runtimeapi .LambdaRuntimeApiClient ;
15
+ import com .amazonaws .services .lambda .runtime .api .client .runtimeapi .LambdaRuntimeApiClientImpl ;
16
+ import com .amazonaws .services .lambda .runtime .api .client .runtimeapi .converters .LambdaErrorConverter ;
17
+ import com .amazonaws .services .lambda .runtime .api .client .runtimeapi .converters .XRayErrorCauseConverter ;
18
+ import com .amazonaws .services .lambda .runtime .api .client .runtimeapi .dto .InvocationRequest ;
19
+ import com .amazonaws .services .lambda .runtime .api .client .runtimeapi .dto .LambdaError ;
20
+ import com .amazonaws .services .lambda .runtime .api .client .runtimeapi .dto .XRayErrorCause ;
17
21
import com .amazonaws .services .lambda .runtime .api .client .util .LambdaOutputStream ;
18
22
import com .amazonaws .services .lambda .runtime .api .client .util .UnsafeUtil ;
19
23
import com .amazonaws .services .lambda .runtime .logging .LogFormat ;
20
24
import com .amazonaws .services .lambda .runtime .logging .LogLevel ;
21
- import com .amazonaws .services .lambda .runtime .serialization .PojoSerializer ;
22
- import com .amazonaws .services .lambda .runtime .serialization .factories .GsonFactory ;
23
- import com .amazonaws .services .lambda .runtime .serialization .factories .JacksonFactory ;
24
25
import com .amazonaws .services .lambda .runtime .serialization .util .ReflectUtil ;
25
26
26
27
import java .io .ByteArrayOutputStream ;
27
28
import java .io .File ;
28
29
import java .io .FileDescriptor ;
29
30
import java .io .FileInputStream ;
31
+ import java .io .IOError ;
30
32
import java .io .IOException ;
31
- import java .io .OutputStream ;
32
33
import java .io .PrintStream ;
33
34
import java .lang .reflect .Constructor ;
34
35
import java .net .URLClassLoader ;
@@ -67,6 +68,10 @@ public class AWSLambda {
67
68
68
69
private static final String AWS_LAMBDA_INITIALIZATION_TYPE = System .getenv (ReservedRuntimeEnvironmentVariables .AWS_LAMBDA_INITIALIZATION_TYPE );
69
70
71
+ protected static URLClassLoader customerClassLoader ;
72
+
73
+ private static LambdaRuntimeApiClient runtimeClient ;
74
+
70
75
static {
71
76
// Override the disabledAlgorithms setting to match configuration for openjdk8-u181.
72
77
// This is to keep DES ciphers around while we deploying security updates.
@@ -143,17 +148,6 @@ public static void setupRuntimeLogger(LambdaLogger lambdaLogger)
143
148
);
144
149
}
145
150
146
- public static String getEnvOrExit (String envVariableName ) {
147
- String value = System .getenv (envVariableName );
148
- if (value == null ) {
149
- System .err .println ("Could not get environment variable " + envVariableName );
150
- System .exit (-1 );
151
- }
152
- return value ;
153
- }
154
-
155
- protected static URLClassLoader customerClassLoader ;
156
-
157
151
/**
158
152
* convert an integer into a FileDescriptor object using reflection to access private members.
159
153
*/
@@ -207,8 +201,7 @@ private static void startRuntime(String handler, LambdaContextLogger lambdaLogge
207
201
System .setErr (new PrintStream (new LambdaOutputStream (System .err ), false , "UTF-8" ));
208
202
setupRuntimeLogger (lambdaLogger );
209
203
210
- String runtimeApi = getEnvOrExit (ReservedRuntimeEnvironmentVariables .AWS_LAMBDA_RUNTIME_API );
211
- LambdaRuntimeClient runtimeClient = new LambdaRuntimeClient (runtimeApi );
204
+ runtimeClient = new LambdaRuntimeApiClientImpl (LambdaEnvironment .RUNTIME_API );
212
205
213
206
String taskRoot = System .getProperty ("user.dir" );
214
207
String libRoot = "/opt/java" ;
@@ -223,17 +216,18 @@ private static void startRuntime(String handler, LambdaContextLogger lambdaLogge
223
216
requestHandler = findRequestHandler (handler , customerClassLoader );
224
217
} catch (UserFault userFault ) {
225
218
lambdaLogger .log (userFault .reportableError (), lambdaLogger .getLogFormat () == LogFormat .JSON ? LogLevel .ERROR : LogLevel .UNDEFINED );
226
- reportInitError (new Failure (userFault ), runtimeClient );
219
+ LambdaError error = LambdaErrorConverter .fromUserFault (userFault );
220
+ runtimeClient .reportInitError (error );
227
221
System .exit (1 );
228
222
return ;
229
223
}
230
224
if (INIT_TYPE_SNAP_START .equals (AWS_LAMBDA_INITIALIZATION_TYPE )) {
231
- onInitComplete (runtimeClient , lambdaLogger );
225
+ onInitComplete (lambdaLogger );
232
226
}
233
227
boolean shouldExit = false ;
234
228
while (!shouldExit ) {
235
229
UserFault userFault = null ;
236
- InvocationRequest request = runtimeClient .waitForNextInvocation ();
230
+ InvocationRequest request = runtimeClient .nextInvocation ();
237
231
if (request .getXrayTraceId () != null ) {
238
232
System .setProperty (LAMBDA_TRACE_HEADER_PROP , request .getXrayTraceId ());
239
233
} else {
@@ -243,26 +237,23 @@ private static void startRuntime(String handler, LambdaContextLogger lambdaLogge
243
237
ByteArrayOutputStream payload ;
244
238
try {
245
239
payload = requestHandler .call (request );
246
- runtimeClient .postInvocationResponse (request .getId (), payload .toByteArray ());
240
+ runtimeClient .reportInvocationSuccess (request .getId (), payload .toByteArray ());
247
241
boolean ignored = Thread .interrupted (); // clear interrupted flag in case if it was set by user's code
248
242
} catch (UserFault f ) {
243
+ shouldExit = f .fatal ;
249
244
userFault = f ;
250
245
UserFault .filterStackTrace (f );
251
- payload = new ByteArrayOutputStream (1024 );
252
- Failure failure = new Failure (f );
253
- GsonFactory .getInstance ().getSerializer (Failure .class ).toJson (failure , payload );
254
- shouldExit = f .fatal ;
255
- runtimeClient .postInvocationError (request .getId (), payload .toByteArray (), failure .getErrorType ());
246
+
247
+ LambdaError error = LambdaErrorConverter .fromUserFault (f );
248
+ runtimeClient .reportInvocationError (request .getId (), error );
256
249
} catch (Throwable t ) {
250
+ shouldExit = t instanceof VirtualMachineError || t instanceof IOError ;
257
251
UserFault .filterStackTrace (t );
258
252
userFault = UserFault .makeUserFault (t );
259
- payload = new ByteArrayOutputStream (1024 );
260
- Failure failure = new Failure (t );
261
- GsonFactory .getInstance ().getSerializer (Failure .class ).toJson (failure , payload );
262
- // These two categories of errors are considered fatal.
263
- shouldExit = Failure .isInvokeFailureFatal (t );
264
- runtimeClient .postInvocationError (request .getId (), payload .toByteArray (), failure .getErrorType (),
265
- serializeAsXRayJson (t ));
253
+
254
+ LambdaError error = LambdaErrorConverter .fromThrowable (t );
255
+ XRayErrorCause xRayErrorCause = XRayErrorCauseConverter .fromThrowable (t );
256
+ runtimeClient .reportInvocationError (request .getId (), error , xRayErrorCause );
266
257
} finally {
267
258
if (userFault != null ) {
268
259
lambdaLogger .log (userFault .reportableError (), lambdaLogger .getLogFormat () == LogFormat .JSON ? LogLevel .ERROR : LogLevel .UNDEFINED );
@@ -271,23 +262,22 @@ private static void startRuntime(String handler, LambdaContextLogger lambdaLogge
271
262
}
272
263
}
273
264
274
- static void onInitComplete (final LambdaRuntimeClient runtimeClient , final LambdaContextLogger lambdaLogger ) throws IOException {
265
+ static void onInitComplete (final LambdaContextLogger lambdaLogger ) throws IOException {
275
266
try {
276
267
Core .getGlobalContext ().beforeCheckpoint (null );
277
- // Blocking call to RAPID /restore/next API, will return after taking snapshot.
278
- // This will also be the 'entrypoint' when resuming from snapshots.
279
- runtimeClient .getRestoreNext ();
268
+ runtimeClient .restoreNext ();
280
269
} catch (Exception e1 ) {
281
270
logExceptionCloudWatch (lambdaLogger , e1 );
282
- reportInitError (new Failure (e1 ), runtimeClient );
271
+ LambdaError error = LambdaErrorConverter .fromThrowable (e1 );
272
+ runtimeClient .reportInitError (error );
283
273
System .exit (64 );
284
274
}
285
275
try {
286
276
Core .getGlobalContext ().afterRestore (null );
287
277
} catch (Exception restoreExc ) {
288
278
logExceptionCloudWatch (lambdaLogger , restoreExc );
289
- Failure errorPayload = new Failure (restoreExc );
290
- reportRestoreError (errorPayload , runtimeClient );
279
+ LambdaError error = LambdaErrorConverter . fromThrowable (restoreExc );
280
+ runtimeClient . reportRestoreError (error );
291
281
System .exit (64 );
292
282
}
293
283
}
@@ -297,40 +287,4 @@ private static void logExceptionCloudWatch(LambdaContextLogger lambdaLogger, Exc
297
287
UserFault userFault = UserFault .makeUserFault (exc , true );
298
288
lambdaLogger .log (userFault .reportableError (), lambdaLogger .getLogFormat () == LogFormat .JSON ? LogLevel .ERROR : LogLevel .UNDEFINED );
299
289
}
300
-
301
- static void reportInitError (final Failure failure ,
302
- final LambdaRuntimeClient runtimeClient ) throws IOException {
303
-
304
- ByteArrayOutputStream payload = new ByteArrayOutputStream (1024 );
305
- JacksonFactory .getInstance ().getSerializer (Failure .class ).toJson (failure , payload );
306
- runtimeClient .postInitError (payload .toByteArray (), failure .getErrorType ());
307
- }
308
-
309
- static int reportRestoreError (final Failure failure ,
310
- final LambdaRuntimeClient runtimeClient ) throws IOException {
311
-
312
- ByteArrayOutputStream payload = new ByteArrayOutputStream (1024 );
313
- JacksonFactory .getInstance ().getSerializer (Failure .class ).toJson (failure , payload );
314
- return runtimeClient .postRestoreError (payload .toByteArray (), failure .getErrorType ());
315
- }
316
-
317
- private static PojoSerializer <XRayErrorCause > xRayErrorCauseSerializer ;
318
-
319
- /**
320
- * @param throwable throwable to convert
321
- * @return json as string expected by XRay's web console. On conversion failure, returns null.
322
- */
323
- private static String serializeAsXRayJson (Throwable throwable ) {
324
- try {
325
- final OutputStream outputStream = new ByteArrayOutputStream ();
326
- final XRayErrorCause cause = new XRayErrorCause (throwable );
327
- if (xRayErrorCauseSerializer == null ) {
328
- xRayErrorCauseSerializer = JacksonFactory .getInstance ().getSerializer (XRayErrorCause .class );
329
- }
330
- xRayErrorCauseSerializer .toJson (cause , outputStream );
331
- return outputStream .toString ();
332
- } catch (Exception e ) {
333
- return null ;
334
- }
335
- }
336
290
}
0 commit comments