sandpack icon indicating copy to clipboard operation
sandpack copied to clipboard

Race condition when programmatically updating files during recompile

Open a-type opened this issue 1 year ago • 6 comments

Bug report

Packages affected

  • [ ] sandpack-client (unclear)
  • [x] sandpack-react

Description of the problem

I'm using Sandpack to bundle and run pre-existing code which is controlled by users and stored externally. The current approach involves loading these files when the external file source is ready, overwriting an initial default empty template. This overwrite-load happens inside a useEffect very shortly after Sandpack is initialized.

However, I've observed a race condition when doing this: in almost all cases, despite updateFile being called, Sandpack will ignore the new files and keep rendering the blank template upon startup.

I believe the source of this race condition is in this logic, which ignores file changes if the client is actively recompiling. Since my file update happens shortly after startup, my theory is the client is busy compiling the empty template, and so the real files are simply never loaded in the client unless I trigger another change later on. But I'm not 100% sure this is the problem. My only evidence to support it is that if I set a logpoint on that line in my devtools while reloading the page, the only log I see shows that filesState.files has the correct (updated) file contents, but client.status is 'initializing', meaning it will not be updated. The logpoint is only triggered once; so it seems that because the timing was unfortunate, it misses its only chance to load the new file contents.

A minimal demonstration of this problem is shown in the codesandbox below. As you can see, the code in the editor has been properly updated, but the sandbox is out of date. Uncomment the timeout wrapping the updateFile call to see how a delay avoids the race condition:

Sandbox

If this truly is a race condition related to the line of code cited above, I might suggest that if the client is busy, the file watching logic should re-enqueue the update for later. Alternatively, a more sophisticated approach might be to cancel current compilation if possible and restart with the latest code.

Workaround

For now I am refactoring my app to fully load external sources before initializing Sandpack, so that instead of starting from a blank template and replacing its files once ready, the app instead waits until it can use the external file sources as the initial files in Sandpack setup. This is probably preferable anyway, but I felt the race condition still feels 'wrong' enough to report to you for consideration. There may be legitimate scenarios where this race condition is triggered either by rapid user input or a slow compilation.

a-type avatar Aug 20 '24 20:08 a-type