Skip to content

Commit

Permalink
Added implementation of workflow pattern based on /// Inspired by htt…
Browse files Browse the repository at this point in the history
  • Loading branch information
oskardudycz committed Jan 18, 2024
1 parent c00847b commit c6b677e
Show file tree
Hide file tree
Showing 13 changed files with 721 additions and 67 deletions.
8 changes: 6 additions & 2 deletions samples/hotelManagement/.vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"editor.formatOnSave": true,

"editor.codeActionsOnSave": {
"source.fixAll.eslint": "explicit"
"source.organizeImports": "explicit",
"source.fixAll.eslint": "explicit",
"source.addMissingImports": "always"
},

"editor.tabSize": 2,
Expand All @@ -13,5 +15,7 @@
"node_modules/": true,
"dist/": true
},
"files.eol": "\n"
"files.eol": "\n",

"typescript.preferences.importModuleSpecifier": "relative"
}
26 changes: 23 additions & 3 deletions samples/hotelManagement/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion samples/hotelManagement/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
"dotenv-cli": "7.3.0",
"express": "4.18.2",
"immutable": "5.0.0-beta.4",
"mongodb": "6.3.0"
"mongodb": "6.3.0",
"ts-essentials": "9.4.1"
},
"devDependencies": {
"@types/convict": "6.1.6",
Expand Down
13 changes: 9 additions & 4 deletions samples/hotelManagement/src/core/command.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { Flavour } from './typing';

export type Command<
CommandType extends string = string,
CommandData extends Record<string, unknown> = Record<string, unknown>,
> = Readonly<{
type: Readonly<CommandType>;
data: Readonly<CommandData>;
}>;
> = Flavour<
Readonly<{
type: Readonly<CommandType>;
data: Readonly<CommandData>;
}>,
'Command'
>;
13 changes: 9 additions & 4 deletions samples/hotelManagement/src/core/event.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { Flavour } from './typing';

export type Event<
EventType extends string = string,
EventData extends Record<string, unknown> = Record<string, unknown>,
> = Readonly<{
type: Readonly<EventType>;
data: Readonly<EventData>;
}>;
> = Flavour<
Readonly<{
type: Readonly<EventType>;
data: Readonly<EventData>;
}>,
'Event'
>;
29 changes: 0 additions & 29 deletions samples/hotelManagement/src/core/processManager.ts

This file was deleted.

2 changes: 2 additions & 0 deletions samples/hotelManagement/src/core/typing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export type Brand<K, T> = K & { readonly __brand: T };
export type Flavour<K, T> = K & { readonly __brand?: T };
19 changes: 19 additions & 0 deletions samples/hotelManagement/src/core/workflow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Command } from './command';
import { Event } from './event';

/// Inspired by https://blog.bittacklr.be/the-workflow-pattern.html

export type WorkflowEvent<Output extends Command | Event> = Extract<
Output,
{ __brand?: 'Event' }
>;

export type Workflow<
Input extends Event | Command,
State,
Output extends Event | Command,
> = {
decide: (command: Input, state: State) => Output[];
evolve: (currentState: State, event: WorkflowEvent<Output>) => State;
getInitialState: () => State;
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { Map } from 'immutable';
import { Command } from '#core/command';
import { enqueue, ProcesssingResult, schedule } from '#core/processManager';
import { Map } from 'immutable';
import {
CheckOut,
GuestCheckedOut,
Expand All @@ -19,10 +18,7 @@ export type GroupCheckoutProcessManagerEvent =
| GuestCheckedOut
| GuestCheckoutFailed;

export type GroupCheckoutProcessingResult = ProcesssingResult<
CheckOut,
GroupCheckoutEvent
>;
export type GroupCheckoutProcessingResult = CheckOut | GroupCheckoutEvent;

export type InitiateGroupCheckout = Command<
'InitiateGroupCheckout',
Expand Down Expand Up @@ -68,27 +64,29 @@ export const GroupCheckoutProcessManager = (

if (state.status === 'Finished') return [];

const checkoutGuestStays = event.guestStayAccountIds.map((id) => {
return schedule<CheckOut>({
type: 'CheckOut',
data: {
guestStayAccountId: id,
now: event.initiatedAt,
groupCheckoutId: event.groupCheckoutId,
},
});
});
const checkoutGuestStays: CheckOut[] = event.guestStayAccountIds.map(
(id) => {
return {
type: 'CheckOut',
data: {
guestStayAccountId: id,
now: event.initiatedAt,
groupCheckoutId: event.groupCheckoutId,
},
};
},
);

return [
...checkoutGuestStays,
enqueue({
{
type: 'GuestCheckoutsInitiated',
data: {
groupCheckoutId: event.groupCheckoutId,
initiatedGuestStayIds: event.guestStayAccountIds,
initiatedAt: event.initiatedAt,
},
}),
},
];
}

Expand Down Expand Up @@ -137,11 +135,8 @@ export const GroupCheckoutProcessManager = (
};

return areAnyOngoingCheckouts(guestStayAccountIds)
? enqueue(finished)
: [
enqueue(finished),
enqueue(finish(groupCheckoutId, state.guestStayAccountIds, now)),
];
? finished
: [finished, finish(groupCheckoutId, state.guestStayAccountIds, now)];
}
}
};
Expand Down

0 comments on commit c6b677e

Please sign in to comment.