Make client -> device connection synchronous

Summary:
devices not always being readily available is causes a lot of complication in the api,
figured to resolve devices first before construction clients,
since clients not attached to a device are shown uncategorized anyway, making them practically un-interactable.
For more background info, see following chat.

{F344388883}

This diff will make it possible to only expose a synchronous api in Sandy

n.b. didn't update Navigation plugin, as that is done in a next diff

Reviewed By: jknoxville

Differential Revision: D24858332

fbshipit-source-id: 8339f831fbbc9c219add56a199364fde67adafc7
This commit is contained in:
Michel Weststrate
2020-11-11 07:57:14 -08:00
committed by Facebook GitHub Bot
parent fd8065eb7a
commit 9b4e7e873c
9 changed files with 124 additions and 102 deletions

View File

@@ -21,7 +21,7 @@ import {setPluginState} from './reducers/pluginStates';
import {Payload, ConnectionStatus} from 'rsocket-types';
import {Flowable, Single} from 'rsocket-flowable';
import {performance} from 'perf_hooks';
import {reportPlatformFailures, reportPluginFailures} from './utils/metrics';
import {reportPluginFailures} from './utils/metrics';
import {notNull} from './utils/typeUtils';
import {default as isProduction} from './utils/isProduction';
import {registerPlugins} from './reducers/plugins';
@@ -33,7 +33,6 @@ import {
defaultEnabledBackgroundPlugins,
} from './utils/pluginUtils';
import {processMessagesLater} from './utils/messageQueue';
import {sideEffect} from './utils/sideEffect';
import {emitBytesReceived} from './dispatcher/tracking';
import {debounce} from 'lodash';
import {batch} from 'react-redux';
@@ -134,11 +133,14 @@ export default class Client extends EventEmitter {
connection: FlipperClientConnection<any, any> | null | undefined;
store: Store;
activePlugins: Set<string>;
/**
* @deprecated
* use plugin.deviceSync instead
*/
device: Promise<BaseDevice>;
_deviceResolve: (device: BaseDevice) => void = (_) => {};
_deviceResolved: BaseDevice | undefined;
deviceSync: BaseDevice;
logger: Logger;
lastSeenDeviceList: Array<BaseDevice>;
broadcastCallbacks: Map<string, Map<string, Set<Function>>>;
messageBuffer: Record<
string /*pluginKey*/,
@@ -168,8 +170,8 @@ export default class Client extends EventEmitter {
conn: FlipperClientConnection<any, any> | null | undefined,
logger: Logger,
store: Store,
plugins?: Plugins | null | undefined,
device?: BaseDevice,
plugins: Plugins | null | undefined,
device: BaseDevice,
) {
super();
this.connected = true;
@@ -185,17 +187,9 @@ export default class Client extends EventEmitter {
this.broadcastCallbacks = new Map();
this.requestCallbacks = new Map();
this.activePlugins = new Set();
this.lastSeenDeviceList = [];
this.device = device
? Promise.resolve(device)
: new Promise((resolve, _reject) => {
this._deviceResolve = resolve;
});
if (device != null) {
this._deviceResolved = device;
}
this.device = Promise.resolve(device);
this.deviceSync = device;
const client = this;
if (conn) {
@@ -215,58 +209,6 @@ export default class Client extends EventEmitter {
}
}
/* All clients should have a corresponding Device in the store.
However, clients can connect before a device is registered, so wait a
while for the device to be registered if it isn't already. */
async setMatchingDevice(): Promise<void> {
return reportPlatformFailures(
new Promise<BaseDevice>((resolve, reject) => {
let unsubscribe: () => void = () => {};
const device = this.store
.getState()
.connections.devices.find(
(device) => device.serial === this.query.device_id,
);
if (device) {
this._deviceResolved = device;
resolve(device);
return;
}
const timeout = setTimeout(() => {
unsubscribe();
const error = `Timed out waiting for device for client ${this.id}`;
console.error(error);
reject(error);
}, 5000);
unsubscribe = sideEffect(
this.store,
{name: 'waitForDevice', throttleMs: 100},
(state) => state.connections.devices,
(newDeviceList) => {
if (newDeviceList === this.lastSeenDeviceList) {
return;
}
this.lastSeenDeviceList = newDeviceList;
const matchingDevice = newDeviceList.find(
(device) => device.serial === this.query.device_id,
);
if (matchingDevice) {
clearTimeout(timeout);
resolve(matchingDevice);
unsubscribe();
}
},
);
}),
'client-setMatchingDevice',
).then((device) => {
this._deviceResolved = device;
this._deviceResolve(device);
});
}
supportsPlugin(pluginId: string): boolean {
return this.plugins.includes(pluginId);
}
@@ -289,7 +231,6 @@ export default class Client extends EventEmitter {
}
async init() {
this.setMatchingDevice();
await this.loadPlugins();
// this starts all sandy enabled plugins
this.plugins.forEach((pluginId) =>
@@ -434,20 +375,12 @@ export default class Client extends EventEmitter {
this.emit('plugins-change');
}
/**
* @deprecated
* use deviceSync.serial
*/
async deviceSerial(): Promise<string> {
try {
const device = await this.device;
if (!device) {
console.error('Using "" for deviceId device is not ready');
return '';
}
return device.serial;
} catch (e) {
console.error(
'Using "" for deviceId because client has no matching device',
);
return '';
}
return this.deviceSync.serial;
}
onMessage(msg: string) {
@@ -478,7 +411,7 @@ export default class Client extends EventEmitter {
flipperMessagesClientPlugin.isConnected()
) {
flipperMessagesClientPlugin.newMessage({
device: this._deviceResolved?.displayTitle(),
device: this.deviceSync?.displayTitle(),
app: this.query.app,
flipperInternalMethod: method,
plugin: data.params?.api,
@@ -497,7 +430,7 @@ export default class Client extends EventEmitter {
}: ${error.message} + \nDevice Stack Trace: ${error.stacktrace}`,
'deviceError',
);
this.device.then((device) => handleError(this.store, device, error));
handleError(this.store, this.deviceSync, error);
} else if (method === 'refreshPlugins') {
this.refreshPlugins();
} else if (method === 'execute') {
@@ -576,7 +509,7 @@ export default class Client extends EventEmitter {
reject(data.error);
const {error} = data;
if (error) {
this.device.then((device) => handleError(this.store, device, error));
handleError(this.store, this.deviceSync, error);
}
} else {
// ???
@@ -670,7 +603,7 @@ export default class Client extends EventEmitter {
if (flipperMessagesClientPlugin.isConnected()) {
flipperMessagesClientPlugin.newMessage({
device: this._deviceResolved?.displayTitle(),
device: this.deviceSync?.displayTitle(),
app: this.query.app,
flipperInternalMethod: method,
payload: response,
@@ -692,7 +625,7 @@ export default class Client extends EventEmitter {
if (flipperMessagesClientPlugin.isConnected()) {
flipperMessagesClientPlugin.newMessage({
device: this._deviceResolved?.displayTitle(),
device: this.deviceSync?.displayTitle(),
app: this.query.app,
flipperInternalMethod: method,
plugin: params?.api,
@@ -776,7 +709,7 @@ export default class Client extends EventEmitter {
if (flipperMessagesClientPlugin.isConnected()) {
flipperMessagesClientPlugin.newMessage({
device: this._deviceResolved?.displayTitle(),
device: this.deviceSync?.displayTitle(),
app: this.query.app,
flipperInternalMethod: method,
payload: params,