Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
give a long gregor reconnect backoff to devices that don't send chats
This should mitigate some of the reconnect flood that the gregor servers have to deal with when they restart. Most idle clients in the wild aren't participating in chat, and don't need to reconnect very aggressively. There were a few different heuristics we could've used here, and others we might want to use in the future. One in particular we almost chose was "has this user ever received a message". However, we sometimes send system-wide messages, like when Linux updates are broken, which could confuse that heuristic. Chat sending is a surer sign of activity than receiving, and it also has the benefit of being individual-device-specific. Two things had to change to make this work. First, we had to configure a chat-activity-based backoff (using a couple new keys in LevelDB). Second, we had to make sure that the backoff was respected on reconnect, which required the new ForceInitialBackoff ConnectionOpts parameter upstream, since we don't keep a persisitent Connection object after disconnects.
- Loading branch information
1 parent
9314f39
commit 668c717
Showing
4 changed files
with
141 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package chat | ||
|
||
import ( | ||
"time" | ||
|
||
"github.com/keybase/client/go/chat/globals" | ||
"github.com/keybase/client/go/libkb" | ||
) | ||
|
||
// All devices are presumed active for the first 24 hours. See comment below. | ||
var InitialAssumedActiveInterval = 24 * time.Hour | ||
var ActiveIntervalAfterSend = 30 * 24 * time.Hour | ||
|
||
func chatActiveDBKey(name string) libkb.DbKey { | ||
return libkb.DbKey{ | ||
Typ: libkb.DBChatActive, | ||
Key: name, | ||
} | ||
} | ||
|
||
func firstQueryTimeDbKey() libkb.DbKey { | ||
return chatActiveDBKey("first_query_time") | ||
} | ||
|
||
func lastSendTimeDbKey() libkb.DbKey { | ||
return chatActiveDBKey("last_send_time") | ||
} | ||
|
||
// If no first query time is found in the local db, this function writes the | ||
// current time. | ||
func TouchFirstChatActiveQueryTime(g *globals.Context) time.Time { | ||
now := time.Now() | ||
var firstQueryUnixTime int64 | ||
found, err := g.LocalChatDb.GetInto(&firstQueryUnixTime, firstQueryTimeDbKey()) | ||
// Warn for errors and bail. | ||
if err != nil { | ||
g.Log.Debug("Failed to get chat active query time: %s", err) | ||
return now | ||
} | ||
// If the first query time doesn't exist, store Now(). | ||
if !found { | ||
g.Log.Debug("Chat active query time not found. Storing current time.") | ||
err := g.LocalChatDb.PutObj(firstQueryTimeDbKey(), nil, now.Unix()) | ||
if err != nil { | ||
g.Log.Debug("Failed to store chat active query time: %s", err) | ||
} | ||
return now | ||
} | ||
// Otherwise return what we found. | ||
return time.Unix(firstQueryUnixTime, 0) | ||
} | ||
|
||
// Returns the zero time if there is no recorded last send time (either because | ||
// the device has never sent a message, or because it hasn't sent one since we | ||
// started recording). | ||
func GetLastSendTime(g *globals.Context) time.Time { | ||
var zeroTime time.Time | ||
var lastSendUnixTime int64 | ||
found, err := g.LocalChatDb.GetInto(&lastSendUnixTime, lastSendTimeDbKey()) | ||
// Warn for errors and return zero. | ||
if err != nil { | ||
g.Log.Debug("Failed to get chat active last send time: %s", err) | ||
return zeroTime | ||
} | ||
// If the last time doesn't exist, again return zero. | ||
if !found { | ||
return zeroTime | ||
} | ||
// Otherwise return what we found. | ||
return time.Unix(lastSendUnixTime, 0) | ||
} | ||
|
||
func RecordChatSend(g *globals.Context) { | ||
err := g.LocalChatDb.PutObj(lastSendTimeDbKey(), nil, time.Now().Unix()) | ||
if err != nil { | ||
g.Log.Debug("Failed to store chat last send time: %s", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters