Skip to content

Commit d3afbb1

Browse files
committed
Adjusted the expected version check and added tests for retries
1 parent c0ac88b commit d3afbb1

File tree

3 files changed

+55
-12
lines changed

3 files changed

+55
-12
lines changed

src/packages/emmett/src/commandHandling/handleCommand.unit.spec.ts

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { describe, it } from 'node:test';
33
import {
44
ExpectedVersionConflictError,
55
getInMemoryEventStore,
6-
isExpectedVersionConflictError,
76
} from '../eventStore';
87
import {
98
assertDeepEqual,
@@ -298,6 +297,49 @@ void describe('Command Handler', () => {
298297
assertEqual(nextExpectedStreamVersion, 2n);
299298
});
300299

300+
void it('does NOT retry handling for wrong explicit version', async () => {
301+
// Given
302+
const productItem: PricedProductItem = {
303+
productId: '123',
304+
quantity: 10,
305+
price: 3,
306+
};
307+
308+
const shoppingCartId = randomUUID();
309+
const command: AddProductItem = {
310+
type: 'AddProductItem',
311+
data: { productItem },
312+
};
313+
314+
// Create the stream
315+
await handleCommand(
316+
eventStore,
317+
shoppingCartId,
318+
(state) => addProductItem(command, state),
319+
{ expectedStreamVersion: 'STREAM_DOES_NOT_EXIST' },
320+
);
321+
322+
let tried = 0;
323+
324+
await assertThrowsAsync(
325+
async () => {
326+
await handleCommand(
327+
eventStore,
328+
shoppingCartId,
329+
(state) => {
330+
tried++;
331+
return addProductItem(command, state);
332+
},
333+
{ expectedStreamVersion: 'STREAM_DOES_NOT_EXIST' },
334+
);
335+
},
336+
(error) => error instanceof ExpectedVersionConflictError,
337+
);
338+
339+
// 0 as it should fail already on aggregating stream
340+
assertEqual(0, tried);
341+
});
342+
301343
void it('When called successfuly returns new state for multiple returned events', async () => {
302344
const productItem: PricedProductItem = {
303345
productId: '123',
@@ -506,7 +548,7 @@ void describe('Command Handler', () => {
506548

507549
let tried = 0;
508550

509-
const error = await assertThrowsAsync(
551+
await assertThrowsAsync(
510552
async () => {
511553
await handleCommand(eventStore, shoppingCartId, () => {
512554
tried++;
@@ -516,8 +558,6 @@ void describe('Command Handler', () => {
516558
(error) => error instanceof ExpectedVersionConflictError,
517559
);
518560

519-
assertTrue(isExpectedVersionConflictError(error));
520-
521561
assertEqual(1, tried);
522562
});
523563
});

src/packages/emmett/src/errors/index.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export class EmmettError extends Error {
5555
public static mapFrom(
5656
error: Error | { message?: string; errorCode?: number },
5757
): EmmettError {
58-
if (error instanceof EmmettError) {
58+
if (EmmettError.isInstanceOf(error)) {
5959
return error;
6060
}
6161

@@ -70,17 +70,16 @@ export class EmmettError extends Error {
7070
});
7171
}
7272

73-
public static isInstanceOf<ErrorType extends EmmettError>(
73+
public static isInstanceOf<ErrorType extends EmmettError = EmmettError>(
7474
error: unknown,
75-
errorCode: (typeof EmmettError.Codes)[keyof typeof EmmettError.Codes],
75+
errorCode?: (typeof EmmettError.Codes)[keyof typeof EmmettError.Codes],
7676
): error is ErrorType {
7777
return (
78-
error !== undefined &&
79-
error !== null &&
8078
typeof error === 'object' &&
79+
error !== null &&
8180
'errorCode' in error &&
8281
isNumber(error.errorCode) &&
83-
error.errorCode === errorCode
82+
(errorCode === undefined || error.errorCode === errorCode)
8483
);
8584
}
8685
}

src/packages/emmett/src/eventStore/expectedVersion.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ConcurrencyError } from '../errors';
1+
import { ConcurrencyError, EmmettError } from '../errors';
22
import type { BigIntStreamPosition, Flavour } from '../typing';
33

44
export type ExpectedStreamVersion<VersionType = BigIntStreamPosition> =
@@ -63,4 +63,8 @@ export class ExpectedVersionConflictError<
6363
export const isExpectedVersionConflictError = (
6464
error: unknown,
6565
): error is ExpectedVersionConflictError =>
66-
error instanceof ExpectedVersionConflictError;
66+
error instanceof ExpectedVersionConflictError ||
67+
EmmettError.isInstanceOf<ConcurrencyError>(
68+
error,
69+
ExpectedVersionConflictError.Codes.ConcurrencyError,
70+
);

0 commit comments

Comments
 (0)