Skip to content

Commit c553c50

Browse files
authored
Fix not firing data changed event on replace item (#386)
* fire event in Replace Item * move assertion into Upsert * add tests to confirm upserting works as intended * fill out data tests * Add Data cange mode for container data * switch overloaded methods to internal, rename data change mode values to manual and auto
1 parent a7c1b19 commit c553c50

File tree

8 files changed

+544
-68
lines changed

8 files changed

+544
-68
lines changed

sample/CustomerApi.Tests/CustomerController/PatchCustomerTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ public async Task Valid_MigratesDataCorrectly()
6363

6464
var client = customerApi.CreateClient(authHeader);
6565
var request = new { EmailAddress = "[email protected]" };
66-
await client.PatchAsJsonAsync("/customers/CustomerId", request);
66+
var response = await client.PatchAsJsonAsync("/customers/CustomerId", request);
6767

68+
response.StatusCode.Should().Be(HttpStatusCode.OK);
6869
await customerApi.Then.TheCustomerShouldMatch(customerUri, c => c.EmailAddresses.SequenceEqual(new List<String> { "[email protected]" }));
6970
}
7071

sample/CustomerApi.Tests/TestApi/CustomerStore.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ Discretionary<string> lastName
5353
return await customerEventRepository.ApplyEvents(customerUri.Uri, 0, customerCreated);
5454
}
5555

56+
public async Task<CustomerReadModel> AnExistingCustomerEmailWasUpdated(CustomerUri customerUri, string emailAddress)
57+
{
58+
var customerReadModel = await customerEventRepository.Get(customerUri.Uri);
59+
var emailUpdated = new CustomerEmailAddressChanged(customerUri, customerReadModel!.EmailAddress, emailAddress);
60+
return await customerEventRepository.ApplyEvents(customerUri.Uri, customerReadModel.Revision, emailUpdated);
61+
}
62+
5663
public async Task GivenTheCustomerIsDeleted(CustomerUri customerUri)
5764
{
5865
var customerDeleted = new CustomerDeleted(customerUri);

src/LogOtter.CosmosDb.ContainerMock/ContainerMock.cs

Lines changed: 113 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,23 @@ public IEnumerable<TestContainerItem<T>> GetAllItems<T>()
6161
}
6262
}
6363

64-
public override async Task<ResponseMessage> CreateItemStreamAsync(
64+
public override Task<ResponseMessage> CreateItemStreamAsync(
6565
Stream streamPayload,
6666
PartitionKey partitionKey,
6767
ItemRequestOptions? requestOptions = null,
6868
CancellationToken cancellationToken = default
6969
)
70+
{
71+
return CreateItemStreamAsync(streamPayload, partitionKey, requestOptions, DataChangeMode.Auto, cancellationToken);
72+
}
73+
74+
internal async Task<ResponseMessage> CreateItemStreamAsync(
75+
Stream streamPayload,
76+
PartitionKey partitionKey,
77+
ItemRequestOptions? requestOptions = null,
78+
DataChangeMode dataChangeMode = DataChangeMode.Auto,
79+
CancellationToken cancellationToken = default
80+
)
7081
{
7182
ThrowNextExceptionIfPresent(new InvocationInformation(nameof(CreateItemStreamAsync)));
7283

@@ -81,7 +92,7 @@ public override async Task<ResponseMessage> CreateItemStreamAsync(
8192

8293
try
8394
{
84-
var response = await _containerData.AddItem(json, partitionKey, requestOptions, cancellationToken);
95+
var response = await _containerData.AddItem(json, partitionKey, dataChangeMode, requestOptions, cancellationToken);
8596

8697
return ToCosmosResponseMessage(response, streamPayload);
8798
}
@@ -91,10 +102,21 @@ public override async Task<ResponseMessage> CreateItemStreamAsync(
91102
}
92103
}
93104

94-
public override async Task<ItemResponse<T>> CreateItemAsync<T>(
105+
public override Task<ItemResponse<T>> CreateItemAsync<T>(
106+
T item,
107+
PartitionKey? partitionKey = default,
108+
ItemRequestOptions? requestOptions = null,
109+
CancellationToken cancellationToken = default
110+
)
111+
{
112+
return CreateItemAsync(item, partitionKey, requestOptions, DataChangeMode.Auto, cancellationToken);
113+
}
114+
115+
internal async Task<ItemResponse<T>> CreateItemAsync<T>(
95116
T item,
96117
PartitionKey? partitionKey = default,
97118
ItemRequestOptions? requestOptions = null,
119+
DataChangeMode dataChangeMode = DataChangeMode.Auto,
98120
CancellationToken cancellationToken = default
99121
)
100122
{
@@ -126,7 +148,7 @@ public override async Task<ItemResponse<T>> CreateItemAsync<T>(
126148

127149
try
128150
{
129-
var response = await _containerData.AddItem(json, GetPartitionKey(json, partitionKey), requestOptions, cancellationToken);
151+
var response = await _containerData.AddItem(json, GetPartitionKey(json, partitionKey), dataChangeMode, requestOptions, cancellationToken);
130152

131153
return ToCosmosItemResponse<T>(response);
132154
}
@@ -201,12 +223,23 @@ public override Task<ItemResponse<T>> ReadItemAsync<T>(
201223
return Task.FromResult<ItemResponse<T>>(itemResponse);
202224
}
203225

204-
public override async Task<ResponseMessage> UpsertItemStreamAsync(
226+
public override Task<ResponseMessage> UpsertItemStreamAsync(
205227
Stream streamPayload,
206228
PartitionKey partitionKey,
207229
ItemRequestOptions? requestOptions = null,
208230
CancellationToken cancellationToken = default
209231
)
232+
{
233+
return UpsertItemStreamAsync(streamPayload, partitionKey, requestOptions, DataChangeMode.Auto, cancellationToken);
234+
}
235+
236+
internal async Task<ResponseMessage> UpsertItemStreamAsync(
237+
Stream streamPayload,
238+
PartitionKey partitionKey,
239+
ItemRequestOptions? requestOptions = null,
240+
DataChangeMode dataChangeMode = DataChangeMode.Auto,
241+
CancellationToken cancellationToken = default
242+
)
210243
{
211244
ThrowNextExceptionIfPresent(new InvocationInformation(nameof(UpsertItemStreamAsync)));
212245

@@ -216,7 +249,7 @@ public override async Task<ResponseMessage> UpsertItemStreamAsync(
216249

217250
try
218251
{
219-
var response = await _containerData.UpsertItem(json, partitionKey, requestOptions, cancellationToken);
252+
var response = await _containerData.UpsertItem(json, partitionKey, dataChangeMode, requestOptions, cancellationToken);
220253
return ToCosmosResponseMessage(response, streamPayload);
221254
}
222255
catch (ContainerMockException ex)
@@ -225,10 +258,21 @@ public override async Task<ResponseMessage> UpsertItemStreamAsync(
225258
}
226259
}
227260

228-
public override async Task<ItemResponse<T>> UpsertItemAsync<T>(
261+
public override Task<ItemResponse<T>> UpsertItemAsync<T>(
262+
T item,
263+
PartitionKey? partitionKey = default,
264+
ItemRequestOptions? requestOptions = null,
265+
CancellationToken cancellationToken = default
266+
)
267+
{
268+
return UpsertItemAsync(item, partitionKey, requestOptions, DataChangeMode.Auto, cancellationToken);
269+
}
270+
271+
internal async Task<ItemResponse<T>> UpsertItemAsync<T>(
229272
T item,
230273
PartitionKey? partitionKey = default,
231274
ItemRequestOptions? requestOptions = null,
275+
DataChangeMode dataChangeMode = DataChangeMode.Auto,
232276
CancellationToken cancellationToken = default
233277
)
234278
{
@@ -238,7 +282,13 @@ public override async Task<ItemResponse<T>> UpsertItemAsync<T>(
238282

239283
try
240284
{
241-
var response = await _containerData.UpsertItem(json, GetPartitionKey(json, partitionKey), requestOptions, cancellationToken);
285+
var response = await _containerData.UpsertItem(
286+
json,
287+
GetPartitionKey(json, partitionKey),
288+
dataChangeMode,
289+
requestOptions,
290+
cancellationToken
291+
);
242292
return ToCosmosItemResponse<T>(response);
243293
}
244294
catch (ContainerMockException ex)
@@ -247,11 +297,23 @@ public override async Task<ItemResponse<T>> UpsertItemAsync<T>(
247297
}
248298
}
249299

250-
public override async Task<ItemResponse<T>> ReplaceItemAsync<T>(
300+
public override Task<ItemResponse<T>> ReplaceItemAsync<T>(
301+
T item,
302+
string id,
303+
PartitionKey? partitionKey = default,
304+
ItemRequestOptions? requestOptions = null,
305+
CancellationToken cancellationToken = default
306+
)
307+
{
308+
return ReplaceItemAsync(item, id, partitionKey, requestOptions, DataChangeMode.Auto, cancellationToken);
309+
}
310+
311+
internal async Task<ItemResponse<T>> ReplaceItemAsync<T>(
251312
T item,
252313
string id,
253314
PartitionKey? partitionKey = default,
254315
ItemRequestOptions? requestOptions = null,
316+
DataChangeMode dataChangeMode = DataChangeMode.Auto,
255317
CancellationToken cancellationToken = default
256318
)
257319
{
@@ -261,7 +323,14 @@ public override async Task<ItemResponse<T>> ReplaceItemAsync<T>(
261323

262324
try
263325
{
264-
var response = await _containerData.ReplaceItem(id, json, GetPartitionKey(json, partitionKey), requestOptions, cancellationToken);
326+
var response = await _containerData.ReplaceItem(
327+
id,
328+
json,
329+
GetPartitionKey(json, partitionKey),
330+
dataChangeMode,
331+
requestOptions,
332+
cancellationToken
333+
);
265334
return ToCosmosItemResponse<T>(response);
266335
}
267336
catch (ContainerMockException ex)
@@ -295,12 +364,23 @@ public override Task<ItemResponse<T>> DeleteItemAsync<T>(
295364
ItemRequestOptions? requestOptions = null,
296365
CancellationToken cancellationToken = default
297366
)
367+
{
368+
return DeleteItemAsync<T>(id, partitionKey, requestOptions, DataChangeMode.Auto, cancellationToken);
369+
}
370+
371+
internal Task<ItemResponse<T>> DeleteItemAsync<T>(
372+
string id,
373+
PartitionKey partitionKey,
374+
ItemRequestOptions? requestOptions = null,
375+
DataChangeMode dataChangeMode = DataChangeMode.Auto,
376+
CancellationToken cancellationToken = default
377+
)
298378
{
299379
ThrowNextExceptionIfPresent(new InvocationInformation(nameof(DeleteItemAsync)));
300380

301381
try
302382
{
303-
_containerData.RemoveItem(id, partitionKey, requestOptions);
383+
_containerData.RemoveItem(id, partitionKey, dataChangeMode, requestOptions);
304384

305385
var itemResponse = new MockItemResponse<T>(HttpStatusCode.NoContent);
306386
return Task.FromResult<ItemResponse<T>>(itemResponse);
@@ -311,18 +391,29 @@ public override Task<ItemResponse<T>> DeleteItemAsync<T>(
311391
}
312392
}
313393

314-
public override async Task<ResponseMessage> DeleteItemStreamAsync(
394+
public override Task<ResponseMessage> DeleteItemStreamAsync(
395+
string id,
396+
PartitionKey partitionKey,
397+
ItemRequestOptions? requestOptions = null,
398+
CancellationToken cancellationToken = default
399+
)
400+
{
401+
return DeleteItemStreamAsync(id, partitionKey, requestOptions, DataChangeMode.Auto, cancellationToken);
402+
}
403+
404+
internal async Task<ResponseMessage> DeleteItemStreamAsync(
315405
string id,
316406
PartitionKey partitionKey,
317407
ItemRequestOptions? requestOptions = null,
408+
DataChangeMode dataChangeMode = DataChangeMode.Auto,
318409
CancellationToken cancellationToken = default
319410
)
320411
{
321412
ThrowNextExceptionIfPresent(new InvocationInformation(nameof(DeleteItemStreamAsync)));
322413

323414
try
324415
{
325-
_containerData.RemoveItem(id, partitionKey, requestOptions);
416+
_containerData.RemoveItem(id, partitionKey, dataChangeMode, requestOptions);
326417
var responseMessage = new ResponseMessage(HttpStatusCode.NoContent);
327418
return responseMessage;
328419
}
@@ -396,6 +487,15 @@ public void RestoreSnapshot(ContainerDataSnapshot snapshot)
396487
_containerData.RestoreSnapshot(snapshot);
397488
}
398489

490+
public void ExecuteDataChanges()
491+
{
492+
while (!_containerData.DataChanges.IsEmpty)
493+
{
494+
_containerData.DataChanges.TryDequeue(out var action);
495+
action?.Invoke();
496+
}
497+
}
498+
399499
private static ResponseMessage ToCosmosResponseMessage(Response response, Stream streamPayload)
400500
{
401501
var statusCode = response.IsUpdate ? HttpStatusCode.OK : HttpStatusCode.Created;

0 commit comments

Comments
 (0)