Reviewed By: mweststrate Differential Revision: D34301593 fbshipit-source-id: 2950de8a8567318cd3e87eff176657df5ba8fd1b
148 lines
3.7 KiB
TypeScript
148 lines
3.7 KiB
TypeScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @format
|
|
*/
|
|
|
|
import {
|
|
ClientResponseType,
|
|
ExecuteMessage,
|
|
FlipperServerForServerAddOn,
|
|
ServerAddOnStartDetails,
|
|
} from 'flipper-common';
|
|
import {assertNotNull} from '../comms/Utilities';
|
|
import {StateMachine} from '../utils/StateMachine';
|
|
import {ServerAddOn} from './ServerAddOn';
|
|
|
|
type TState =
|
|
| 'inactive'
|
|
| 'starting'
|
|
| 'active'
|
|
| 'fatal'
|
|
| 'stopping'
|
|
| 'zombie';
|
|
|
|
export class ServerAddOnManager {
|
|
public readonly state = new StateMachine<TState, 'fatal'>('inactive');
|
|
private _serverAddOn?: ServerAddOn;
|
|
constructor(
|
|
public readonly pluginName: string,
|
|
details: ServerAddOnStartDetails,
|
|
initialOwner: string,
|
|
flipperServer: FlipperServerForServerAddOn,
|
|
) {
|
|
this.startServerAddOn(details, initialOwner, flipperServer);
|
|
}
|
|
|
|
sendExpectResponse(message: ExecuteMessage): Promise<ClientResponseType> {
|
|
if (!this.state.is('active')) {
|
|
console.info(
|
|
'StateAddOnManager.sendExpectResponse -> error: server add-on is not active, Current state:',
|
|
this.state.currentState,
|
|
);
|
|
throw new Error(
|
|
'StateAddOnManager.sendExpectResponse -> error: server add-on is not active',
|
|
);
|
|
}
|
|
assertNotNull(
|
|
this._serverAddOn,
|
|
'StateAddOnManager.sendExpectResponse -> _serverAddOn is undefined',
|
|
);
|
|
return this._serverAddOn.connection.sendExpectResponse(message);
|
|
}
|
|
|
|
async addOwner(owner: string) {
|
|
if (this.state.is('starting')) {
|
|
await this.state.wait(['active', 'fatal']);
|
|
}
|
|
|
|
if (!this.state.is('active')) {
|
|
console.info(
|
|
'StateAddOnManager.addOwner -> error: server add-on is not active, Current state:',
|
|
this.state.currentState,
|
|
);
|
|
throw new Error(
|
|
'StateAddOnManager.addOwner -> error: server add-on is not active',
|
|
);
|
|
}
|
|
assertNotNull(
|
|
this._serverAddOn,
|
|
'StateAddOnManager.addOwner -> _serverAddOn is undefined',
|
|
);
|
|
|
|
this._serverAddOn.addOwner(owner);
|
|
}
|
|
|
|
async removeOwner(owner: string) {
|
|
if (this.state.is(['stopping', 'inactive'])) {
|
|
return this.state.wait(['zombie', 'inactive']);
|
|
}
|
|
|
|
if (this.state.is('starting')) {
|
|
await this.state.wait(['active', 'fatal']);
|
|
}
|
|
|
|
if (!this.state.is('active')) {
|
|
console.debug(
|
|
'StateAddOnManager.removeOwner -> error: server add-on failed to start, Current state:',
|
|
this.state.currentState,
|
|
);
|
|
return;
|
|
}
|
|
|
|
assertNotNull(
|
|
this._serverAddOn,
|
|
'StateAddOnManager.addOwner -> _serverAddOn is undefined',
|
|
);
|
|
|
|
const stopping = this._serverAddOn.removeOwner(owner);
|
|
|
|
if (stopping) {
|
|
this.state.set('stopping');
|
|
try {
|
|
await stopping;
|
|
this.state.set('inactive');
|
|
} catch (e) {
|
|
this.state.set('zombie');
|
|
console.error(
|
|
'ServerAddOnManager.removeOwner -> server add-on failed to clean up',
|
|
this.pluginName,
|
|
e,
|
|
);
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
|
|
private async startServerAddOn(
|
|
details: ServerAddOnStartDetails,
|
|
initialOwner: string,
|
|
flipperServer: FlipperServerForServerAddOn,
|
|
) {
|
|
try {
|
|
this.state.set('starting');
|
|
|
|
this._serverAddOn = await ServerAddOn.start(
|
|
this.pluginName,
|
|
details,
|
|
initialOwner,
|
|
flipperServer,
|
|
);
|
|
|
|
this.state.set('active');
|
|
} catch (e) {
|
|
this.state.set('fatal', e);
|
|
console.error(
|
|
'StateAddOnManager.startServerAddOn -> error',
|
|
this.pluginName,
|
|
details,
|
|
initialOwner,
|
|
e,
|
|
);
|
|
}
|
|
}
|
|
}
|