-
Notifications
You must be signed in to change notification settings - Fork 135
/
Copy pathAbstractMessaging.ts
105 lines (94 loc) · 2.93 KB
/
AbstractMessaging.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
import { AgentError, AppIdentifier } from '@finos/fdc3-standard';
import { Messaging } from '../Messaging';
import { RegisterableListener } from '../listeners/RegisterableListener';
import {
AgentResponseMessage,
AppRequestMessage,
WebConnectionProtocol6Goodbye,
} from '@finos/fdc3-schema/dist/generated/api/BrowserTypes';
import { Logger } from '../util/Logger';
export abstract class AbstractMessaging implements Messaging {
private appIdentifier: AppIdentifier;
abstract createUUID(): string;
abstract post(message: AppRequestMessage | WebConnectionProtocol6Goodbye): Promise<void>;
abstract register(l: RegisterableListener): void;
abstract unregister(id: string): void;
abstract createMeta(): AppRequestMessage['meta'];
constructor(appIdentifier: AppIdentifier) {
this.appIdentifier = appIdentifier;
}
waitFor<X extends AgentResponseMessage>(
filter: (m: X) => boolean,
timeoutMs?: number,
timeoutErrorMessage?: string
): Promise<X> {
const id = this.createUUID();
return new Promise<X>((resolve, reject) => {
let done = false;
let timeout: NodeJS.Timeout | null = null;
const l: RegisterableListener = {
id,
filter: filter,
action: m => {
Logger.debug('Received from DesktopAgent: ', m);
done = true;
this.unregister(id);
if (timeout) {
clearTimeout(timeout);
}
resolve(m as X);
},
register: async () => {
this.register(l);
},
unsubscribe: async () => {
this.unregister(id);
},
};
this.register(l);
if (timeoutMs) {
timeout = setTimeout(() => {
this.unregister(id);
if (!done) {
Logger.error(
`waitFor rejecting after ${timeoutMs}ms at ${new Date().toISOString()} with ${timeoutErrorMessage}`
);
reject(new Error(timeoutErrorMessage));
}
}, timeoutMs);
}
});
}
async exchange<X extends AgentResponseMessage>(
message: AppRequestMessage,
expectedTypeName: AgentResponseMessage['type'],
timeoutMs: number
): Promise<X> {
const prom = this.waitFor<X>(
m => {
return m.type == expectedTypeName && m.meta.requestUuid == message.meta.requestUuid;
},
timeoutMs,
AgentError.ApiTimeout
);
Logger.debug('Sending to DesktopAgent: ', message);
this.post(message);
try {
const out: X = await prom;
if (out?.payload?.error) {
throw new Error(out.payload.error);
} else {
return out;
}
} catch (error) {
if ((error as Error).message == AgentError.ApiTimeout) {
Logger.error(`Timed-out while waiting for ${expectedTypeName} with requestUuid ${message.meta.requestUuid}`);
}
throw error;
}
}
getAppIdentifier(): AppIdentifier {
return this.appIdentifier;
}
abstract disconnect(): Promise<void>;
}