Context
connectionStore.ts's connect() and disconnect() actions both call api.* independently with no cancellation hook.
Problem
Click Connect on a slow profile, then immediately Cancel/Disconnect — the in-flight connect() resolves later and pushes the connection into activeConnections while the earlier disconnect() had nothing to remove. End state: live MySQL pool with no client-side reference, no way to close from UI without app restart. connectionStore.test.ts:393-400 explicitly documents and ships the leaky behavior as the contract.
Files
- src/stores/connectionStore.ts:58-72, 74-90
- src/stores/tests/connectionStore.test.ts:374-411
Repro
Open Connect on a profile that takes >500ms (latency simulation). Within 200ms click Cancel. After both settle, activeConnections has an entry for a connection the UI no longer references.
Expected
Race resolves cleanly: either the connect is cancelled before applying, or the connection is auto-disconnected after resolution when its cancel flag is set.
Proposed fix
Scope S. Track Map<profileId, AbortController> (or Set<pendingProfileIds>) in store; on disconnect(profileId) during in-flight connect, set a skip flag; on connect resolution, check flag and immediately api.disconnect. Flip the race test to assert no leak.
Acceptance
Existing race test flips from leaky to clean. Manual repro shows no activeConnections entry after connect+cancel.
Needs human verify
Yes.
Context
connectionStore.ts'sconnect()anddisconnect()actions both callapi.*independently with no cancellation hook.Problem
Click Connect on a slow profile, then immediately Cancel/Disconnect — the in-flight
connect()resolves later and pushes the connection intoactiveConnectionswhile the earlierdisconnect()had nothing to remove. End state: live MySQL pool with no client-side reference, no way to close from UI without app restart.connectionStore.test.ts:393-400explicitly documents and ships the leaky behavior as the contract.Files
Repro
Open Connect on a profile that takes >500ms (latency simulation). Within 200ms click Cancel. After both settle,
activeConnectionshas an entry for a connection the UI no longer references.Expected
Race resolves cleanly: either the connect is cancelled before applying, or the connection is auto-disconnected after resolution when its cancel flag is set.
Proposed fix
Scope S. Track
Map<profileId, AbortController>(orSet<pendingProfileIds>) in store; ondisconnect(profileId)during in-flight connect, set a skip flag; on connect resolution, check flag and immediatelyapi.disconnect. Flip the race test to assert no leak.Acceptance
Existing race test flips from leaky to clean. Manual repro shows no
activeConnectionsentry after connect+cancel.Needs human verify
Yes.