Skip to content

Commit 39cd97b

Browse files
committed
Pass domain event id around
1 parent 91ca162 commit 39cd97b

File tree

22 files changed

+180
-85
lines changed

22 files changed

+180
-85
lines changed

src/commands/exclusion-events/exclude-event-form.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {flow, pipe} from 'fp-ts/lib/function';
22
import * as E from 'fp-ts/Either';
33
import {html, safe, toLoggedInContent} from '../../types/html';
44
import {Form} from '../../types/form';
5-
import { DomainEvent } from '../../types';
5+
import {StoredDomainEvent} from '../../types';
66
import { renderEvent } from '../../queries/shared-render/render-domain-event';
77
import * as t from 'io-ts';
88
import * as tt from 'io-ts-types';
@@ -12,7 +12,7 @@ import { StatusCodes } from 'http-status-codes';
1212
import * as O from 'fp-ts/Option';
1313

1414
type ViewModel = {
15-
event: O.Option<DomainEvent>,
15+
event: O.Option<StoredDomainEvent>,
1616
event_id: tt.UUID,
1717
};
1818

@@ -54,7 +54,12 @@ const constructForm: Form<ViewModel>['constructForm'] = input => ({events}) => p
5454
)
5555
),
5656
E.map(params => params.event_id),
57-
E.map(event_id => ({event_id, event: O.fromNullable(events.findLast((event) => event.event_id === event_id))}))
57+
E.map(event_id => ({
58+
event_id,
59+
event: O.fromNullable(
60+
events.findLast(event => event.event_id === event_id)
61+
),
62+
}))
5863
);
5964

6065
export const excludeEventForm: Form<ViewModel> = {

src/commands/exclusion-events/exclude-event.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as t from 'io-ts';
22
import * as tt from 'io-ts-types';
3+
import * as O from 'fp-ts/Option';
34
import {Command} from '../command';
45
import {isAdminOrSuperUser} from '../is-admin-or-super-user';
56

@@ -9,9 +10,7 @@ const codec = t.strict({
910

1011
export type ExcludeEvent = t.TypeOf<typeof codec>;
1112

12-
const process: Command<ExcludeEvent>['process'] = async input => {
13-
14-
};
13+
const process: Command<ExcludeEvent>['process'] = () => O.none;
1514

1615
const resource = () => ({
1716
type: 'ExcludeEvent',

src/dependencies.ts

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
import {Logger} from 'pino';
2-
import {Failure, Email, DomainEvent, ResourceVersion} from './types';
2+
import {
3+
Failure,
4+
Email,
5+
DomainEvent,
6+
ResourceVersion,
7+
StoredDomainEvent,
8+
StoredEventOfType,
9+
} from './types';
310
import * as TE from 'fp-ts/TaskEither';
411
import * as O from 'fp-ts/Option';
512
import {FailureWithStatus} from './types/failure-with-status';
613
import {StatusCodes} from 'http-status-codes';
714
import {Resource} from './types/resource';
8-
import {EventName, EventOfType} from './types/domain-event';
15+
import {EventName} from './types/domain-event';
916
import {SharedReadModel} from './read-models/shared-state';
1017
import {
1118
SheetDataTable,
@@ -30,19 +37,19 @@ export type Dependencies = {
3037
) => TE.TaskEither<FailureWithStatus, unknown>;
3138
getAllEvents: () => TE.TaskEither<
3239
FailureWithStatus,
33-
ReadonlyArray<DomainEvent>
40+
ReadonlyArray<StoredDomainEvent>
3441
>;
3542
getAllExclusionEvents: () => TE.TaskEither<
3643
FailureWithStatus,
3744
ReadonlyArray<ExcludedEvent>
3845
>;
3946
getAllEventsByType: <T extends EventName>(
4047
eventType: T
41-
) => TE.TaskEither<FailureWithStatus, ReadonlyArray<EventOfType<T>>>;
48+
) => TE.TaskEither<FailureWithStatus, ReadonlyArray<StoredEventOfType<T>>>;
4249
getResourceEvents: (resource: Resource) => TE.TaskEither<
4350
FailureWithStatus,
4451
{
45-
events: ReadonlyArray<DomainEvent>;
52+
events: ReadonlyArray<StoredDomainEvent>;
4653
version: ResourceVersion;
4754
}
4855
>;

src/init-dependencies/event-store/events-from-rows.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as E from 'fp-ts/Either';
33
import * as tt from 'io-ts-types';
44
import {EventsTable} from './events-table';
55
import * as t from 'io-ts';
6-
import {DomainEvent} from '../../types';
6+
import {StoredDomainEvent} from '../../types';
77
import {internalCodecFailure} from '../../types/failure-with-status';
88

99
const reshapeRowToEvent = (row: EventsTable['rows'][number]) =>
@@ -12,6 +12,7 @@ const reshapeRowToEvent = (row: EventsTable['rows'][number]) =>
1212
tt.JsonFromString.decode,
1313
E.chain(tt.JsonRecord.decode),
1414
E.map(payload => ({
15+
event_id: row.id,
1516
type: row.event_type,
1617
...payload,
1718
}))
@@ -21,6 +22,6 @@ export const eventsFromRows = (rows: EventsTable['rows']) =>
2122
pipe(
2223
rows,
2324
E.traverseArray(reshapeRowToEvent),
24-
E.chain(t.readonlyArray(DomainEvent).decode),
25+
E.chain(t.readonlyArray(StoredDomainEvent).decode),
2526
E.mapLeft(internalCodecFailure('Failed to get events from DB'))
2627
);

src/init-dependencies/event-store/exclude-event.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import {dbExecute} from '../../util';
1111

1212
const insertEventExclusionRow = `
1313
INSERT INTO events_exclusions
14-
(id, event_id, reverted_by_number, revert_reason)
15-
VALUES (?, ?, ?, ?);
14+
(id, event_id, reverted_by_member_number, revert_reason, reverted_at_timestamp_epoch_ms)
15+
VALUES (?, ?, ?, ?, ?);
1616
`;
1717

1818
// This should only be used where an event needs to be 'deleted'.
@@ -36,6 +36,7 @@ export const excludeEvent =
3636
event_id,
3737
reverted_by_number,
3838
revert_reason,
39+
Date.now(),
3940
]
4041
),
4142
failureWithStatus(

src/init-dependencies/event-store/exclusion-events-from-rows.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,31 @@ import {pipe} from 'fp-ts/lib/function';
22
import * as E from 'fp-ts/Either';
33
import * as tt from 'io-ts-types';
44
import {EventExclusionsTable} from './events-table';
5-
import * as t from 'io-ts';
65
import {DomainEvent} from '../../types';
76
import {internalCodecFailure} from '../../types/failure-with-status';
8-
import { ExcludedEvent } from './excluded-event';
97

10-
const reshapeRowToEvent = (row: EventExclusionsTable['rows'][number]) =>
8+
const reshapeRowToExcludedEvent = (
9+
row: EventExclusionsTable['rows'][number]
10+
) =>
1111
pipe(
1212
row.payload,
1313
tt.JsonFromString.decode,
1414
E.chain(tt.JsonRecord.decode),
1515
E.map(payload => ({
1616
type: row.event_type,
1717
...payload,
18-
}))
19-
);
20-
21-
export const exclusionEventsFromRows = (rows: EventExclusionsTable['rows']): ReadonlyArray<ExcludedEvent> =>
22-
pipe(
23-
rows,
24-
E.traverseArray(reshapeRowToEvent),
25-
E.chain(t.readonlyArray(DomainEvent).decode),
18+
})),
19+
E.chain(DomainEvent.decode),
20+
E.map(payload => ({
21+
id: row.id,
22+
event_id: row.event_id,
23+
reverted_by_number: row.reverted_by_member_number,
24+
revert_reason: row.revert_reason,
25+
revert_at: new Date(row.reverted_at_timestamp_epoch_ms),
26+
payload,
27+
})),
2628
E.mapLeft(internalCodecFailure('Failed to get events from DB'))
2729
);
30+
31+
export const exclusionEventsFromRows = (rows: EventExclusionsTable['rows']) =>
32+
pipe(rows, E.traverseArray(reshapeRowToExcludedEvent));

src/init-dependencies/event-store/get-all-events.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import {EventExclusionsTable, EventsTable} from './events-table';
1111
import {eventsFromRows} from './events-from-rows';
1212
import {Client} from '@libsql/client';
1313
import {StatusCodes} from 'http-status-codes';
14-
import {DomainEvent} from '../../types';
15-
import {EventName, EventOfType} from '../../types/domain-event';
14+
import {StoredDomainEvent, StoredEventOfType} from '../../types';
15+
import {EventName} from '../../types/domain-event';
1616
import {dbExecute} from '../../util';
1717
import { exclusionEventsFromRows } from './exclusion-events-from-rows';
1818

@@ -87,8 +87,11 @@ export const getAllEventsByType =
8787
// This assumes that the DB has only returned events of the correct type.
8888
// This assumption avoids the need to do extra validation.
8989
// TODO - Pass codec to validate straight to eventsFromRows and get best of both.
90-
TE.map<ReadonlyArray<DomainEvent>, ReadonlyArray<EventOfType<T>>>(
91-
es => es as ReadonlyArray<EventOfType<T>>
90+
TE.map<
91+
ReadonlyArray<StoredDomainEvent>,
92+
ReadonlyArray<StoredEventOfType<T>>
93+
>(
94+
es => es as ReadonlyArray<StoredEventOfType<T>>
9295
)
9396
);
9497

@@ -130,9 +133,12 @@ export const getAllEventsByTypes =
130133
// This assumption avoids the need to do extra validation.
131134
// TODO - Pass codec to validate straight to eventsFromRows and get best of both.
132135
TE.map<
133-
ReadonlyArray<DomainEvent>,
134-
ReadonlyArray<EventOfType<T> | EventOfType<R>>
135-
>(es => es as ReadonlyArray<EventOfType<T> | EventOfType<R>>)
136+
ReadonlyArray<StoredDomainEvent>,
137+
ReadonlyArray<StoredEventOfType<T> | StoredEventOfType<R>>
138+
>(
139+
es =>
140+
es as ReadonlyArray<StoredEventOfType<T> | StoredEventOfType<R>>
141+
)
136142
);
137143

138144
export const getAllExclusionEvents = (dbClient: Client): Dependencies['getAllExclusionEvents'] =>
@@ -161,5 +167,5 @@ export const getAllExclusionEvents = (dbClient: Client): Dependencies['getAllExc
161167
)
162168
),
163169
TE.map(table => table.rows),
164-
TE.map(exclusionEventsFromRows)
170+
TE.chainEitherK(exclusionEventsFromRows)
165171
);

src/queries/exclusion-log/render.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ const renderEntry = (event: ViewModel['events'][number]) => html`
2424
<li>
2525
<b>EXCLUDED by ${renderMemberNumber(event.reverted_by_number)} at ${displayDate(DateTime.fromJSDate(event.revert_at))}
2626
because '${sanitizeString(event.revert_reason)}'.</b>
27+
<br />
28+
Event id: ${sanitizeString(event.event_id)}
29+
<br />
2730
${renderPayload(event.payload)}
2831
</li>
2932
`;

src/queries/log/construct-view-model.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {Params} from '../query';
22
import {pipe} from 'fp-ts/lib/function';
3-
import {DomainEvent, User} from '../../types';
3+
import {StoredDomainEvent, User} from '../../types';
44
import {Dependencies} from '../../dependencies';
55
import * as TE from 'fp-ts/TaskEither';
66
import {ViewModel, LogSearch} from './view-model';
@@ -26,7 +26,7 @@ function parseQueryToLogSearch(query: Params): LogSearch {
2626
}
2727

2828
const applyLogSearch =
29-
(search: LogSearch) => (events: ReadonlyArray<DomainEvent>) =>
29+
(search: LogSearch) => (events: ReadonlyArray<StoredDomainEvent>) =>
3030
pipe(events, events => {
3131
const start = search.offset;
3232
const end = search.offset + search.limit;

src/queries/log/view-model.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {DomainEvent, User} from '../../types';
1+
import {StoredDomainEvent, User} from '../../types';
22

33
export interface LogSearch {
44
offset: number;
@@ -9,5 +9,5 @@ export type ViewModel = {
99
user: User;
1010
count: number;
1111
search: LogSearch;
12-
events: ReadonlyArray<DomainEvent>;
12+
events: ReadonlyArray<StoredDomainEvent>;
1313
};

0 commit comments

Comments
 (0)