Conversation
The token stored at `colab new` is issued for 3600 s and was never renewed, so about an hour after creation every command through the tunnel failed with 404 and the CLI pruned the local session (killing its keep-alive daemon) although the VM stayed assigned and running. The keep-alive daemon now records the token expiry (`SessionState.token_expires_at`) and, with less than 10 minutes left or the expiry unknown, copies the fresh token from the assignment listing into the store through the new locked field-level `StateStore.update`. Renewals and failures are logged and shown by `colab log`. Addresses googlecolab#106. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Symptom
About an hour after
colab new, every command that reaches the VM through the tunnel (exec,ls,upload,download,repl,console, ...) fails with HTTP 404 while the runtime is still assigned and running (it keeps executing jobs and consuming compute units). Because 404/401 is treated as "session lost", the CLI then prunes the local session and kills its keep-alive daemon, leaving a VM that can no longer be addressed or stopped from the CLI, only from the web UI. Reported in #106; reproduced today with 0.6.0 and onmain.Cause
The runtime proxy token stored in
sessions.jsonis issued withtokenExpiresInSeconds: 3600(RuntimeProxyInfoalready parses the field, but nothing reads it). Its lifetime is independent of the assignment's, and the CLI never renews it.Client.list_assignments()returns a freshly issuedruntimeProxyInfo(valid for another 3600 s) for every assignment. Writing thattoken/urlinto the session's entry restores access; repeating it periodically keeps a runtime reachable for as long as it is assigned.Fix
The keep-alive daemon, which already runs every 60 s per session, now renews the token before it expires:
SessionState.token_expires_atrecords when the token stops being accepted;colab newandcolab runpopulate it fromtoken_expires_in_seconds. A missing value (state written by an older CLI) means "unknown, renew now"._renew_token_if_expiring: with less thanTOKEN_RENEWAL_MARGIN(10 min) left it callslist_assignments(), finds its own endpoint and stores the newtoken,urland expiry. Failures are logged astoken_renewal_errorand retried on the next iteration; they never stop the daemon or count as keep-alive ping errors. Successful renewals logtoken_renewed; both events are rendered bycolab log.StateStore.update(name, **fields)is a locked field-level read-modify-write, so the daemon's write cannot clobberkernel_id/running/last_executionthat a concurrently running command writes (agetfollowed byaddfrom a second process could).docs/01_session_management.mdand the README keep-alive bullet describe the behaviour.No new dependencies, no other behaviour change.
renew_runtime_token(session_name, endpoint)is a plain function so a reactive path can reuse it.Known gap, documented in the design doc: a command that holds a
SessionStateacross a renewal (e.g. a longexec) writes its stale copy back when it finishes; the daemon sees the stale expiry and renews again within one iteration (about 60 s). #123's recover-before-prune on 404/401 covers that window; the two changes are complementary (this one keeps the stored token valid for every command, including the file operations noted in the #123 validation, and avoids the failed call altogether, as suggested at the end of #106).Verification
runtimeProxyInfofrom the assignment listing into the state file, and repeating the renewal every ~45 min kept a runtime usable for hours (well past the one-hour mark at which stock 0.6.0 loses it).sessions.jsonwith a fake client: a legacy entry without expiry is renewed at once, other fields survive the write, a fresh token triggers no listing call, and a token inside the margin is renewed.Tests
uv run pytest tests/(353 passed; 345 before) anduv run ruff check src testspass; the touched files areruff formatclean.New tests in
tests/test_keep_alive.py:colab newrecords the expiry; the daemon renews an expiring token with the listing's values for its own endpoint; leaves a fresh token alone; renews a token of unknown expiry; survives a listing failure (loop continues, nokeep_alive_error); does not write anything for an endpoint that is no longer listed. Intests/test_state.py:StateStore.updatesets only the given fields and is a no-op for an unknown session.Related: #106, #123 (reactive recovery), #109 (broader rework that also covers this).
I read CONTRIBUTING.md; I am opening this in case it is useful as a small, self-contained reference for the proactive half of #106. Feel free to close if it does not fit your plans.
🤖 Generated with Claude Code