using System;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Amazon;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.Lambda.Core;
using Amazon.Lambda.S3Events;
using Amazon.Lambda.Serialization.SystemTextJson;
using Amazon.StepFunctions;
using Amazon.StepFunctions.Model;
using Amazon.Util;
using Amazon.XRay.Recorder.Handlers.AwsSdk;
using Amazon.Lambda.RuntimeSupport;
using System.Text.Json.Serialization;
using System.Text.Json;
using System.Diagnostics.CodeAnalysis;
using Amazon.DynamoDBv2.Model;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using System.Globalization;
namespace s3Trigger
{
public class Function
{
private static readonly string STATE_MACHINE_ARN = Environment.GetEnvironmentVariable("STATE_MACHINE_ARN") ?? string.Empty;
private static readonly string PHOTO_TABLE = Environment.GetEnvironmentVariable("PHOTO_TABLE") ?? string.Empty;
private static readonly IAmazonDynamoDB _ddbClient = new AmazonDynamoDBClient();
private static readonly IAmazonStepFunctions _stepClient = new AmazonStepFunctionsClient();
static Function()
{
AWSSDKHandler.RegisterXRayForAllServices();
}
///
/// The main entry point for the custom runtime.
///
///
private static async Task Main()
{
Func handler = FunctionHandler;
await LambdaBootstrapBuilder.Create(handler, new SourceGeneratorLambdaJsonSerializer(options =>
{
options.PropertyNameCaseInsensitive = true;
}))
.Build()
.RunAsync();
}
public static async Task FunctionHandler(S3Event evnt, ILambdaContext context)
{
var bucket = evnt.Records[0].S3.Bucket.Name;
var key = WebUtility.UrlDecode(evnt.Records[0].S3.Object.Key);
Console.WriteLine($"Bucket: {bucket}");
Console.WriteLine($"key: {key}");
var photoData = key.Split("/").Reverse().Take(2).ToArray();
var photoId = photoData[0];
var userId = photoData[1];
Console.WriteLine($"Parsed photoId: {photoId}");
var input = new SfnInput
{
Bucket = bucket,
SourceKey = key,
PhotoId = photoId,
UserId = userId,
TablePhoto = Environment.GetEnvironmentVariable(PHOTO_TABLE)
};
var stepResponse = await _stepClient.StartExecutionAsync(new StartExecutionRequest
{
StateMachineArn = STATE_MACHINE_ARN,
Name = $"{MakeSafeName(photoId, 80)}",
Input = JsonSerializer.Serialize(input, CustomJsonSerializerContext.Default.SfnInput)
}).ConfigureAwait(false);
int status = (int)ProcessingStatus.Running;
var request = new UpdateItemRequest
{
Key = new Dictionary()
{
{ "PhotoId", new AttributeValue { S = photoId } }
},
ExpressionAttributeValues = new Dictionary()
{
{":sfnArn",new AttributeValue { S = stepResponse.ExecutionArn }},
{":status",new AttributeValue { S = status.ToString() }},
{":date",new AttributeValue { S = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ss.fff'Z'", CultureInfo.InvariantCulture)}},
},
UpdateExpression = "SET SfnExecutionArn = :sfnArn, ProcessingStatus = :status, UpdatedDate = :date",
TableName = PHOTO_TABLE
};
await _ddbClient.UpdateItemAsync(request);
}
public static string MakeSafeName(string displayName, int maxSize)
{
var builder = new StringBuilder();
foreach (var c in displayName)
if (char.IsLetterOrDigit(c))
builder.Append(c);
else
builder.Append('-');
var name = builder.ToString();
if (maxSize < name.Length) name = name.Substring(0, maxSize);
return name;
}
}
}