mirror of
https://github.com/tiennm99/goclaw.git
synced 2026-10-04 14:13:15 +00:00
98 lines
2.3 KiB
Go
98 lines
2.3 KiB
Go
package replycontext
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func scopedKey(scope Scope, messageID string) cacheKey {
|
|
return cacheKey{
|
|
tenant: strings.TrimSpace(scope.TenantID),
|
|
channel: strings.TrimSpace(scope.ChannelID),
|
|
thread: strings.TrimSpace(scope.ThreadID),
|
|
message: strings.TrimSpace(messageID),
|
|
}
|
|
}
|
|
|
|
func (c *Cache) lookupLocked(scope Scope, ids []string) *node {
|
|
for _, id := range ids {
|
|
key := scopedKey(scope, id)
|
|
if canonical, ok := c.aliases[key]; ok {
|
|
return c.nodes[canonical]
|
|
}
|
|
if n := c.nodes[key]; n != nil {
|
|
return n
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (c *Cache) collectChainLocked(scope Scope, start *node) []renderMessage {
|
|
visited := make(map[cacheKey]struct{}, c.opts.MaxDepth)
|
|
reversed := make([]renderMessage, 0, c.opts.MaxDepth)
|
|
for n := start; n != nil && len(reversed) < c.opts.MaxDepth; {
|
|
if _, ok := visited[n.key]; ok {
|
|
break
|
|
}
|
|
visited[n.key] = struct{}{}
|
|
reversed = append(reversed, renderMessage{sender: n.sender, body: n.body})
|
|
parent := c.lookupLocked(scope, n.parentIDs)
|
|
if parent == nil && len(reversed) < c.opts.MaxDepth {
|
|
if fallback := n.parentFallback(); fallback.body != "" {
|
|
reversed = append(reversed, fallback)
|
|
}
|
|
}
|
|
n = parent
|
|
}
|
|
|
|
for i, j := 0, len(reversed)-1; i < j; i, j = i+1, j-1 {
|
|
reversed[i], reversed[j] = reversed[j], reversed[i]
|
|
}
|
|
return reversed
|
|
}
|
|
|
|
func (n *node) parentFallback() renderMessage {
|
|
return renderMessage{
|
|
sender: n.parentQuote.Sender,
|
|
body: n.parentQuote.Body,
|
|
}
|
|
}
|
|
|
|
func (c *Cache) purgeExpiredLocked(now time.Time) {
|
|
if c.opts.TTL <= 0 {
|
|
return
|
|
}
|
|
for key, n := range c.nodes {
|
|
if now.Sub(n.createdAt) > c.opts.TTL {
|
|
c.deleteNodeLocked(key, n)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (c *Cache) evictLocked() {
|
|
for len(c.nodes) > c.opts.MaxEntries {
|
|
var oldestKey cacheKey
|
|
var oldest *node
|
|
for key, n := range c.nodes {
|
|
if oldest == nil || n.createdAt.Before(oldest.createdAt) {
|
|
oldestKey = key
|
|
oldest = n
|
|
}
|
|
}
|
|
if oldest == nil {
|
|
return
|
|
}
|
|
c.deleteNodeLocked(oldestKey, oldest)
|
|
}
|
|
}
|
|
|
|
func (c *Cache) deleteNodeLocked(key cacheKey, n *node) {
|
|
delete(c.nodes, key)
|
|
for _, id := range n.ids {
|
|
aliasKey := cacheKey{tenant: key.tenant, channel: key.channel, thread: key.thread, message: id}
|
|
if c.aliases[aliasKey] == key {
|
|
delete(c.aliases, aliasKey)
|
|
}
|
|
}
|
|
}
|