HasTraits are expensive to instantiate, so make Users as light as possible
Removes immediate instantiation of Spawners during User init. Spawners will only be instantiated while running
Avoids instantiating too many objects before they are used
- deletes Spawner instances after they stop to avoid lingering instances
- use user_dict cache more often instead of db queries
- check for empty spawners dict to avoid a few Spawner instantiations
this is the most likely cause of redirect loops when using docker,
so record the spawner version and check it when a redirect is detected.
In the event of a redirect and mismatch, fail with a message explaining the version mismatch and how to fix it.
handle will_resume case correctly, where an API token *may* be re-used.
Previously, we only did it right if the token was *always* reused,
but clearing out a container would get it into a bad state.
- test that .will_resume preserves tokens (worked, but wasn't tested)
If a Spawner reuses a token, validate it in the db:
- verify that it's in the db
- if it doesn't map onto the right user, revoke the token
- if it's not in the db, insert it as a user-provided token
The most likely case is prior unclean shutdown of something like DockerSpawner,
where a spawn failed and thus the token was revoked,
but the container was in fact created.
it was made a method for handing named_servers,
but that made things way more complicated and replaced a boolean flag with a callable,
which would behave unexpectedly but without error if a boolean flag was expected.
Spawners have properties for dealing with this now, so use spawners
Restore `user.running` as an alias for `user.spawner.ready`
produces summary of active/pending/ready spawner counts
Avoids brittle bookkeeping of running counts,
computing the value upon request.
For 10k users this is still only a few milliseconds, which seems worth it
only benefit of privy was KDF, but if users provide good 32B keys, this doesn't help.
Fernet already adds randomness, etc. to tokens, so is good enough on its own if keys are good.
privy is used for encryption
- db only has blob column, no knowledge of encryption
- add CryptKeeper for handling encryption
- use privy for encryption, so we have fewer choices to make
- storing/loading encrypted auth_state runs in a ThreadPool
flag for waiting for the proxy to be updated
avoids User.running being True when the user's server has not yet been added to the proxy,
causing potential redirect loops.
in both directions - Hub checks singleuser server on spawn and singleuser server checks Hub on startup
if minor versions mismatch, log at warning level, otherwise debug
store id on outer User, rather than accessing orm_user.id, which seems to fail sometimes
this may fix the recent increase in intermittent test failures
namedtuple(path, host)
everywhere that accepts a RouteSpec must also accept a string
and treat it as RouteSpec(string).
RouteSpec.as_routespec(spec_or_string) handles this.