mirror of
https://github.com/ergochat/ergo.git
synced 2024-11-10 22:19:31 +01:00
persist lastSignoff in the database
This commit is contained in:
parent
17a89838b8
commit
4472683d58
@ -35,6 +35,7 @@ const (
|
||||
keyCertToAccount = "account.creds.certfp %s"
|
||||
keyAccountChannels = "account.channels %s" // channels registered to the account
|
||||
keyAccountJoinedChannels = "account.joinedto %s" // channels a persistent client has joined
|
||||
keyAccountLastSignoff = "account.lastsignoff %s"
|
||||
|
||||
keyVHostQueueAcctToId = "vhostQueue %s"
|
||||
vhostRequestIdx = "vhostQueue"
|
||||
@ -103,7 +104,7 @@ func (am *AccountManager) createAlwaysOnClients(config *Config) {
|
||||
account, err := am.LoadAccount(accountName)
|
||||
if err == nil && account.Verified &&
|
||||
persistenceEnabled(config.Accounts.Bouncer.AlwaysOn, account.Settings.AlwaysOn) {
|
||||
am.server.AddAlwaysOnClient(account, am.loadChannels(accountName))
|
||||
am.server.AddAlwaysOnClient(account, am.loadChannels(accountName), am.loadLastSignoff(accountName))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -534,6 +535,36 @@ func (am *AccountManager) loadChannels(account string) (channels []string) {
|
||||
return
|
||||
}
|
||||
|
||||
func (am *AccountManager) saveLastSignoff(account string, lastSignoff time.Time) {
|
||||
key := fmt.Sprintf(keyAccountLastSignoff, account)
|
||||
var val string
|
||||
if !lastSignoff.IsZero() {
|
||||
val = strconv.FormatInt(lastSignoff.UnixNano(), 10)
|
||||
}
|
||||
am.server.store.Update(func(tx *buntdb.Tx) error {
|
||||
if val != "" {
|
||||
tx.Set(key, val, nil)
|
||||
} else {
|
||||
tx.Delete(key)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func (am *AccountManager) loadLastSignoff(account string) (lastSignoff time.Time) {
|
||||
key := fmt.Sprintf(keyAccountLastSignoff, account)
|
||||
var lsText string
|
||||
am.server.store.View(func(tx *buntdb.Tx) error {
|
||||
lsText, _ = tx.Get(key)
|
||||
return nil
|
||||
})
|
||||
lsNum, err := strconv.ParseInt(lsText, 10, 64)
|
||||
if err != nil {
|
||||
return time.Unix(0, lsNum)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (am *AccountManager) addRemoveCertfp(account, certfp string, add bool, hasPrivs bool) (err error) {
|
||||
certfp, err = utils.NormalizeCertfp(certfp)
|
||||
if err != nil {
|
||||
@ -1034,6 +1065,7 @@ func (am *AccountManager) Unregister(account string) error {
|
||||
vhostQueueKey := fmt.Sprintf(keyVHostQueueAcctToId, casefoldedAccount)
|
||||
channelsKey := fmt.Sprintf(keyAccountChannels, casefoldedAccount)
|
||||
joinedChannelsKey := fmt.Sprintf(keyAccountJoinedChannels, casefoldedAccount)
|
||||
lastSignoffKey := fmt.Sprintf(keyAccountLastSignoff, casefoldedAccount)
|
||||
|
||||
var clients []*Client
|
||||
|
||||
@ -1070,6 +1102,7 @@ func (am *AccountManager) Unregister(account string) error {
|
||||
channelsStr, _ = tx.Get(channelsKey)
|
||||
tx.Delete(channelsKey)
|
||||
tx.Delete(joinedChannelsKey)
|
||||
tx.Delete(lastSignoffKey)
|
||||
|
||||
_, err := tx.Delete(vhostQueueKey)
|
||||
am.decrementVHostQueueCount(casefoldedAccount, err)
|
||||
|
@ -306,7 +306,7 @@ func (server *Server) RunClient(conn clientConn, proxyLine string) {
|
||||
client.run(session, proxyLine)
|
||||
}
|
||||
|
||||
func (server *Server) AddAlwaysOnClient(account ClientAccount, chnames []string) {
|
||||
func (server *Server) AddAlwaysOnClient(account ClientAccount, chnames []string, lastSignoff time.Time) {
|
||||
now := time.Now().UTC()
|
||||
config := server.Config()
|
||||
|
||||
@ -323,6 +323,7 @@ func (server *Server) AddAlwaysOnClient(account ClientAccount, chnames []string)
|
||||
realIP: utils.IPv4LoopbackAddress,
|
||||
|
||||
alwaysOn: true,
|
||||
lastSignoff: lastSignoff,
|
||||
}
|
||||
|
||||
client.SetMode(modes.TLS, true)
|
||||
@ -1187,10 +1188,17 @@ func (client *Client) destroy(session *Session) {
|
||||
}
|
||||
if alwaysOn && remainingSessions == 0 {
|
||||
client.lastSignoff = lastSignoff
|
||||
client.dirtyBits |= IncludeLastSignoff
|
||||
} else {
|
||||
lastSignoff = time.Time{}
|
||||
}
|
||||
exitedSnomaskSent := client.exitedSnomaskSent
|
||||
client.stateMutex.Unlock()
|
||||
|
||||
if !lastSignoff.IsZero() {
|
||||
client.wakeWriter()
|
||||
}
|
||||
|
||||
// destroy all applicable sessions:
|
||||
var quitMessage string
|
||||
for _, session := range sessionsToDestroy {
|
||||
@ -1573,6 +1581,7 @@ func (client *Client) historyStatus(config *Config) (persistent, ephemeral bool,
|
||||
// TODO add a dirty flag for lastSignoff
|
||||
const (
|
||||
IncludeChannels uint = 1 << iota
|
||||
IncludeLastSignoff
|
||||
)
|
||||
|
||||
func (client *Client) markDirty(dirtyBits uint) {
|
||||
@ -1609,7 +1618,7 @@ func (client *Client) writeLoop() {
|
||||
|
||||
func (client *Client) performWrite() {
|
||||
client.stateMutex.Lock()
|
||||
// TODO actually read dirtyBits in the future
|
||||
dirtyBits := client.dirtyBits
|
||||
client.dirtyBits = 0
|
||||
account := client.account
|
||||
client.stateMutex.Unlock()
|
||||
@ -1619,10 +1628,18 @@ func (client *Client) performWrite() {
|
||||
return
|
||||
}
|
||||
|
||||
if (dirtyBits & IncludeChannels) != 0 {
|
||||
channels := client.Channels()
|
||||
channelNames := make([]string, len(channels))
|
||||
for i, channel := range channels {
|
||||
channelNames[i] = channel.Name()
|
||||
}
|
||||
client.server.accounts.saveChannels(account, channelNames)
|
||||
}
|
||||
if (dirtyBits & IncludeLastSignoff) != 0 {
|
||||
client.stateMutex.RLock()
|
||||
lastSignoff := client.lastSignoff
|
||||
client.stateMutex.RUnlock()
|
||||
client.server.accounts.saveLastSignoff(account, lastSignoff)
|
||||
}
|
||||
}
|
||||
|
@ -94,6 +94,12 @@ func (client *Client) AllSessionData(currentSession *Session) (data []SessionDat
|
||||
}
|
||||
|
||||
func (client *Client) AddSession(session *Session) (success bool, numSessions int, lastSignoff time.Time) {
|
||||
defer func() {
|
||||
if !lastSignoff.IsZero() {
|
||||
client.wakeWriter()
|
||||
}
|
||||
}()
|
||||
|
||||
client.stateMutex.Lock()
|
||||
defer client.stateMutex.Unlock()
|
||||
|
||||
@ -111,6 +117,7 @@ func (client *Client) AddSession(session *Session) (success bool, numSessions in
|
||||
// on the server with no sessions:
|
||||
lastSignoff = client.lastSignoff
|
||||
client.lastSignoff = time.Time{}
|
||||
client.dirtyBits |= IncludeLastSignoff
|
||||
}
|
||||
client.sessions = newSessions
|
||||
return true, len(client.sessions), lastSignoff
|
||||
|
Loading…
Reference in New Issue
Block a user