From 42bad68220d288ef2436609ee50ad993c239b362 Mon Sep 17 00:00:00 2001 From: Dawid Date: Wed, 18 Sep 2024 07:32:59 -0700 Subject: [PATCH] fix app crashing when reloads overlap (#46416) Summary: Regarding the [issue](https://github.com/facebook/react-native/issues/44755) where the app sometimes crashes due to race condition when two reloads overlap in unfortunate way. This PR fixes it in some way by introducing throttling on reload command. For now I set it to 700ms as I was still able to reproduce it on 500-550ms for provided repro in the issue. The problem may still happen for bigger apps where reload may take more time to finish. ## Changelog: [GENERAL] [FIXED] - throttle reload command Pull Request resolved: https://github.com/facebook/react-native/pull/46416 Test Plan: I've tested on provided repro and a smaller app trying to brake it. Reviewed By: huntie Differential Revision: D62847076 Pulled By: cipolleschi fbshipit-source-id: 6471f792d6b692e87e3e98a699443a88c6ef43cd --- .../src/commands/start/attachKeyHandlers.js | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/community-cli-plugin/src/commands/start/attachKeyHandlers.js b/packages/community-cli-plugin/src/commands/start/attachKeyHandlers.js index fcb387691e40dc..82af11a671207a 100644 --- a/packages/community-cli-plugin/src/commands/start/attachKeyHandlers.js +++ b/packages/community-cli-plugin/src/commands/start/attachKeyHandlers.js @@ -19,6 +19,18 @@ import fetch from 'node-fetch'; const CTRL_C = '\u0003'; const CTRL_D = '\u0004'; +const RELOAD_TIMEOUT = 500; + +const throttle = (callback: () => void, timeout: number) => { + let previousCallTimestamp = 0; + return () => { + const currentCallTimestamp = new Date().getTime(); + if (currentCallTimestamp - previousCallTimestamp > timeout) { + previousCallTimestamp = currentCallTimestamp; + callback(); + } + }; +}; export default function attachKeyHandlers({ cliConfig, @@ -41,11 +53,15 @@ export default function attachKeyHandlers({ env: {FORCE_COLOR: chalk.supportsColor ? 'true' : 'false'}, }; + const reload = throttle(() => { + logger.info('Reloading connected app(s)...'); + messageSocket.broadcast('reload', null); + }, RELOAD_TIMEOUT); + const onPress = async (key: string) => { switch (key.toLowerCase()) { case 'r': - logger.info('Reloading connected app(s)...'); - messageSocket.broadcast('reload', null); + reload(); break; case 'd': logger.info('Opening Dev Menu...');