From 136dfb12a1a3fb1878ef94863ea448dca8719e01 Mon Sep 17 00:00:00 2001 From: Koushik Dutta Date: Sat, 20 Nov 2021 22:33:27 -0800 Subject: [PATCH] server: fix race condition on state reporting --- server/src/plugin/plugin-host-api.ts | 1 + server/src/plugin/plugin-host.ts | 29 +++++++++++++++------------- 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/server/src/plugin/plugin-host-api.ts b/server/src/plugin/plugin-host-api.ts index 14d271ef0..ca8caa7f5 100644 --- a/server/src/plugin/plugin-host-api.ts +++ b/server/src/plugin/plugin-host-api.ts @@ -21,6 +21,7 @@ export class PluginHostAPI extends PluginAPIManagedListeners implements PluginAP 'setDeviceProperty', 'deliverPush', 'requestRestart', + "setState", ]; restartDebounced = debounce(async () => { diff --git a/server/src/plugin/plugin-host.ts b/server/src/plugin/plugin-host.ts index 3c879e6f9..d329541b8 100644 --- a/server/src/plugin/plugin-host.ts +++ b/server/src/plugin/plugin-host.ts @@ -648,6 +648,10 @@ export function startPluginClusterWorker() { }) } +/** + * Warning: do not await in any of these methods unless necessary, otherwise + * execution order of state reporting may fail. + */ class LazyRemote implements PluginRemote { remote: PluginRemote; @@ -658,17 +662,6 @@ class LazyRemote implements PluginRemote { })(); } - async ensureRemote() { - try { - if (!this.remote) - await this.remoteReadyPromise; - } - catch (e) { - return; - } - return true; - } - async loadZip(packageJson: any, zipData: Buffer, options?: PluginRemoteLoadZipOptions): Promise { if (!this.remote) await this.remoteReadyPromise; @@ -685,13 +678,23 @@ class LazyRemote implements PluginRemote { return this.remote.setNativeId(nativeId, id, storage); } async updateDeviceState(id: string, state: { [property: string]: SystemDeviceState; }): Promise { - if (!await this.ensureRemote()) + try { + if (!this.remote) + await this.remoteReadyPromise; + } + catch (e) { return; + } return this.remote.updateDeviceState(id, state); } async notify(id: string, eventTime: number, eventInterface: string, property: string, propertyState: SystemDeviceState, changed?: boolean): Promise { - if (!await this.ensureRemote()) + try { + if (!this.remote) + await this.remoteReadyPromise; + } + catch (e) { return; + } return this.remote.notify(id, eventTime, eventInterface, property, propertyState, changed); } async ioEvent(id: string, event: string, message?: any): Promise {