// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0
using System.Text.Json;
using Amazon;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.Lambda.Core;
using Amazon.Util;
using Amazon.XRay.Recorder.Handlers.AwsSdk;
using AWS.Lambda.Powertools.Logging;
using AWS.Lambda.Powertools.Metrics;
using AWS.Lambda.Powertools.Tracing;
using DynamoDBContextConfig = Amazon.DynamoDBv2.DataModel.DynamoDBContextConfig;
// Assembly attribute already set
// [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace Unicorn.Properties.PropertiesService;
///
/// Represents the AWS Lambda function responsible for pausing the properties approval workflow until the Contract
/// has been approved
///
public class WaitForContractApprovalFunction
{
private readonly IDynamoDBContext _dynamoDbContext;
///
/// Default constructor. Initialises global variables for function.
///
/// Init exception
public WaitForContractApprovalFunction()
{
// Instrument all AWS SDK calls
AWSSDKHandler.RegisterXRayForAllServices();
var dynamodbTable = Environment.GetEnvironmentVariable("CONTRACT_STATUS_TABLE");
if (string.IsNullOrEmpty(dynamodbTable))
{
throw new Exception("Environment variable CONTRACT_STATUS_TABLE is not defined.");
}
AWSConfigsDynamoDB.Context.TypeMappings[typeof(ContractStatusItem)] =
new TypeMapping(typeof(ContractStatusItem), dynamodbTable);
var config = new DynamoDBContextConfig { Conversion = DynamoDBEntryConversion.V2 };
_dynamoDbContext = new DynamoDBContext(new AmazonDynamoDBClient(), config);
}
///
/// Event handler for ContractStatusChangedEvent
///
/// The input payload
/// Lambda Context runtime methods and attributes
[Logging(LogEvent = true)]
[Metrics(CaptureColdStart = true)]
[Tracing]
public async Task FunctionHandler(object input, ILambdaContext context)
{
var document = JsonSerializer.SerializeToDocument(input);
var propertyId = document.RootElement.GetProperty("Input").GetProperty("PropertyId").GetString() ?? "";
var taskToken = document.RootElement.GetProperty("TaskToken").GetString();
Logger.LogInformation($"Property Id : {propertyId}");
Logger.LogInformation($"Task Token : {taskToken}");
var contractStatus = await GetContractStatus(propertyId).ConfigureAwait(false);
if (contractStatus == null)
{
throw new ContractStatusNotFoundException($"Could not find property with ID: {propertyId}");
}
contractStatus.SfnWaitApprovedTaskToken = taskToken;
await SaveContractStatus(contractStatus).ConfigureAwait(false);
}
///
/// Retrieves the contract status for a specifies property
///
/// Property ID
/// Instance of
[Tracing(SegmentName = "Get Contract Status")]
private async Task GetContractStatus(string propertyId)
{
ContractStatusItem? item;
try
{
Logger.LogInformation($"Getting Contract Status for {propertyId}");
item = await _dynamoDbContext.LoadAsync(propertyId).ConfigureAwait(false);
}
catch (Exception e)
{
Logger.LogInformation($"Error loading contract {propertyId}: {e.Message}");
item = null;
}
Logger.LogInformation($"Found contact: {item != null}");
return item;
}
[Tracing(SegmentName = "Save Contract Status")]
private async Task SaveContractStatus(ContractStatusItem contractStatus)
{
try
{
Logger.LogInformation($"Saving contract for Property ID: {contractStatus.PropertyId}");
await _dynamoDbContext.SaveAsync(contractStatus);
}
catch (Exception e)
{
Logger.LogError(e.Message);
throw;
}
}
}