Skip to content

Commit

Permalink
Refactor example to be simpler and with a comparable Idempotent examp…
Browse files Browse the repository at this point in the history
…le Guid. Update dependencies.
  • Loading branch information
hjgraca committed Jul 4, 2023
1 parent 38130a1 commit daa7219
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 97 deletions.
67 changes: 11 additions & 56 deletions examples/Idempotency/src/HelloWorld/Function.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,13 @@

using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Amazon.DynamoDBv2;
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.Core;
using Amazon.Lambda.Serialization.SystemTextJson;
using AWS.Lambda.Powertools.Idempotency;
using AWS.Lambda.Powertools.Idempotency.Persistence;
using AWS.Lambda.Powertools.Logging;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
Expand All @@ -34,34 +31,30 @@ namespace HelloWorld;

public class Function
{
private static HttpClient? _httpClient;
private static AmazonDynamoDBClient? _dynamoDbClient;

/// <summary>
/// Function constructor
/// </summary>
public Function()
{
_httpClient = new HttpClient();
_dynamoDbClient = new AmazonDynamoDBClient();

Init(_dynamoDbClient, _httpClient);
Init(_dynamoDbClient);
}

/// <summary>
/// Test constructor
/// </summary>
public Function(AmazonDynamoDBClient amazonDynamoDb, HttpClient httpClient)
public Function(AmazonDynamoDBClient amazonDynamoDb)
{
_httpClient = httpClient;
_dynamoDbClient = amazonDynamoDb;
Init(amazonDynamoDb, httpClient);
Init(amazonDynamoDb);
}
private void Init(AmazonDynamoDBClient amazonDynamoDb, HttpClient httpClient)

private void Init(AmazonDynamoDBClient amazonDynamoDb)
{
ArgumentNullException.ThrowIfNull(amazonDynamoDb);
ArgumentNullException.ThrowIfNull(httpClient);
var tableName = Environment.GetEnvironmentVariable("TABLE_NAME");
ArgumentNullException.ThrowIfNull(tableName);

Expand Down Expand Up @@ -92,29 +85,13 @@ private void Init(AmazonDynamoDBClient amazonDynamoDb, HttpClient httpClient)
[Logging(LogEvent = true)]
public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest apigwProxyEvent, ILambdaContext context)
{
var serializationOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
var request = JsonSerializer.Deserialize<LookupRequest>(apigwProxyEvent.Body, serializationOptions);
if (request is null)
{
return new APIGatewayProxyResponse
{
Body = "Invalid request",
StatusCode = 403,
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};
}

var location = await GetCallingIp(request.Address);

var requestContextRequestId = apigwProxyEvent.RequestContext.RequestId;
var response = new
{
RequestId = requestContextRequestId,
Greeting = "Hello Powertools for AWS Lambda (.NET)",
IpAddress = location
MethodGuid = GenerateGuid(), // Guid generated by the GenerateGuid method. used to compare Method output
HandlerGuid = Guid.NewGuid().ToString() // Guid generated in the Handler. used to compare Handler output
};

try
Expand All @@ -138,33 +115,11 @@ public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyReques
}

/// <summary>
/// Calls location api to return IP address
/// Generates a new Guid to check if value is the same between calls (should be when idempotency enabled)
/// </summary>
/// <param name="address">Uri of the service providing the calling IP</param>
/// <returns>IP address string</returns>
private static async Task<string?> GetCallingIp(string address)
{
if (_httpClient == null) return "0.0.0.0";
_httpClient.DefaultRequestHeaders.Accept.Clear();
_httpClient.DefaultRequestHeaders.Add("User-Agent", "AWS Lambda .Net Client");

var response = await _httpClient.GetStringAsync(address).ConfigureAwait(false);
var ip = response.Replace("\n", "");

return ip;
}
}

/// <summary>
/// Record to represent the data structure of Lookup request
/// </summary>
[Serializable]
public class LookupRequest
{
public string Address { get; private set; }

public LookupRequest(string address)
/// <returns>GUID</returns>
private static string GenerateGuid()
{
Address = address;
return Guid.NewGuid().ToString();
}
}
6 changes: 3 additions & 3 deletions examples/Idempotency/src/HelloWorld/HelloWorld.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Amazon.Lambda.Core" Version="2.1.0" />
<PackageReference Include="Amazon.Lambda.APIGatewayEvents" Version="2.5.0" />
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.3.0" />
<PackageReference Include="Amazon.Lambda.APIGatewayEvents" Version="2.6.0" />
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.3.1" />
<PackageReference Include="AWS.Lambda.Powertools.Idempotency" Version="0.0.1-preview" />
<PackageReference Include="AWS.Lambda.Powertools.Logging" Version="1.1.1" />
<PackageReference Include="AWSSDK.DynamoDBv2" Version="3.7.103.7" />
<PackageReference Include="AWSSDK.DynamoDBv2" Version="3.7.105.1" />
</ItemGroup>
</Project>
42 changes: 7 additions & 35 deletions examples/Idempotency/test/HelloWorld.Test/FunctionTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,28 +53,14 @@ public async Task TestHelloWorldFunctionHandler()
// arrange
var requestId = Guid.NewGuid().ToString("D");
var accountId = Guid.NewGuid().ToString("D");
var location = "192.158.1.38";

Environment.SetEnvironmentVariable("POWERTOOLS_SERVICE_NAME","powertools-dotnet-idempotency-sample");
Environment.SetEnvironmentVariable("POWERTOOLS_LOG_LEVEL","INFO");
Environment.SetEnvironmentVariable("TABLE_NAME",_tableName);

var handlerMock = new Mock<HttpMessageHandler>();
handlerMock
.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>()
)
.ReturnsAsync(new HttpResponseMessage
{
StatusCode = HttpStatusCode.OK,
Content = new StringContent(location)
});

var request = new APIGatewayProxyRequest
{
Body = "{\"address\": \"https://checkip.amazonaws.com\"}",
Body = "{\"address\": \"Hello World\"}",
RequestContext = new APIGatewayProxyRequest.ProxyRequestContext
{
RequestId = requestId,
Expand All @@ -89,25 +75,11 @@ public async Task TestHelloWorldFunctionHandler()
MemoryLimitInMB = 215,
AwsRequestId = Guid.NewGuid().ToString("D")
};

var body = new Dictionary<string, string>
{
{ "RequestId", requestId },
{ "Greeting", "Hello Powertools for AWS Lambda (.NET)" },
{ "IpAddress", location },
};

var expectedResponse = new APIGatewayProxyResponse
{
Body = JsonSerializer.Serialize(body),
StatusCode = 200,
Headers = new Dictionary<string, string> { { "Content-Type", "application/json" } }
};

// act
var function = new Function(_client, new HttpClient(handlerMock.Object));
var function = new Function(_client);

var firstResponse = await function.FunctionHandler(request, context);
await function.FunctionHandler(request, context);

var secondCallContext = new TestLambdaContext
{
Expand All @@ -116,16 +88,16 @@ public async Task TestHelloWorldFunctionHandler()
MemoryLimitInMB = 215,
AwsRequestId = Guid.NewGuid().ToString("D")
};

var secondResponse = await function.FunctionHandler(request, secondCallContext);

_testOutputHelper.WriteLine("First Response: \n" + firstResponse.Body);
_testOutputHelper.WriteLine("Second Response: \n" + secondResponse.Body);

// assert
Assert.Equal(firstResponse.Body, secondResponse.Body);
Assert.Equal(expectedResponse.Body, secondResponse.Body);
Assert.Equal(expectedResponse.Headers, secondResponse.Headers);
Assert.Equal(expectedResponse.StatusCode, secondResponse.StatusCode);
Assert.Equal(firstResponse.Headers, secondResponse.Headers);
Assert.Equal(firstResponse.StatusCode, secondResponse.StatusCode);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
<PackageReference Include="Amazon.Lambda.Core" Version="2.1.0" />
<PackageReference Include="Amazon.Lambda.TestUtilities" Version="2.0.0" />
<PackageReference Include="Amazon.Lambda.Serialization.SystemTextJson" Version="2.3.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
<PackageReference Include="Moq" Version="4.18.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
<PackageReference Include="Moq" Version="4.18.4" />
<PackageReference Include="xunit" Version="2.4.2" />
<PackageReference Include="Testcontainers" Version="3.2.0" />
<PackageReference Include="Testcontainers" Version="3.3.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand Down

0 comments on commit daa7219

Please sign in to comment.