Skip to content

Commit 279fd2b

Browse files
committed
Added first check for event-sourced application
1 parent 0ec4216 commit 279fd2b

File tree

12 files changed

+407
-44
lines changed

12 files changed

+407
-44
lines changed

samples/from_crud_to_eventsourcing/src/core/http.ts

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@ import { assertUnsignedBigInt } from './validation';
88
type WeakETag = `W/${string}`;
99
type ETag = WeakETag | string;
1010

11+
const enum HeaderNames {
12+
IF_MATCH = 'if-match',
13+
IF_NOT_MATCH = 'if-not-match',
14+
}
15+
1116
export const WeakETagRegex = /W\/"(\d+.*)"/;
1217

1318
export const enum ETagErrors {
1419
WRONG_WEAK_ETAG_FORMAT = 'WRONG_WEAK_ETAG_FORMAT',
15-
MISSING_IF_MATCH_HEADER = 'MISSING_IF_MATCH_HEADER',
20+
MISSING_HEADER = 'MISSING_HEADER',
1621
}
1722

1823
export const isWeakETag = (etag: ETag): etag is WeakETag => {
@@ -29,18 +34,28 @@ export const toWeakETag = (value: unknown): WeakETag => {
2934
return `W/"${value}"`;
3035
};
3136

32-
export const getETagFromIfMatch = (request: Request): ETag => {
33-
const etag = request.headers['if-match'];
37+
export const getETagFromHeader = (
38+
request: Request,
39+
headerName: HeaderNames
40+
): ETag | undefined => {
41+
const etag = request.headers[headerName];
3442

35-
if (etag === undefined) {
36-
throw ETagErrors.MISSING_IF_MATCH_HEADER;
43+
if (etag === undefined || etag.length > 0) {
44+
return undefined;
3745
}
3846

39-
return etag;
47+
return etag[0];
4048
};
4149

42-
export const getWeakETagValueFromIfMatch = (request: Request): WeakETag => {
43-
const etag = getETagFromIfMatch(request);
50+
export const getWeakETagValueFromHeader = (
51+
request: Request,
52+
headerName: HeaderNames
53+
): WeakETag | undefined => {
54+
const etag = getETagFromHeader(request, headerName);
55+
56+
if (etag === undefined) {
57+
return undefined;
58+
}
4459

4560
if (!isWeakETag(etag)) {
4661
throw ETagErrors.WRONG_WEAK_ETAG_FORMAT;
@@ -49,8 +64,32 @@ export const getWeakETagValueFromIfMatch = (request: Request): WeakETag => {
4964
return getWeakETagValue(etag);
5065
};
5166

52-
export const getExpectedRevisionFromETag = (request: Request): bigint =>
53-
assertUnsignedBigInt(getWeakETagValueFromIfMatch(request));
67+
export const getExpectedRevision = (
68+
request: Request,
69+
headerName: HeaderNames
70+
): bigint | undefined => {
71+
const eTag = getWeakETagValueFromHeader(request, headerName);
72+
73+
if (eTag === undefined) {
74+
return undefined;
75+
}
76+
77+
return assertUnsignedBigInt(eTag);
78+
};
79+
80+
export const getExpectedRevisionFromIfMatch = (request: Request): bigint => {
81+
const revision = getExpectedRevision(request, HeaderNames.IF_MATCH);
82+
83+
if (revision === undefined) {
84+
throw ETagErrors.MISSING_HEADER;
85+
}
86+
87+
return revision;
88+
};
89+
90+
export const getExpectedRevisionFromIfNotMatch = (
91+
request: Request
92+
): bigint | undefined => getExpectedRevision(request, HeaderNames.IF_NOT_MATCH);
5493

5594
//////////////////////////////////////
5695
/// HTTP Helpers

samples/from_crud_to_eventsourcing/src/core/postgres.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,16 @@ export const disconnectFromPostgres = async () => {
4141
export const runPostgresMigration = ({
4242
connectionString,
4343
migrationsPath,
44+
ignoreEdditedMigrationFile = false,
4445
}: {
4546
connectionString: string;
4647
migrationsPath: string;
48+
ignoreEdditedMigrationFile?: boolean;
4749
}) => {
4850
execSync(
49-
`npx node_modules/@databases/pg-migrations apply --database ${connectionString} --directory ${migrationsPath}`
51+
`npx node_modules/@databases/pg-migrations apply --database ${connectionString} --directory ${migrationsPath} ${
52+
ignoreEdditedMigrationFile ? '--ignore-error migration_file_edited' : ''
53+
}`
5054
);
5155
};
5256

samples/from_crud_to_eventsourcing/src/core/validation.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ export const assertPositiveNumberOrUndefined = (
3939
};
4040

4141
export const assertUnsignedBigInt = (value: string): bigint => {
42+
if (value === undefined) {
43+
throw ValidationErrors.NOT_AN_UNSIGNED_BIGINT;
44+
}
45+
4246
const number = BigInt(value);
4347
if (number < 0) {
4448
throw ValidationErrors.NOT_AN_UNSIGNED_BIGINT;

samples/from_crud_to_eventsourcing/src/crud/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
import { startAPI } from '#core/api';
22
import { disconnectFromPostgres } from '#core/postgres';
3-
import { disconnectFromEventStore } from '#eventsourced/core/streams';
43
import { router } from './shoppingCarts/routes';
54

65
//////////////////////////////////////////////////////////
76
/// Make sure that we dispose Postgres connection pool
87
//////////////////////////////////////////////////////////
98

109
process.once('SIGTERM', disconnectFromPostgres);
11-
process.once('SIGTERM', disconnectFromEventStore);
1210

1311
//////////////////////////////////////////////////////////
1412
/// API

samples/from_crud_to_eventsourcing/src/eventsourced/core/subscriptions.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export type EventHandler = (event: SubscriptionResolvedEvent) => Promise<void>;
2020

2121
export const SubscriptionToAll =
2222
(
23-
eventStore: EventStoreDBClient,
23+
getEventStore: () => EventStoreDBClient,
2424
loadCheckpoint: (subscriptionId: string) => Promise<bigint | undefined>
2525
) =>
2626
async (subscriptionId: string, handlers: EventHandler[]) => {
@@ -29,7 +29,7 @@ export const SubscriptionToAll =
2929
? START
3030
: { prepare: currentPosition, commit: currentPosition };
3131

32-
const subscription = eventStore.subscribeToAll({
32+
const subscription = getEventStore().subscribeToAll({
3333
fromPosition,
3434
filter: excludeSystemEvents(),
3535
});
@@ -98,6 +98,6 @@ export const handleEventInPostgresTransactionScope =
9898
};
9999

100100
export const SubscriptionToAllWithPostgresCheckpoints = SubscriptionToAll(
101-
getEventStore(),
101+
getEventStore,
102102
loadCheckPointFromPostgres
103103
);

0 commit comments

Comments
 (0)