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