Skip to content

Start a stopped database on login failure, then connect - #217

Merged
srbaker merged 11 commits into
mainfrom
srbaker/quick-connect-login
Aug 12, 2026
Merged

srbaker merged 11 commits into
mainfrom
srbaker/quick-connect-login

Conversation

@srbaker

@srbaker srbaker commented Jul 23, 2026 •

Copy link
Copy Markdown
Collaborator

Why

Logging in to a database that is not running just fails with an unhelpful error. You then have to leave the login, find the database, start it by hand, and try again.

What changed

  • Offer to start a stopped database on login failure, then connect. When a login fails because its database is stopped, offer to start it and connect automatically. The prompt offers Now / Never, and Never is remembered so you are not asked again.
  • Report signal kills honestly. A GemStone process killed by a signal now says so (e.g. "killed by signal SIGKILL") instead of the misleading "exit code null".
  • Keep the Admin output panel shut while auto-starting during a login -- no unsolicited panel popping open.
  • Recover a database when only one of its processes is wedged. Anything that is down is offered first, so a wedged stone no longer leaves a stopped NetLDI stopped. not-responding is reported only when both are up, where starting cannot help.
  • Report a recovery failure instead of letting it escape the login command. maybeStartDatabaseAndRetry documents itself as reporting the outcome on every path, but only guarded the failures it expected -- remembering the preference and reading the database list were bare, so an unwritable settings.json rejected out of the flow. With this branch having replaced the commands catchwith a barefinally`, that surfaced as "command failed", naming neither the login nor the reason. The contract is now true at the source, and the command keeps a net as well.
  • Scope the auto-start preference so no workspace can override it. The prompt writes ConfigurationTarget.Global, but the setting declared no scope and so took VS Codes default of window` -- which a workspace outranks. Anyone with such an override would click Never, have it written where it stays outranked, and be asked again with no sign of why.

Verification

  • Full CI matrix green on this head: GemStone 3.6.2 / 3.6.2 (Node 22.15.1) / 3.6.8 / 3.7.2 / 3.7.4.3 / 3.7.5, plus lint, format, CodeQL and vsce packaging.
  • Locally: compile, lint, format:check clean; 4509 client unit tests pass. The remaining local failures are the integration suites that need a live stone, which CI covers above.
  • Each commit ships its own tests (autoStartDatabase, autoStartDecision, autoStartPrompt, databaseForLogin, loginTreeProvider, processManager).

srbaker added 3 commits July 22, 2026 20:29
A login to a Jasper-managed database that isn't running failed with a raw
GCI error, leaving the user to go start the stone and NetLDI by hand.
A jetsam kill reports a null exit code and no output, so the start failure
message told the user nothing at all.
Revealing it mid-connect yanked focus off the editor; the connect's own
progress notification and row spinner already report what is happening.
@srbaker
srbaker marked this pull request as ready for review July 23, 2026 19:12
Comment thread client/src/versionsMatch.ts Resolved
Comment thread client/src/autoStartPrompt.ts Resolved
Comment thread client/src/autoStartDecision.ts Resolved
The auto-start recovery bailed entirely the moment either the stone or the
NetLDI was running-but-unresponsive -- even when the other process was simply
stopped and could be started on its own. The two are started independently, so
a wedge on one side is no reason to leave a genuinely-down process on the other
side down: it just dead-ends a recovery that could have worked. Offer to start
whatever is stopped first, and only fall back to reporting an unresponsive
process when nothing can be started. Adds a test for the down-plus-wedged case.

Two fixes from the same review, each on its own rationale:

- Inline versionsMatch back into processManager. It was already exported from
  there, so a dedicated module for one small function bought nothing but an
  extra hop; the reviewer rightly asked why it existed. The two pure consumers
  import it from processManager again (their tests mock vscode to stay
  headless -- the one cost of un-splitting).

- Correct a stale comment on the auto-start preference command. It claimed the
  prompt "has no button for Never", but the prompt offers Yes/No/Always/Never;
  the palette command is for changing the choice later, not for reaching Never.
  Left as-is it misleads the next reader about what the prompt actually does.
@srbaker
srbaker force-pushed the srbaker/quick-connect-login branch from b9d5b0c to 4a59e73 Compare July 23, 2026 21:16
srbaker added 5 commits July 24, 2026 00:55
…-login

# Conflicts:
#	client/src/extension.ts
maybeStartDatabaseAndRetry documents itself as responsible for reporting the
outcome on every path, but it only guarded the failures it expected: a start,
and the retry. Remembering the preference and reading the database list were
left bare, so an unwritable settings.json or an unreadable database root
rejected straight out of the flow.

That used to be caught by the login command's own catch, which this branch
replaced with a bare finally. Without it VS Code reports "command failed",
naming neither the login nor the reason -- strictly less than the error the
recovery flow was standing in for.

So make the contract true at the source, and keep the command's net as well
since a command handler should never reject.
The prompt's Always/Never buttons write ConfigurationTarget.Global, on the
reasoning that whether to start a stopped database is a property of how someone
likes to work rather than of whichever folder is open. But the setting declared
no scope, so it took VS Code's default of "window" -- which a workspace is free
to override, and a workspace value outranks the global one.

Anyone with such an override would click "Never", have it written where it stays
outranked, and be asked again on the next connect, with no sign of why.
@srbaker
srbaker enabled auto-merge August 5, 2026 20:52

@MatiasFernandez MatiasFernandez left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left some comments worth checking

Comment thread client/src/processManager.ts Resolved
Comment thread client/src/databaseForLogin.ts Resolved
Comment thread client/src/loginTreeProvider.ts Resolved
Comment thread client/src/extension.ts Resolved
Four things Matias raised on #217.

The connecting spinner was held by the login's position in the list, which
outlives the render it came from: starting a stone and its NetLDI takes
seconds, the tree stays interactive, and a login deleted or reordered meanwhile
left the `finally`'s clear landing on whichever login had inherited that slot —
the row actually connecting kept spinning with nothing able to stop it. It is
keyed by the login's identity now, so both the spinner and the clearing follow
the login rather than the slot.

A signal-killed process claimed memory pressure whatever the signal was. Only
SIGKILL earns that: it is what macOS jetsam does. A SIGSEGV from a broken
install or a SIGTERM from someone running kill now say so plainly, instead of
sending the reader off to free memory that was never the problem. The test
that covered this accepted any of three words, so it passed either way; it is
two tests now, one that requires the memory advice and one that forbids it.

`isLocalHost` answers "is this login on this machine" in one place, and Serve
Seaside's inline copy of the same predicate now asks it. It also accepts `::1`
and `[::1]`: an IPv6-loopback login is the same machine, but read as remote it
would quietly lose the auto-start offer, with the user seeing only the original
login failure again and nothing explaining why.

And `resolvedGciPath` says why it exists — `gciPath` is a `let`, which
TypeScript widens back to `string | undefined` inside the async closure — so
the next reader does not tidy it away and hit a type error they cannot place.
@srbaker
srbaker added this pull request to the merge queue Aug 12, 2026
Merged via the queue into main with commit c955c0a Aug 12, 2026
30 checks passed
@srbaker
srbaker deleted the srbaker/quick-connect-login branch August 12, 2026 21:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants