-
Notifications
You must be signed in to change notification settings - Fork 488
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
refactor(webview): avoid race conditions in constructors. #5961
refactor(webview): avoid race conditions in constructors. #5961
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
export class ApplicationComposer { | ||
public readonly documentUri: vscode.Uri | ||
public webviewPanel: vscode.WebviewPanel | ||
public webviewPanel: vscode.WebviewPanel = {} as vscode.WebviewPanel |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there any reason this can't be public webviewPanel: vscode.WebviewPanel | undefined
? If the webview panel is an empty object does that make some assumptions down the line that it might be defined, even though it isn't?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I wasn't sure if there was a better way to handle this. Since the constructor is private, the only way to instantiate ApplicationComposer
is through the create
method. Thus, this field will always be initiated. Perhaps there is a better way to enforce this invariant?
The advantage of an empty object is that I don't have to do an undefined check on each usage, but maybe if we can't enforce create
being the sole entry point then this is necessary?
## Problem It appears that older versions of VSCode are causing this test to be flaky, which appears to be fixed in v1.88. See findings section for more information. ## Solution - Skip the test if vscode version is pre-1.88. - Add tech-debt test to remove this check once min is 1.88+. ## Findings - Ran 1000 times in CI, and failed 29 times. (2.9% failure rate). If we re-reran 3 times, ci would pass ~ 99.998% of the time (assuming failures independent). - Only fails on VSCode minimum (1.83.0). - Originally thought it was related to activating Q extension or fetching it from CDN, but appears mocking this still results in flakiness. - Every failure comes with a `ERROR:gles2_command_buffer_stub.cc(364)] ContextResult::kFatalFailure Failed to create context.` which appears to be from OpenGL. This means it is coming from very far down the stack since VSCode is built on electron, which uses chromium, which is then using OpenGL. (ai suggests this is a GPU problem?). - Thought to be from race condition with async constructor hack, fixed by #5961. - Evidence is suggesting that this could be a bug in a prior version of VSCode, electron, or OpenGL, and should go away once we bump minimum VSCode version. - Works on VSCode 1.90+, 1.87- fails, 1.88 is the minimum version it is not flaky. (verified using 1000 attempts). - Failures are NOT independent since retrying 10x times only reduced failure rate to ~1%. Therefore retries are not a viable option.
Problem
In the constructor for
ApplicationComposerManager
, there is an async call (non-awaited). This call is modifying state within the object and therefore causes a race condition with any other function relying on this state. Seeaws-toolkit-vscode/packages/core/src/applicationcomposer/webviewManager.ts
Lines 30 to 33 in 8113288
This is potentially related to a flaky test.The test is still failing, but this refactor is still a win.Solution
create
method with a private constructor. Move this pattern upward to enable async calls.License: I confirm that my contribution is made under the terms of the Apache 2.0 license.