Intergrate ServerAddOn with PluginManager

Reviewed By: lblasa

Differential Revision: D34042338

fbshipit-source-id: 2ae3992738e647075f19c4dba0ebfb01e6c12b8f
This commit is contained in:
Andrey Goncharov
2022-02-28 03:50:34 -08:00
committed by Facebook GitHub Bot
parent 016299b374
commit a60865f0be
3 changed files with 41 additions and 4 deletions

View File

@@ -421,7 +421,7 @@ export class FlipperServerImpl implements FlipperServer {
'plugin-source': (path) => this.pluginManager.loadSource(path), 'plugin-source': (path) => this.pluginManager.loadSource(path),
'plugins-server-add-on-start': (pluginName) => 'plugins-server-add-on-start': (pluginName) =>
this.pluginManager.startServerAddOn(pluginName), this.pluginManager.startServerAddOn(pluginName),
'plugins-server-add-on-stop': (pluginName) => 'plugins-server-add-on-stop': async (pluginName) =>
this.pluginManager.stopServerAddOn(pluginName), this.pluginManager.stopServerAddOn(pluginName),
'doctor-get-healthchecks': getHealthChecks, 'doctor-get-healthchecks': getHealthChecks,
'doctor-run-healthcheck': runHealthcheck, 'doctor-run-healthcheck': runHealthcheck,

View File

@@ -30,6 +30,7 @@ import {
getInstalledPlugin, getInstalledPlugin,
installPluginFromNpm, installPluginFromNpm,
} from 'flipper-plugin-lib'; } from 'flipper-plugin-lib';
import {ServerAddOn} from './ServerAddOn';
const maxInstalledPluginVersionsToKeep = 2; const maxInstalledPluginVersionsToKeep = 2;
@@ -43,6 +44,8 @@ const getTempDirName = promisify(tmp.dir) as (
) => Promise<string>; ) => Promise<string>;
export class PluginManager { export class PluginManager {
private readonly serverAddOns = new Map<string, ServerAddOn>();
async start() { async start() {
// This needn't happen immediately and is (light) I/O work. // This needn't happen immediately and is (light) I/O work.
setTimeout(() => { setTimeout(() => {
@@ -154,9 +157,32 @@ export class PluginManager {
async startServerAddOn(pluginName: string) { async startServerAddOn(pluginName: string) {
console.debug('PluginManager.startServerAddOn', pluginName); console.debug('PluginManager.startServerAddOn', pluginName);
// TODO: Get owner from websocket connection ID
const fakeOwner = 'test';
const existingServerAddOn = this.serverAddOns.get(pluginName);
if (existingServerAddOn) {
console.debug(
'PluginManager.startServerAddOn -> already started, adding an owner',
pluginName,
fakeOwner,
);
existingServerAddOn.addOwner(fakeOwner);
return;
} }
async stopServerAddOn(pluginName: string) { const newServerAddOn = await ServerAddOn.start(pluginName, fakeOwner);
this.serverAddOns.set(pluginName, newServerAddOn);
}
stopServerAddOn(pluginName: string) {
console.debug('PluginManager.stopServerAddOn', pluginName); console.debug('PluginManager.stopServerAddOn', pluginName);
const serverAddOn = this.serverAddOns.get(pluginName);
if (!serverAddOn) {
console.debug('PluginManager.stopServerAddOn -> not started', pluginName);
return;
}
// TODO: Get owner from websocket connection ID
const fakeOwner = 'test';
serverAddOn.removeOwner(fakeOwner);
} }
} }

View File

@@ -15,6 +15,13 @@ interface ServerAddOnModule {
serverAddOn?: () => Promise<ServerAddOnCleanup>; serverAddOn?: () => Promise<ServerAddOnCleanup>;
} }
// TODO: Metro does not like dynamic requires. Figure out how to properly configure metro to handle them.
// https://github.com/webpack/webpack/issues/4175#issuecomment-323023911
function requireDynamically(path: string) {
// eslint-disable-next-line no-eval
return eval(`require('${path}');`); // Ensure Metro does not analyze the require statement
}
// TODO: Fix potential race conditions when starting/stopping concurrently // TODO: Fix potential race conditions when starting/stopping concurrently
export class ServerAddOn { export class ServerAddOn {
private owners: Set<string>; private owners: Set<string>;
@@ -30,7 +37,7 @@ export class ServerAddOn {
static async start(path: string, initialOwner: string): Promise<ServerAddOn> { static async start(path: string, initialOwner: string): Promise<ServerAddOn> {
console.info('ServerAddOn.start', path); console.info('ServerAddOn.start', path);
const {serverAddOn} = require(path) as ServerAddOnModule; const {serverAddOn} = requireDynamically(path) as ServerAddOnModule;
assertNotNull(serverAddOn); assertNotNull(serverAddOn);
assert( assert(
typeof serverAddOn === 'function', typeof serverAddOn === 'function',
@@ -66,6 +73,10 @@ export class ServerAddOn {
private async stop() { private async stop() {
console.info('ServerAddOn.stop', this.path); console.info('ServerAddOn.stop', this.path);
try {
await this.cleanup(); await this.cleanup();
} catch (e) {
console.error('ServerAddOn.stop -> failed to clean up', this.path);
}
} }
} }