AWS Lambda Node.js Handler 的 callback 效果

文件 AWS Lambda Function Handler in Node.js 中寫到:

The Node.js runtimes v6.10 and v8.10 support the optional callback parameter. You can use it to explicitly return information back to the caller.



When the callback is called (explicitly or implicitly), AWS Lambda continues the Lambda function invocation until the event loop is empty.

雖然呼叫 callback 塞了要回傳的資料,Lambda Function 還是會繼續執行到 event loop 清空,但呼叫端其實也沒辦法先得到結果。

AWS Lambda Context Object in Node.js 裡說明 context.callbackWaitsForEmptyEventLoop:

callbackWaitsForEmptyEventLoop – Set to false to send the response right away when the callback executes, instead of waiting for the Node.js event loop to be empty. If false, any outstanding events will continue to run during the next invocation.

也就是說如果把 callbackWaitsForEmptyEventLoop 設為 false,雖然會在 callback 被呼叫時,立刻送出 response,但是 Lambda Function 就會進入 freeze 狀態,其他還未執行的 event 會再下次被呼叫時才執行到。

結論就是,一個 Node.js Lambda Function 本身無法做到先把結果回傳給呼叫端,本身繼續處理完其他可以非同步處理,不影響回傳結果的事。有一個稍微變通方式可以做到,是用 Event 方式呼叫另一個 Lambda Function 做額外非同步處理。

AWS AppSync 目前還不能用自訂 scalar type

一加自訂的 scalar type 到 schema 中,儲存 schema 就會失敗,論壇也要人問到這個:https://forums.aws.amazon.com/thread.jspa?messageID=829930&tstart=0

目前只能額外用 AppSync 提供的他們定義的一些 scalar type:https://docs.aws.amazon.com/appsync/latest/devguide/scalars.html#appsync-defined-scalars

他們應該是有打算開放自訂 scalar type,後續再看看什麼時候會開放

Spring Cloud AWS – Assume Role & Proxy configuration for STS & SQS

@Configuration
public class AppConfig {
    private static final String SESSION_NAME = "sample";

    @Value("${proxy.host:#{null}}")
    private String proxyHost;

    @Value("${proxy.port:0}")
    private int proxyPort;

    @Value("${cloud.aws.region.static}")
    private String region;

    @Bean
    @Primary
    public AWSCredentialsProvider awsCredentialsProvider(
            @Value("${cloud.aws.credentials.accessKey}") String accessKey,
            @Value("${cloud.aws.credentials.secretKey}") String secretKey,
            @Value("${cloud.aws.role}") String role) {

        AWSSecurityTokenService stsClient = AWSSecurityTokenServiceClientBuilder.standard()
                .withRegion(region)
                .withClientConfiguration(clientConfiguration())
                .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey)))
                .build();

        return new STSAssumeRoleSessionCredentialsProvider
                .Builder(role, SESSION_NAME)
                .withStsClient(stsClient)
                .build();
    }

    @Bean
    public QueueMessageHandlerFactory queueMessageHandlerFactory() {
        QueueMessageHandlerFactory factory = new QueueMessageHandlerFactory();
        MappingJackson2MessageConverter messageConverter = new MappingJackson2MessageConverter();

        messageConverter.setStrictContentTypeMatch(false);
        factory.setArgumentResolvers(Collections.singletonList(new PayloadArgumentResolver(messageConverter)));
        return factory;
    }

    @Bean(name = "amazonSQS")
    public AmazonSQSAsync amazonSQSAsyncClient(AWSCredentialsProvider awsCredentialsProvider) {
        return AmazonSQSAsyncClientBuilder.standard()
                .withRegion(region)
                .withCredentials(awsCredentialsProvider)
                .withClientConfiguration(clientConfiguration())
                .build();
    }

    @Bean
    ClientConfiguration clientConfiguration() {
        ClientConfiguration clientConfiguration = new ClientConfiguration();

        if (!StringUtils.isEmpty(proxyHost)) {
            clientConfiguration.setProxyHost(proxyHost);
            clientConfiguration.setProxyPort(proxyPort);
        }

        return clientConfiguration;
    }
}