Skip to content

Commit

Permalink
Merge pull request #884 from apernet/fix-lazy
Browse files Browse the repository at this point in the history
fix: lazy mode should defer config evaluation
  • Loading branch information
tobyxdd authored Dec 29, 2023
2 parents b7dff17 + d73edff commit f3d6751
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 26 deletions.
26 changes: 12 additions & 14 deletions app/cmd/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -398,21 +398,19 @@ func runClient(cmd *cobra.Command, args []string) {
if err := viper.Unmarshal(&config); err != nil {
logger.Fatal("failed to parse client config", zap.Error(err))
}
hyConfig, err := config.Config()
if err != nil {
logger.Fatal("failed to load client config", zap.Error(err))
}

c, err := client.NewReconnectableClient(hyConfig, func(c client.Client, info *client.HandshakeInfo, count int) {
connectLog(info, count)
// On the client side, we start checking for updates after we successfully connect
// to the server, which, depending on whether lazy mode is enabled, may or may not
// be immediately after the client starts. We don't want the update check request
// to interfere with the lazy mode option.
if count == 1 && !disableUpdateCheck {
go runCheckUpdateClient(c)
}
}, config.Lazy)
c, err := client.NewReconnectableClient(
config.Config,
func(c client.Client, info *client.HandshakeInfo, count int) {
connectLog(info, count)
// On the client side, we start checking for updates after we successfully connect
// to the server, which, depending on whether lazy mode is enabled, may or may not
// be immediately after the client starts. We don't want the update check request
// to interfere with the lazy mode option.
if count == 1 && !disableUpdateCheck {
go runCheckUpdateClient(c)
}
}, config.Lazy)
if err != nil {
logger.Fatal("failed to initialize client", zap.Error(err))
}
Expand Down
25 changes: 13 additions & 12 deletions core/client/reconnect.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,21 @@ import (
// reconnectableClientImpl is a wrapper of Client, which can reconnect when the connection is closed,
// except when the caller explicitly calls Close() to permanently close this client.
type reconnectableClientImpl struct {
config *Config
configFunc func() (*Config, error) // called before connecting
connectedFunc func(Client, *HandshakeInfo, int) // called when successfully connected
client Client
count int
connectedFunc func(Client, *HandshakeInfo, int) // called when successfully connected
m sync.Mutex
closed bool // permanent close
}

func NewReconnectableClient(config *Config, connectedFunc func(Client, *HandshakeInfo, int), lazy bool) (Client, error) {
// Make sure we capture any error in config and return it here,
// so that the caller doesn't have to wait until the first call
// to TCP() or UDP() to get the error (when lazy is true).
if err := config.verifyAndFill(); err != nil {
return nil, err
}
// NewReconnectableClient creates a reconnectable client.
// If lazy is true, the client will not connect until the first call to TCP() or UDP().
// We use a function for config mainly to delay config evaluation
// (which involves DNS resolution) until the actual connection attempt.
func NewReconnectableClient(configFunc func() (*Config, error), connectedFunc func(Client, *HandshakeInfo, int), lazy bool) (Client, error) {
rc := &reconnectableClientImpl{
config: config,
configFunc: configFunc,
connectedFunc: connectedFunc,
}
if !lazy {
Expand All @@ -41,9 +39,12 @@ func (rc *reconnectableClientImpl) reconnect() error {
if rc.client != nil {
_ = rc.client.Close()
}
var err error
var info *HandshakeInfo
rc.client, info, err = NewClient(rc.config)
config, err := rc.configFunc()
if err != nil {
return err
}
rc.client, info, err = NewClient(config)
if err != nil {
return err
} else {
Expand Down

0 comments on commit f3d6751

Please sign in to comment.