5

I'm trying to run a Lambda function from a console application. The idea is for it to run a quick fire & forget lambda function without waiting for lambda function to return. My code doesn't appear to be executing the lambda function at all though. I know the function works because I can run with the test. When I run the below code I just get a task cancelled exception.

var jsonSerializer = new JsonSerializer();
var lambdaConfig = new AmazonLambdaConfig() { RegionEndpoint = RegionEndpoint.USEast2 };
var lambdaClient = new AmazonLambdaClient(lambdaConfig);

using (var memoryStream = new MemoryStream())
{
    jsonSerializer.Serialize(myData, memoryStream);
    var lambdaRequest = new InvokeRequest
    {
        FunctionName = "MyFunction",
        InvocationType = "Event",
        PayloadStream = memoryStream
};

var result = Task.Run(async () => { return await lambdaClient.InvokeAsync(lambdaRequest); }).Result;

Does anyone have some insight into what I'm doing wrong?

Thanks!

4 Answers 4

9

You can pass your myData directly instead converting into MemoryStream, if the data is a valid JSON with double quotes.

In function name you can use the ARN or just the name. Both works fine for me in latest version AWSSDK.Lambda -Version 3.3.103.31

static readonly string awsAccessKey = "access key here";
static readonly string awsSecretKey = "secret key here";

private static BasicAWSCredentials awsCredentials = new BasicAWSCredentials(awsAccessKey, awsSecretKey);
private static AmazonLambdaConfig lambdaConfig = new AmazonLambdaConfig() { RegionEndpoint = RegionEndpoint.USEast1 };
private static AmazonLambdaClient lambdaClient = new AmazonLambdaClient(awsCredentials, lambdaConfig);

public async Task<string> GetLambdaResponse(string myData)
{
    var lambdaRequest = new InvokeRequest
    {
        FunctionName = "mylambdafunction",
        Payload = myData
    };

    var response = await lambdaClient.InvokeAsync(lambdaRequest);
    if (response != null)
    {
        using (var sr = new StreamReader(response.Payload))
        {
            return await sr.ReadToEndAsync();
        }
    }
    return string.Empty;        
}
Sign up to request clarification or add additional context in comments.

Comments

4

I believe there are two issues in your code:

  • (Mentioned by @Nikosi) You dispose your memoryStream before it is used for lambda invocation
  • (The fix that helped in my case) When you serialize you payload into memory stream, the position in the stream points to the byte after its end and thus SDK has nothing to read from it. So I just used memoryStream.Seek(0L, SeekOrigin.Begin)

By the way, assuming that JsonSerializer is the one from Newtonsoft.Json package, I didn't find Serialize method that accepts Stream parameter, only TextWriter or JsonWriter. So it might be necessary to wrap it into StreamWriter and make sure you call Flush or FlushAsync (or dispose StreamWriter before using memory stream as Lambda payload) like this:

await using var stream = new MemoryStream();
await using var streamWriter = new StreamWriter(stream);
var serializer = new JsonSerializer();
serializer.Serialize(streamWriter, payload);
await streamWriter.FlushAsync();
stream.Seek(0L, SeekOrigin.Begin);

log.LogInformation("Batch {0}: sending {1} messages to Lambda", batchId, batch.Count);

var lambdaResponse = await lambda.InvokeAsync(new InvokeRequest
{
    InvocationType = InvocationType.RequestResponse,
    PayloadStream = stream,
    //Payload = JsonConvert.SerializeObject(payload),
    FunctionName = lambdaArn
}, stoppingToken);

Comments

3

Mixing blocking calls could be causing a deadlock. If the intent is to fire and for get then just call the desired function. Also why give request a stream only to dispose of it after wards

public static void Main(string[] args) {    
    var jsonSerializer = new JsonSerializer();
    var lambdaConfig = new AmazonLambdaConfig() { RegionEndpoint = RegionEndpoint.USEast2 };
    var lambdaClient = new AmazonLambdaClient(lambdaConfig);

    var memoryStream = new MemoryStream();

    jsonSerializer.Serialize(myData, memoryStream);
    var lambdaRequest = new InvokeRequest
    {
        FunctionName = "MyFunction",
        InvocationType = "Event",
        PayloadStream = memoryStream
    };

    lambdaClient.InvokeAsync(lambdaRequest);

    Console.ReadLine();
}

2 Comments

The code that you've posed is what I started with, unfortunately the lambda function is never being called, the program completes but the function is never fired. I started wrapping it in Task.Run just to see if it would ever return with a response positive or negative.
Hi Corey, did you ever get this to work? I'm having the same problem.
3

The FunctionName in Nkosi's answer should actually be the entire ARN to your lambda function, so taking from Nkosi's answer:

public static void Main(string[] args) {    
var jsonSerializer = new JsonSerializer();
var lambdaConfig = new AmazonLambdaConfig() { RegionEndpoint = RegionEndpoint.USEast2 };
var lambdaClient = new AmazonLambdaClient(lambdaConfig);

var memoryStream = new MemoryStream();

jsonSerializer.Serialize(myData, memoryStream);
var lambdaRequest = new InvokeRequest
{
    FunctionName = "arn:aws:lambda:ap-southeast-2:{id}:function:MyFunction",
    InvocationType = "Event",
    PayloadStream = memoryStream
};

lambdaClient.InvokeAsync(lambdaRequest);

Console.ReadLine();

1 Comment

I will have to give this a try, I ended up abandoning this in favor of the azure function I wrote. I would like to see if I could make it redundant with this. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.