Skip to content

Commit 4b88fb9

Browse files
committed
docs: clarify fast-path async behavior - deferred registration, race condition fix, failure retry
1 parent 2ed5c03 commit 4b88fb9

File tree

1 file changed

+20
-6
lines changed

1 file changed

+20
-6
lines changed

docs/startup-flow.md

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,29 @@ python environments extension begins activation
6868
c. a persisted env path exists in workspace state for this scope (folder Uri)
6969

7070
FAST PATH (run if above three conditions are true):
71-
1. read persisted path
72-
2. `resolve(persistedPath)`
71+
**Race-condition safety (runs before any await):**
72+
1. if `_initialized` doesn't exist yet:
73+
- create deferred and **register immediately** via `setInitialized()` callback
74+
- this blocks concurrent callers from spawning duplicate background inits
75+
- kick off `startBackgroundInit()` as fire-and-forget
76+
2. get project fsPath: `getProjectFsPathForScope(api, scope)`
77+
- prefers resolved project path if available, falls back to scope.fsPath
78+
- shared across all managers to avoid lambda duplication
79+
3. read persisted path
80+
4. `resolve(persistedPath)`
7381
1. failure → see SLOW PATH
74-
2. successful → return env immediately AND
75-
3. if `_initialized` deferred doesn't exist yet:
76-
- create one, kick off `startBackgroundInit()` as fire-and-forget
82+
2. successful → return env immediately (background init continues in parallel)
83+
**Failure recovery (in startBackgroundInit error handler):**
84+
- if background init throws: `setInitialized(undefined)` — clear deferred so next `get()` call retries init
7785

7886
SLOW PATH — fast path conditions not met, or fast path failed:
79-
4. `initialize()` — lazy, once-only per manager (guarded by deferred)
87+
4. `initialize()` — lazy, once-only per manager (guarded by `_initialized` deferred)
88+
**Once-only guarantee:**
89+
- first caller creates `_initialized` deferred (if not already created by fast path)
90+
- concurrent callers see the existing deferred and await it instead of re-running init
91+
- deferred is **not cleared on failure** here (unlike in fast-path background handler)
92+
so only one init attempt runs, but subsequent calls still await the same failed init
93+
**Note:** In the fast path, if background init fails, the deferred is cleared to allow retry
8094
a. `nativeFinder.refresh(hardRefresh=false)`:
8195
→ internally calls `handleSoftRefresh()` → computes cache key from options
8296
- on reload: cache is empty (Map was destroyed) → cache miss

0 commit comments

Comments
 (0)