-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
use Fx to start and stop the host, swarm, autorelay and quicreuse #2118
Conversation
00516e2
to
fc5436b
Compare
if err != nil { | ||
return nil, err | ||
} | ||
lifecycle.Append(fx.StartStopHook(ar.Start, ar.Close)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
autorelay depends on Identify to start first, how can we enforce that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is guaranteed because we construct the host first, then autorelay (since the autorelay constructor depends on the host). Fx executes startup hooks in the order they were added, so this determines that host.Start
is called before autorelay.Start
. Now I admit that this is pretty subtle.
The correct solution is to remove the IDService()
from the host, and instead pass a reference to identify to the autorelay constructor. That would make the dependency tree more obvious. Let's do that in a follow-up PR?
if err != nil { | ||
return nil, err | ||
} | ||
lifecycle.Append(fx.StopHook(sw.Close)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we closing the swarm twice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned elsewhere, we are but that's okay since the swarm close is guarded to only close once. The closing twice is useful because each close is logically for a different reason.
- Here we are closing because we created the swarm.
- Below, in decorate we are closing to ensure we close before the quicreuse conn manager.
By closing twice we prevent these different procedures from being tangled.
8d52991
to
6d00b06
Compare
The swarm is not constructed by the basic host, thus is shouldn't be closed by it.
type closableBasicHost struct { | ||
*fx.App | ||
*basichost.BasicHost | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can have just one type which uses host.Host interface instead of a separate type for closableBasicHost and closableRoutedHost
type closableHost struct {
*fx.App
host.Host
}
config/config.go
Outdated
// should probably fail if listening on *any* addr fails. | ||
return sw.Listen(cfg.ListenAddrs...) | ||
}, | ||
OnStop: func(context.Context) error { return sw.Close() }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will this call sw.Close
twice? One for this and one for the previous option where we do,
lifecycle.Append(fx.StopHook(sw.Close))
I think this is fine though, swarm.Close is guarded by a sync.Once
Thanks for removing |
82dab47
to
489b685
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to add a couple more tests. At least:
- A test that asserts the connmanager is closed after we close the host/swarm.
- A test that asserts their are no dangling goroutines after starting and stopping a host.
if err != nil { | ||
return nil, err | ||
} | ||
lifecycle.Append(fx.StopHook(sw.Close)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned elsewhere, we are but that's okay since the swarm close is guarded to only close once. The closing twice is useful because each close is logically for a different reason.
- Here we are closing because we created the swarm.
- Below, in decorate we are closing to ensure we close before the quicreuse conn manager.
By closing twice we prevent these different procedures from being tangled.
To do this, I've had to move a few leaky tests into a separate package. I've filed a bug for the AutoNAT issue (#2743) but the "error on startup" issue is going to require some pretty invasive changes (we need to construct _then_ start).
I've added a dangling goroutine test which should be sufficient. It implicitly asserts that the connection manager is closed as the connection manager launches a background goroutine. Ideally we'd have some way to also assert that there are no scheduled timers, but I don't think we can. When doing that, I noticed two issues:
(I'm trying to push this forward because I don't want it to develop a bunch of merge conflicts) |
Thanks @Stebalien! I didn't know about uber/goleak. Looks helpful. I'll try to fix the current leaks. |
Hm. That goroutine should have been excluded... |
Oh, different nat goroutine. |
I'd add |
This is effectively covered by checking for dangling goroutines. |
Fixes #2117. Part of #1993. Part of #2514.