mirror of
https://github.com/docker/docker-agent.git
synced 2026-11-04 10:02:15 +00:00
Adds lifecycle.Supervisor: a single, well-tested implementation of the
connect / watch / restart / stop dance that pkg/tools/mcp had grown
inline as watchConnection / tryRestart / forceReconnectAndWait. The
supervisor:
* accepts a transport-agnostic Connector that returns a Session
(Wait + Close), so MCP, remote MCP, and the upcoming LSP port all
share the same lifecycle code.
* has a configurable Policy: Restart (Never/OnFailure/Always),
MaxAttempts, Backoff (Initial/Max/Multiplier/Jitter), and three
callback hooks (OnDisconnect, OnRestart, OnFailed). Defaults match
historical behaviour: RestartOnFailure, 5 attempts, 1s..32s.
* tracks state via the Tracker added in the previous commit, so
callers can query State() / IsReady() / Restarted() instead of
reading internal fields.
* implements RestartAndWait via a single 'forceRestart' flag and a
swappable 'restarted' channel, fixing a subtle race where Close()
on a clean session caused Wait()==nil and the watcher would fall
through to Failed instead of reconnecting.
mcp.Toolset is rewritten on top of the supervisor:
* deletes started / stopping / watcherAlive / restarted state
fields and the watchConnection / tryRestart / forceReconnectAndWait
methods (~150 lines).
* the initialize handshake (including the upstream-bug retry for
'failed to send initialized notification') moves into a small
clientConnector adapter; the existing mcpClient interface is
reused as a Session.
* cache invalidation and tool/prompt refresh happen via
OnDisconnect / OnRestart hooks rather than open-coded inside the
watcher loop.
* forceReconnectAndWait becomes supervisor.RestartAndWait.
* tests that previously poked at Toolset.started / Toolset.restarted
/ Toolset.mu now go through Toolset.IsStarted() and
supervisor.Restarted(); a small testhelpers_test.go provides
newTestToolset(...) and markStartedForTesting() so per-request
code paths can be exercised without driving a full Connect.
External behaviour is preserved: the same conditions return
errServerUnavailable (now an alias to lifecycle.ErrServerUnavailable),
the same retry budget governs reconnects, and the public Toolset API
(Tools, ListPrompts, GetPrompt, callTool, Start, Stop, all the
Set*Handler methods) is unchanged. All existing tests still pass under
'go test -race'.
Assisted-By: docker-agent
10 lines
245 B
Go
10 lines
245 B
Go
package lifecycle
|
|
|
|
import "time"
|
|
|
|
// ExportedBackoffDelay exposes Backoff.delay for tests in the _test
|
|
// package.
|
|
func ExportedBackoffDelay(b Backoff, attempt int, randFloat func() float64) time.Duration {
|
|
return b.delay(attempt, randFloat)
|
|
}
|