Skip to content
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

Add periodic refresh for connection #58

Merged
merged 11 commits into from
May 15, 2024
10 changes: 6 additions & 4 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,12 @@ type Config struct {
*bridgeconfig.BaseConfig `yaml:",inline"`

Meta struct {
Mode BridgeMode `yaml:"mode"`
IGE2EE bool `yaml:"ig_e2ee"`
Proxy string `yaml:"proxy"`
GetProxyFrom string `yaml:"get_proxy_from"`
Mode BridgeMode `yaml:"mode"`
IGE2EE bool `yaml:"ig_e2ee"`
Proxy string `yaml:"proxy"`
GetProxyFrom string `yaml:"get_proxy_from"`
MinFullReconnectIntervalSeconds int `yaml:"min_full_reconnect_interval_seconds"`
ForceRefreshIntervalSeconds int `yaml:"force_refresh_interval_seconds"`
} `yaml:"meta"`

Bridge BridgeConfig `yaml:"bridge"`
Expand Down
4 changes: 4 additions & 0 deletions example-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ meta:
# HTTP endpoint to request new proxy address from, for dynamically assigned proxies.
# The endpoint must return a JSON body with a string field called proxy_url.
get_proxy_from:
# Minimum interval between full reconnects in seconds, default is 1 hour
min_full_reconnect_interval_seconds: 3600
Copy link
Member Author

@javiercr javiercr May 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm exposing MinFullReconnectIntervalSeconds in the config file, as it also affect the interval for force refreshes.

# Interval to force refresh the connection (full reconnect), default is 1 day. Set 0 to disable force refreshes.
force_refresh_interval_seconds: 86400

# Bridge config
bridge:
Expand Down
1 change: 1 addition & 0 deletions messagix/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ func (c *Client) Disconnect() {
(*fn)()
}
c.socket.Disconnect()
c.socket.conn = nil
}

func (c *Client) SaveSession(path string) error {
Expand Down
2 changes: 1 addition & 1 deletion portal.go
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ func (portal *Portal) handleMatrixMessage(ctx context.Context, sender *User, evt
} else {
ctx = context.WithValue(ctx, msgconvContextKeyClient, sender.Client)
tasks, otid, err = portal.MsgConv.ToMeta(ctx, evt, content, relaybotFormatted)
if errors.Is(err, metaTypes.ErrPleaseReloadPage) && time.Since(sender.lastFullReconnect) > MinFullReconnectInterval {
if errors.Is(err, metaTypes.ErrPleaseReloadPage) && sender.canReconnect() {
log.Err(err).Msg("Got please reload page error while converting message, reloading page in background")
go sender.FullReconnect()
err = errReloading
Expand Down
25 changes: 20 additions & 5 deletions user.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ var (
ErrNotLoggedIn = errors.New("not logged in")
)

const MinFullReconnectInterval = 1 * time.Hour
const setDisconnectStateAfterConnectAttempts = 3

func (br *MetaBridge) GetUserByMXID(userID id.UserID) *User {
Expand Down Expand Up @@ -542,6 +541,18 @@ func (user *User) unlockedConnect() {
}
go user.sendMarkdownBridgeAlert(context.TODO(), "Failed to connect to %s: %v", user.bridge.ProtocolName, err)
javiercr marked this conversation as resolved.
Show resolved Hide resolved
}

refreshInterval := time.Duration(user.bridge.Config.Meta.ForceRefreshIntervalSeconds) * time.Second
if refreshInterval > 0 {
user.log.Debug().Msgf("Connection will be refreshed at %s", time.Now().Add(refreshInterval).Format(time.RFC3339))
javiercr marked this conversation as resolved.
Show resolved Hide resolved
go func() {
var refreshTimer = time.NewTimer(refreshInterval)

<-refreshTimer.C
user.log.Info().Msg("Refreshing connection")
user.FullReconnect()
}()
}
}

func (user *User) Login(ctx context.Context, cookies *cookies.Cookies) error {
Expand Down Expand Up @@ -1014,7 +1025,7 @@ func (user *User) e2eeEventHandler(rawEvt any) {
}
user.BridgeState.Send(user.waState)
case *events.CATRefreshError:
if errors.Is(evt.Error, types.ErrPleaseReloadPage) && time.Since(user.lastFullReconnect) > MinFullReconnectInterval {
if errors.Is(evt.Error, types.ErrPleaseReloadPage) && user.canReconnect() {
user.log.Err(evt.Error).Msg("Got CATRefreshError, reloading page")
go user.FullReconnect()
return
Expand All @@ -1028,7 +1039,7 @@ func (user *User) e2eeEventHandler(rawEvt any) {
go user.sendMarkdownBridgeAlert(context.TODO(), "Error in WhatsApp connection: %s", evt.PermanentDisconnectDescription())
case events.PermanentDisconnect:
cf, ok := evt.(*events.ConnectFailure)
if ok && cf.Reason == events.ConnectFailureLoggedOut && time.Since(user.lastFullReconnect) > MinFullReconnectInterval {
if ok && cf.Reason == events.ConnectFailureLoggedOut && user.canReconnect() {
user.log.Debug().Msg("Doing full reconnect after WhatsApp 401 error")
go user.FullReconnect()
}
Expand Down Expand Up @@ -1133,7 +1144,7 @@ func (user *User) eventHandler(rawEvt any) {
StateEvent: status.StateUnknownError,
Error: MetaServerUnavailable,
}
if time.Since(user.lastFullReconnect) > MinFullReconnectInterval {
if user.canReconnect() {
user.log.Debug().Msg("Doing full reconnect after server unavailable error")
go user.FullReconnect()
}
Expand Down Expand Up @@ -1183,10 +1194,14 @@ func (user *User) unlockedDisconnect() {
user.metaState = status.BridgeState{}
}

func (user *User) canReconnect() bool {
return time.Since(user.lastFullReconnect) > time.Duration(user.bridge.Config.Meta.MinFullReconnectIntervalSeconds)*time.Second
}

func (user *User) FullReconnect() {
user.Lock()
defer user.Unlock()
if time.Since(user.lastFullReconnect) < MinFullReconnectInterval {
if !user.canReconnect() {
return
}
user.unlockedDisconnect()
Expand Down
Loading