refactor(simulator): factor out common helpers
[e-mobility-charging-stations-simulator.git] / src / charging-station / broadcast-channel / UIServiceWorkerBroadcastChannel.ts
CommitLineData
4c3c0d59 1import { WorkerBroadcastChannel } from './WorkerBroadcastChannel';
268a74bb
JB
2import {
3 type BroadcastChannelResponse,
4 type BroadcastChannelResponsePayload,
5 type MessageEvent,
6 type ResponsePayload,
7 ResponseStatus,
7671fa0b
JB
8} from '../../types';
9import { Utils, logger } from '../../utils';
10import type { AbstractUIService } from '../ui-server/ui-services/AbstractUIService';
6c8f5d90
JB
11
12const moduleName = 'UIServiceWorkerBroadcastChannel';
13
0d2cec76
JB
14type Responses = {
15 responsesExpected: number;
16 responsesReceived: number;
17 responses: BroadcastChannelResponsePayload[];
18};
19
268a74bb 20export class UIServiceWorkerBroadcastChannel extends WorkerBroadcastChannel {
0d2cec76 21 private readonly uiService: AbstractUIService;
53870cff 22 private readonly responses: Map<string, Responses>;
6c8f5d90
JB
23
24 constructor(uiService: AbstractUIService) {
25 super();
26 this.uiService = uiService;
27 this.onmessage = this.responseHandler.bind(this) as (message: MessageEvent) => void;
28 this.onmessageerror = this.messageErrorHandler.bind(this) as (message: MessageEvent) => void;
0d2cec76 29 this.responses = new Map<string, Responses>();
6c8f5d90
JB
30 }
31
32 private responseHandler(messageEvent: MessageEvent): void {
5dea4c94
JB
33 const validatedMessageEvent = this.validateMessageEvent(messageEvent);
34 if (validatedMessageEvent === false) {
6c8f5d90
JB
35 return;
36 }
5dea4c94
JB
37 if (this.isRequest(validatedMessageEvent.data) === true) {
38 return;
39 }
40 const [uuid, responsePayload] = validatedMessageEvent.data as BroadcastChannelResponse;
0d2cec76
JB
41 if (this.responses.has(uuid) === false) {
42 this.responses.set(uuid, {
43 responsesExpected: this.uiService.getBroadcastChannelExpectedResponses(uuid),
44 responsesReceived: 1,
45 responses: [responsePayload],
46 });
47 } else if (
6d9876e7 48 this.responses.get(uuid)?.responsesReceived <= this.responses.get(uuid)?.responsesExpected
0d2cec76
JB
49 ) {
50 this.responses.get(uuid).responsesReceived++;
72092cfc 51 this.responses.get(uuid)?.responses.push(responsePayload);
6d9876e7
JB
52 }
53 if (
54 this.responses.get(uuid)?.responsesReceived === this.responses.get(uuid)?.responsesExpected
0d2cec76 55 ) {
0d2cec76
JB
56 this.uiService.sendResponse(uuid, this.buildResponsePayload(uuid));
57 this.responses.delete(uuid);
58 this.uiService.deleteBroadcastChannelRequest(uuid);
59 }
60 }
6c8f5d90 61
0d2cec76 62 private buildResponsePayload(uuid: string): ResponsePayload {
c56450e3
JB
63 const responsesStatus =
64 this.responses
65 .get(uuid)
66 ?.responses.every(({ status }) => status === ResponseStatus.SUCCESS) === true
67 ? ResponseStatus.SUCCESS
68 : ResponseStatus.FAILURE;
0d2cec76
JB
69 return {
70 status: responsesStatus,
71 hashIdsSucceeded: this.responses
72 .get(uuid)
9bb1159e 73 ?.responses.filter(({ hashId }) => !Utils.isNullOrUndefined(hashId))
3ce0201e 74 .map(({ status, hashId }) => {
0d2cec76
JB
75 if (status === ResponseStatus.SUCCESS) {
76 return hashId;
77 }
3ce0201e 78 }),
0d2cec76
JB
79 ...(responsesStatus === ResponseStatus.FAILURE && {
80 hashIdsFailed: this.responses
81 .get(uuid)
9bb1159e 82 ?.responses.filter(({ hashId }) => !Utils.isNullOrUndefined(hashId))
3ce0201e 83 .map(({ status, hashId }) => {
0d2cec76
JB
84 if (status === ResponseStatus.FAILURE) {
85 return hashId;
86 }
3ce0201e 87 }),
0d2cec76 88 }),
f53c88d0
JB
89 ...(responsesStatus === ResponseStatus.FAILURE && {
90 responsesFailed: this.responses
91 .get(uuid)
9bb1159e 92 ?.responses.filter((response) => !Utils.isNullOrUndefined(response))
3ce0201e 93 .map((response) => {
f53c88d0
JB
94 if (response.status === ResponseStatus.FAILURE) {
95 return response;
96 }
3ce0201e 97 }),
f53c88d0 98 }),
0d2cec76 99 };
6c8f5d90
JB
100 }
101
102 private messageErrorHandler(messageEvent: MessageEvent): void {
103 logger.error(
104 `${this.uiService.logPrefix(moduleName, 'messageErrorHandler')} Error at handling message:`,
5083d31a 105 messageEvent
6c8f5d90
JB
106 );
107 }
108}