Reload single plugin on auto-update

Summary: Implemented a way for re-loading single plugin on auto-update. This make it possible to apply update without full Flipper restart.

Reviewed By: mweststrate

Differential Revision: D23729972

fbshipit-source-id: ed30f7cde5a0537945db0b5bb6969ae8fde42cb6
This commit is contained in:
Anton Nikolaev
2020-09-28 02:50:10 -07:00
committed by Facebook GitHub Bot
parent 5e979403a0
commit 0982dc06a0
9 changed files with 204 additions and 47 deletions

View File

@@ -15,7 +15,11 @@ import produce from 'immer';
import {
defaultEnabledBackgroundPlugins,
getPluginKey,
isDevicePluginDefinition,
} from './utils/pluginUtils';
import Client from './Client';
import {PluginDefinition} from './plugin';
import {deconstructPluginKey} from './utils/clientUtils';
export const store: Store = createStore<StoreState, Actions, any, any>(
rootReducer,
@@ -48,35 +52,59 @@ export function rootReducer(
plugins.push(selectedPlugin);
// enabling a plugin on one device enables it on all...
clients.forEach((client) => {
// sandy plugin? initialize it
client.startPluginIfNeeded(plugin, true);
// background plugin? connect it needed
if (
!defaultEnabledBackgroundPlugins.includes(selectedPlugin) &&
client?.isBackgroundPlugin(selectedPlugin)
) {
client.initPlugin(selectedPlugin);
}
startPlugin(client, plugin);
});
} else {
plugins.splice(idx, 1);
// enabling a plugin on one device disables it on all...
clients.forEach((client) => {
// disconnect background plugins
if (
!defaultEnabledBackgroundPlugins.includes(selectedPlugin) &&
client?.isBackgroundPlugin(selectedPlugin)
) {
client.deinitPlugin(selectedPlugin);
}
// stop sandy plugins
client.stopPluginIfNeeded(plugin.id);
delete draft.pluginMessageQueue[
getPluginKey(client.id, {serial: client.query.device_id}, plugin.id)
];
stopPlugin(client, plugin.id);
const pluginKey = getPluginKey(
client.id,
{serial: client.query.device_id},
plugin.id,
);
delete draft.pluginMessageQueue[pluginKey];
});
}
});
} else if (action.type === 'UPDATE_PLUGIN' && state) {
const plugin: PluginDefinition = action.payload;
const clients = state.connections.clients;
return produce(state, (draft) => {
const clientsWithEnabledPlugin = clients.filter((c) => {
return (
c.supportsPlugin(plugin.id) &&
state.connections.userStarredPlugins[c.query.app]?.includes(plugin.id)
);
});
// stop plugin for each client where it is enabled
clientsWithEnabledPlugin.forEach((client) => {
stopPlugin(client, plugin.id, true);
delete draft.pluginMessageQueue[
getPluginKey(client.id, {serial: client.query.device_id}, plugin.id)
];
});
// cleanup classic plugin state
Object.keys(draft.pluginStates).forEach((pluginKey) => {
const pluginKeyParts = deconstructPluginKey(pluginKey);
if (pluginKeyParts.pluginName === plugin.id) {
delete draft.pluginStates[pluginKey];
}
});
// update plugin definition
const {devicePlugins, clientPlugins} = draft.plugins;
const p = action.payload;
if (isDevicePluginDefinition(p)) {
devicePlugins.set(p.id, p);
} else {
clientPlugins.set(p.id, p);
}
// start plugin for each client
clientsWithEnabledPlugin.forEach((client) => {
startPlugin(client, plugin, true);
});
});
}
// otherwise
@@ -88,3 +116,36 @@ if (!isProduction()) {
// @ts-ignore
window.flipperStore = store;
}
function stopPlugin(
client: Client,
pluginId: string,
forceInitBackgroundPlugin: boolean = false,
): boolean {
if (
(forceInitBackgroundPlugin ||
!defaultEnabledBackgroundPlugins.includes(pluginId)) &&
client?.isBackgroundPlugin(pluginId)
) {
client.deinitPlugin(pluginId);
}
// stop sandy plugins
client.stopPluginIfNeeded(pluginId);
return true;
}
function startPlugin(
client: Client,
plugin: PluginDefinition,
forceInitBackgroundPlugin: boolean = false,
) {
client.startPluginIfNeeded(plugin, true);
// background plugin? connect it needed
if (
(forceInitBackgroundPlugin ||
!defaultEnabledBackgroundPlugins.includes(plugin.id)) &&
client?.isBackgroundPlugin(plugin.id)
) {
client.initPlugin(plugin.id);
}
}