Skip to content

Commit a105920

Browse files
authored
Update TestToolv2 Lambda Runtime API to partition the events per listening function and support for RequestResponse invocation type. (#1912)
1 parent ce7d6be commit a105920

File tree

8 files changed

+322
-70
lines changed

8 files changed

+322
-70
lines changed

Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Components/Pages/Home.razor

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
@page "/"
1+
@page "/"
22

33
@using Amazon.Lambda.TestTool.Commands
44
@using Amazon.Lambda.TestTool.Services
@@ -9,7 +9,7 @@
99
@using Microsoft.AspNetCore.Http;
1010

1111
@inject IHttpContextAccessor HttpContextAccessor
12-
@inject IRuntimeApiDataStore RuntimeApiModel
12+
@inject IRuntimeApiDataStoreManager DataStoreManager
1313
@inject IDirectoryManager DirectoryManager
1414

1515
<PageTitle>Lambda Function Tester</PageTitle>
@@ -62,33 +62,33 @@
6262
</div>
6363
<div class="col-sm-6">
6464
<h3>Active Event:</h3>
65-
@if (RuntimeApiModel.ActiveEvent == null)
65+
@if (DataStore.ActiveEvent == null)
6666
{
6767
<h2>No active event</h2>
6868
}
6969
else
7070
{
7171
<div>
72-
<div style="cursor: pointer" @onclick="() => OnRequeue(RuntimeApiModel.ActiveEvent.AwsRequestId)">
72+
<div style="cursor: pointer" @onclick="() => OnRequeue(DataStore.ActiveEvent.AwsRequestId)">
7373
@((MarkupString)RebootIcon)
7474
</div>
75-
<p><b>Request ID:</b> @RuntimeApiModel.ActiveEvent.AwsRequestId</p>
76-
<p><b>Status:</b> <span style="@GetStatusStyle(RuntimeApiModel.ActiveEvent.EventStatus)">@RuntimeApiModel.ActiveEvent.EventStatus</span></p>
77-
<p><b>Last Updated:</b> @RuntimeApiModel.ActiveEvent.LastUpdated</p>
78-
<p><b>Event JSON:</b><span class="event-value"><span class="fake-link" @onclick="() => ShowEventJson(RuntimeApiModel.ActiveEvent)">@CreateSnippet(RuntimeApiModel.ActiveEvent.EventJson)</span></span></p>
79-
@if (RuntimeApiModel.ActiveEvent.EventStatus == EventContainer.Status.Failure)
75+
<p><b>Request ID:</b> @DataStore.ActiveEvent.AwsRequestId</p>
76+
<p><b>Status:</b> <span style="@GetStatusStyle(DataStore.ActiveEvent.EventStatus)">@DataStore.ActiveEvent.EventStatus</span></p>
77+
<p><b>Last Updated:</b> @DataStore.ActiveEvent.LastUpdated</p>
78+
<p><b>Event JSON:</b><span class="event-value"><span class="fake-link" @onclick="() => ShowEventJson(DataStore.ActiveEvent)">@CreateSnippet(DataStore.ActiveEvent.EventJson)</span></span></p>
79+
@if (DataStore.ActiveEvent.EventStatus == EventContainer.Status.Failure)
8080
{
81-
<p><b>Error Type:</b> @RuntimeApiModel.ActiveEvent.ErrorType</p>
81+
<p><b>Error Type:</b> @DataStore.ActiveEvent.ErrorType</p>
8282
<p>
8383
<b>Error Response:</b>
84-
<pre class="form-control" style="@Constants.ResponseErrorStyleSizeConstraint">@RuntimeApiModel.ActiveEvent.ErrorResponse</pre>
84+
<pre class="form-control" style="@Constants.ResponseErrorStyleSizeConstraint">@DataStore.ActiveEvent.ErrorResponse</pre>
8585
</p>
8686
}
8787
else
8888
{
8989
<p>
9090
<b>Response:</b>
91-
<pre class="form-control" style="@Constants.ResponseSuccessStyleSizeConstraint">@Utils.TryPrettyPrintJson(RuntimeApiModel.ActiveEvent.Response)</pre>
91+
<pre class="form-control" style="@Constants.ResponseSuccessStyleSizeConstraint">@Utils.TryPrettyPrintJson(DataStore.ActiveEvent.Response)</pre>
9292
</p>
9393
}
9494
</div>
@@ -101,7 +101,7 @@
101101
<div class="col-sm-6">
102102
<h3>Queued Events: <button class="btn btn-secondary btn-sm" @onclick="OnClearQueued">Clear</button></h3>
103103
<div class="col-xs-5 event-list">
104-
@foreach (var evnt in @RuntimeApiModel.QueuedEvents)
104+
@foreach (var evnt in @DataStore.QueuedEvents)
105105
{
106106
<div class="event-list-item">
107107
<div class="row" style="padding: 2px">
@@ -123,7 +123,7 @@
123123
<div class="col-sm-6">
124124
<h3>Executed Events: <button class="btn btn-secondary btn-sm" @onclick="OnClearExecuted">Clear</button></h3>
125125
<div class="col-xs-5 event-list">
126-
@foreach (var evnt in @RuntimeApiModel.ExecutedEvents.OrderByDescending(x => x.LastUpdated))
126+
@foreach (var evnt in @DataStore.ExecutedEvents.OrderByDescending(x => x.LastUpdated))
127127
{
128128
<div class="event-list-item">
129129
<div class="row" style="padding: 2px">
@@ -189,6 +189,8 @@
189189

190190
private IDictionary<string, IList<LambdaRequest>> SampleRequests { get; set; } = new Dictionary<string, IList<LambdaRequest>>();
191191

192+
private IRuntimeApiDataStore DataStore => DataStoreManager.GetLambdaRuntimeDataStore(LambdaRuntimeApi.DefaultFunctionName);
193+
192194
string? _selectedSampleRequestName;
193195
string? SelectedSampleRequestName
194196
{
@@ -218,58 +220,58 @@
218220

219221
protected override void OnInitialized()
220222
{
221-
RuntimeApiModel.StateChange += RuntimeApiModelOnStateChange;
223+
DataStore.StateChange += DataStoreOnStateChange;
222224
SampleRequestManager = new SampleRequestManager(DirectoryManager.GetCurrentDirectory());
223225
SampleRequests = SampleRequestManager.GetSampleRequests();
224226
}
225227

226-
private void RuntimeApiModelOnStateChange(object? sender, EventArgs e)
228+
private void DataStoreOnStateChange(object? sender, EventArgs e)
227229
{
228230
InvokeAsync(this.StateHasChanged);
229231
}
230232

231233
void OnAddEventClick()
232234
{
233-
RuntimeApiModel.QueueEvent(FunctionInput);
235+
DataStore.QueueEvent(FunctionInput, false);
234236
FunctionInput = "";
235237
SelectedSampleRequestName = NoSampleSelectedId;
236238
StateHasChanged();
237239
}
238240

239241
void OnClearQueued()
240242
{
241-
RuntimeApiModel.ClearQueued();
243+
DataStore.ClearQueued();
242244
StateHasChanged();
243245
}
244246

245247
void OnClearExecuted()
246248
{
247-
RuntimeApiModel.ClearExecuted();
249+
DataStore.ClearExecuted();
248250
StateHasChanged();
249251
}
250252

251253
void OnRequeue(string awsRequestId)
252254
{
253255
EventContainer? evnt = null;
254-
if (string.Equals(RuntimeApiModel.ActiveEvent?.AwsRequestId, awsRequestId))
256+
if (string.Equals(DataStore.ActiveEvent?.AwsRequestId, awsRequestId))
255257
{
256-
evnt = RuntimeApiModel.ActiveEvent;
258+
evnt = DataStore.ActiveEvent;
257259
}
258260
else
259261
{
260-
evnt = RuntimeApiModel.ExecutedEvents.FirstOrDefault(x => string.Equals(x.AwsRequestId, awsRequestId));
262+
evnt = DataStore.ExecutedEvents.FirstOrDefault(x => string.Equals(x.AwsRequestId, awsRequestId));
261263
}
262264

263265
if (evnt == null)
264266
return;
265267

266-
RuntimeApiModel.QueueEvent(evnt.EventJson);
268+
DataStore.QueueEvent(evnt.EventJson, false);
267269
StateHasChanged();
268270
}
269271

270272
void OnDeleteEvent(string awsRequestId)
271273
{
272-
RuntimeApiModel.DeleteEvent(awsRequestId);
274+
DataStore.DeleteEvent(awsRequestId);
273275
StateHasChanged();
274276
}
275277

Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Models/EventContainer.cs

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

44
using Amazon.Lambda.TestTool.Services;
55

66
namespace Amazon.Lambda.TestTool.Models;
77

8-
public class EventContainer
8+
public class EventContainer : IDisposable
99
{
1010
public enum Status { Queued, Executing, Success, Failure }
1111

@@ -21,6 +21,9 @@ public enum Status { Queued, Executing, Success, Failure }
2121
public DateTime LastUpdated { get; private set; }
2222

2323
private Status _status = Status.Queued;
24+
25+
private ManualResetEventSlim? _resetEvent;
26+
2427
public Status EventStatus
2528
{
2629
get => _status;
@@ -33,12 +36,17 @@ public Status EventStatus
3336

3437
private readonly RuntimeApiDataStore _dataStore;
3538

36-
public EventContainer(RuntimeApiDataStore dataStore, int eventCount, string eventJson)
39+
public EventContainer(RuntimeApiDataStore dataStore, int eventCount, string eventJson, bool isRequestResponseMode)
3740
{
3841
LastUpdated = DateTime.Now;
3942
_dataStore = dataStore;
4043
AwsRequestId = eventCount.ToString("D12");
4144
EventJson = eventJson;
45+
46+
if (isRequestResponseMode)
47+
{
48+
_resetEvent = new ManualResetEventSlim(false);
49+
}
4250
}
4351

4452
public string FunctionArn
@@ -51,6 +59,12 @@ public void ReportSuccessResponse(string response)
5159
LastUpdated = DateTime.Now;
5260
Response = response;
5361
EventStatus = Status.Success;
62+
63+
if (_resetEvent != null)
64+
{
65+
_resetEvent.Set();
66+
}
67+
5468
_dataStore.RaiseStateChanged();
5569
}
5670

@@ -60,6 +74,50 @@ public void ReportErrorResponse(string errorType, string errorBody)
6074
ErrorType = errorType;
6175
ErrorResponse = errorBody;
6276
EventStatus = Status.Failure;
77+
78+
if (_resetEvent != null)
79+
{
80+
_resetEvent.Set();
81+
}
82+
6383
_dataStore.RaiseStateChanged();
6484
}
85+
86+
public bool WaitForCompletion()
87+
{
88+
if (_resetEvent == null)
89+
{
90+
return false;
91+
}
92+
93+
// The 15 minutes is a fail safe so we at some point we unblock the thread. It is intentionally
94+
// long to give the user time to debug the Lambda function.
95+
return _resetEvent.Wait(TimeSpan.FromMinutes(15));
96+
}
97+
98+
public void Dispose()
99+
{
100+
Dispose(true);
101+
GC.SuppressFinalize(this);
102+
}
103+
104+
private bool _disposed = false;
105+
protected virtual void Dispose(bool disposing)
106+
{
107+
if (_disposed)
108+
{
109+
return;
110+
}
111+
112+
if (disposing)
113+
{
114+
if (_resetEvent != null)
115+
{
116+
_resetEvent.Dispose();
117+
_resetEvent = null;
118+
}
119+
}
120+
121+
_disposed = true;
122+
}
65123
}

Tools/LambdaTestTool-v2/src/Amazon.Lambda.TestTool/Processes/TestToolProcess.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
22
// SPDX-License-Identifier: Apache-2.0
33

44
using Amazon.Lambda.TestTool.Commands.Settings;
@@ -37,7 +37,7 @@ public static TestToolProcess Startup(RunCommandSettings settings, CancellationT
3737
{
3838
var builder = WebApplication.CreateBuilder();
3939

40-
builder.Services.AddSingleton<IRuntimeApiDataStore, RuntimeApiDataStore>();
40+
builder.Services.AddSingleton<IRuntimeApiDataStoreManager, RuntimeApiDataStoreManager>();
4141

4242
// Add services to the container.
4343
builder.Services.AddRazorComponents()
@@ -65,7 +65,7 @@ public static TestToolProcess Startup(RunCommandSettings settings, CancellationT
6565
app.MapRazorComponents<App>()
6666
.AddInteractiveServerRenderMode();
6767

68-
_ = new LambdaRuntimeApi(app, app.Services.GetService<IRuntimeApiDataStore>()!);
68+
LambdaRuntimeApi.SetupLambdaRuntimeApiEndpoints(app);
6969

7070
var runTask = app.RunAsync(cancellationToken);
7171

0 commit comments

Comments
 (0)