1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Implement requesting from renderer in main

Signed-off-by: Janne Savolainen <janne.savolainen@live.fi>
This commit is contained in:
Janne Savolainen 2022-05-27 14:48:44 +03:00
parent 2c38a65da8
commit 6c310034c2
No known key found for this signature in database
GPG Key ID: 8C6CFB2FFFE8F68A
7 changed files with 258 additions and 0 deletions

View File

@ -227,6 +227,75 @@ describe("channel", () => {
});
});
});
describe("requesting from renderer in main, given listener for channel in a renderer and application has started", () => {
let testRequestChannel: TestRequestChannel;
let requestListenerInRendererMock: AsyncFnMock<(arg: string) => string>;
let rendererDi: DiContainer;
let mainDi: DiContainer;
let requestFromChannel: RequestFromChannel;
beforeEach(async () => {
const applicationBuilder = getApplicationBuilder();
mainDi = applicationBuilder.dis.mainDi;
rendererDi = applicationBuilder.dis.rendererDi;
requestListenerInRendererMock = asyncFn();
const testChannelListenerInRendererInjectable = getInjectable({
id: "test-channel-listener-in-renderer",
instantiate: (di) => ({
channel: di.inject(testRequestChannelInjectable),
handler: requestListenerInRendererMock,
}),
injectionToken: requestChannelListenerInjectionToken,
});
rendererDi.register(testChannelListenerInRendererInjectable);
// Notice how test channel has presence in both DIs, being from common
mainDi.register(testRequestChannelInjectable);
rendererDi.register(testRequestChannelInjectable);
testRequestChannel = mainDi.inject(testRequestChannelInjectable);
requestFromChannel = mainDi.inject(
requestFromChannelInjectionToken,
);
await applicationBuilder.render();
});
describe("when requesting from channel", () => {
let actualPromise: Promise<string>;
beforeEach(() => {
actualPromise = requestFromChannel(testRequestChannel, "some-request");
});
it("triggers listener in renderer", () => {
expect(requestListenerInRendererMock).toHaveBeenCalledWith("some-request");
});
it("does not resolve yet", async () => {
const promiseStatus = await getPromiseStatus(actualPromise);
expect(promiseStatus.fulfilled).toBe(false);
});
it("when renderer resolves with response, resolves with response", async () => {
await requestListenerInRendererMock.resolve("some-response");
const actual = await actualPromise;
expect(actual).toBe("some-response");
});
});
});
});
const testMessageChannelInjectable = getInjectable({

View File

@ -0,0 +1,21 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { MessageChannel } from "../message-channel-injection-token";
import { messageChannelInjectionToken } from "../message-channel-injection-token";
export type RequestFromChannelForMainRequestChannel = MessageChannel<{ channelId: string; request: any }>;
const requestFromChannelForMainRequestChannelInjectable = getInjectable({
id: "request-from-channel-for-main-request-channel",
instantiate: (): RequestFromChannelForMainRequestChannel => ({
id: "request-from-channel-for-main-request-channel",
}),
injectionToken: messageChannelInjectionToken,
});
export default requestFromChannelForMainRequestChannelInjectable;

View File

@ -0,0 +1,21 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { MessageChannel } from "../message-channel-injection-token";
import { messageChannelInjectionToken } from "../message-channel-injection-token";
export type RequestFromChannelForMainResponseChannel = MessageChannel<{ channelId: string; response: any }>;
const requestFromChannelForMainResponseChannelInjectable = getInjectable({
id: "request-from-channel-for-main-response-channel",
instantiate: (): RequestFromChannelForMainResponseChannel => ({
id: "request-from-channel-for-main-response-channel",
}),
injectionToken: messageChannelInjectionToken,
});
export default requestFromChannelForMainResponseChannelInjectable;

View File

@ -0,0 +1,36 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { MessageChannelListener } from "../../../common/channel/message-channel-listener-injection-token";
import { messageChannelListenerInjectionToken } from "../../../common/channel/message-channel-listener-injection-token";
import type { RequestFromChannelForMainResponseChannel } from "../../../common/channel/request-from-channel-for-main/request-from-channel-for-main-response-channel.injectable";
import requestFromChannelForMainResponseChannelInjectable from "../../../common/channel/request-from-channel-for-main/request-from-channel-for-main-response-channel.injectable";
import requestFromChannelForMainResponsePromiseInjectable from "./request-from-channel-for-main-response-promise.injectable";
const requestFromChannelForMainResponseChannelListenerInjectable =
getInjectable({
id: "request-from-channel-for-main-response-channel-listener",
instantiate: (
di,
): MessageChannelListener<RequestFromChannelForMainResponseChannel> => {
const channel = di.inject(requestFromChannelForMainResponseChannelInjectable);
const getResponsePromise = (channelId: string) => di.inject(requestFromChannelForMainResponsePromiseInjectable, channelId);
return {
channel,
handler: ({ channelId, response }) => {
const responsePromise = getResponsePromise(channelId);
responsePromise.resolve(response);
},
};
},
injectionToken: messageChannelListenerInjectionToken,
});
export default requestFromChannelForMainResponseChannelListenerInjectable;

View File

@ -0,0 +1,33 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
const requestFromChannelForMainResponsePromiseInjectable = getInjectable({
id: "request-from-channel-for-main-response-promise",
instantiate: (di, channelId: string) => {
void channelId;
let resolve: (response: boolean) => void;
const promise = new Promise<boolean>(_resolve => {
resolve = _resolve;
});
return ({
promise,
resolve: (response: boolean) => {
resolve(response);
},
});
},
lifecycle: lifecycleEnum.keyedSingleton({
getInstanceKey: (di, channelId: string) => channelId,
}),
});
export default requestFromChannelForMainResponsePromiseInjectable;

View File

@ -0,0 +1,32 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import { requestFromChannelInjectionToken } from "../../../common/channel/request-from-channel-injection-token";
import { messageToChannelInjectionToken } from "../../../common/channel/message-to-channel-injection-token";
import requestFromChannelForMainRequestChannelInjectable from "../../../common/channel/request-from-channel-for-main/request-from-channel-for-main-request-channel.injectable";
import requestFromChannelForMainResponsePromiseInjectable from "./request-from-channel-for-main-response-promise.injectable";
const requestFromChannelInjectable = getInjectable({
id: "request-from-channel",
instantiate: (di) => {
const messageToChannel = di.inject(messageToChannelInjectionToken);
const requestFromChannelForMainMessageChannel = di.inject(requestFromChannelForMainRequestChannelInjectable);
const getResponsePromise = (channelId: string) => di.inject(requestFromChannelForMainResponsePromiseInjectable, channelId);
return async (channel, ...[request]) => {
const responsePromise = getResponsePromise(channel.id);
messageToChannel(requestFromChannelForMainMessageChannel, { channelId: channel.id, request });
return await responsePromise.promise;
};
},
injectionToken: requestFromChannelInjectionToken,
});
export default requestFromChannelInjectable;

View File

@ -0,0 +1,46 @@
/**
* Copyright (c) OpenLens Authors. All rights reserved.
* Licensed under MIT License. See LICENSE in root directory for more information.
*/
import { getInjectable } from "@ogre-tools/injectable";
import type { MessageChannelListener } from "../../../common/channel/message-channel-listener-injection-token";
import { messageChannelListenerInjectionToken } from "../../../common/channel/message-channel-listener-injection-token";
import type { RequestFromChannelForMainRequestChannel } from "../../../common/channel/request-from-channel-for-main/request-from-channel-for-main-request-channel.injectable";
import requestFromChannelForMainRequestChannelInjectable from "../../../common/channel/request-from-channel-for-main/request-from-channel-for-main-request-channel.injectable";
import { requestChannelListenerInjectionToken } from "../../../common/channel/request-channel-listener-injection-token";
import requestFromChannelForMainResponseChannelInjectable from "../../../common/channel/request-from-channel-for-main/request-from-channel-for-main-response-channel.injectable";
import { messageToChannelInjectionToken } from "../../../common/channel/message-to-channel-injection-token";
const requestFromChannelForMainMessageChannelListenerInjectable = getInjectable(
{
id: "request-from-channel-for-main-message-channel-listener",
instantiate: (di): MessageChannelListener<RequestFromChannelForMainRequestChannel> => {
const requestChannel = di.inject(requestFromChannelForMainRequestChannelInjectable);
const responseChannel = di.inject(requestFromChannelForMainResponseChannelInjectable);
const messageToChannel = di.inject(messageToChannelInjectionToken);
const listeners = di.injectMany(requestChannelListenerInjectionToken);
return {
channel: requestChannel,
handler: async ({ channelId, request }) => {
const targetListener = listeners.find(listener => listener.channel.id === channelId);
if (targetListener) {
const response = await targetListener.handler(request);
messageToChannel(responseChannel, {
channelId,
response,
});
}
},
};
},
injectionToken: messageChannelListenerInjectionToken,
},
);
export default requestFromChannelForMainMessageChannelListenerInjectable;