mirror of
https://github.com/CJackHwang/ds2api.git
synced 2026-05-06 01:15:29 +08:00
110 lines
2.0 KiB
Go
110 lines
2.0 KiB
Go
package responses
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
|
|
"ds2api/internal/auth"
|
|
)
|
|
|
|
type storedResponse struct {
|
|
Owner string
|
|
Value map[string]any
|
|
ExpiresAt time.Time
|
|
}
|
|
|
|
type responseStore struct {
|
|
mu sync.Mutex
|
|
ttl time.Duration
|
|
items map[string]storedResponse
|
|
}
|
|
|
|
func newResponseStore(ttl time.Duration) *responseStore {
|
|
if ttl <= 0 {
|
|
ttl = 15 * time.Minute
|
|
}
|
|
return &responseStore{
|
|
ttl: ttl,
|
|
items: make(map[string]storedResponse),
|
|
}
|
|
}
|
|
|
|
func responseStoreKey(owner, id string) string {
|
|
return owner + "\x00" + id
|
|
}
|
|
|
|
func responseStoreOwner(a *auth.RequestAuth) string {
|
|
if a == nil {
|
|
return ""
|
|
}
|
|
return a.CallerID
|
|
}
|
|
|
|
func (s *responseStore) put(owner, id string, value map[string]any) {
|
|
if s == nil || owner == "" || id == "" || value == nil {
|
|
return
|
|
}
|
|
now := time.Now()
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
s.sweepLocked(now)
|
|
s.items[responseStoreKey(owner, id)] = storedResponse{
|
|
Owner: owner,
|
|
Value: cloneAnyMap(value),
|
|
ExpiresAt: now.Add(s.ttl),
|
|
}
|
|
}
|
|
|
|
func (s *responseStore) get(owner, id string) (map[string]any, bool) {
|
|
if s == nil || owner == "" || id == "" {
|
|
return nil, false
|
|
}
|
|
now := time.Now()
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
s.sweepLocked(now)
|
|
item, ok := s.items[responseStoreKey(owner, id)]
|
|
if !ok {
|
|
return nil, false
|
|
}
|
|
if item.Owner != owner {
|
|
return nil, false
|
|
}
|
|
return cloneAnyMap(item.Value), true
|
|
}
|
|
|
|
func (s *responseStore) sweepLocked(now time.Time) {
|
|
for k, v := range s.items {
|
|
if now.After(v.ExpiresAt) {
|
|
delete(s.items, k)
|
|
}
|
|
}
|
|
}
|
|
|
|
func cloneAnyMap(in map[string]any) map[string]any {
|
|
if in == nil {
|
|
return nil
|
|
}
|
|
out := make(map[string]any, len(in))
|
|
for k, v := range in {
|
|
out[k] = v
|
|
}
|
|
return out
|
|
}
|
|
|
|
func (h *Handler) getResponseStore() *responseStore {
|
|
if h == nil {
|
|
return nil
|
|
}
|
|
h.responsesMu.Lock()
|
|
defer h.responsesMu.Unlock()
|
|
if h.responses == nil {
|
|
ttl := 15 * time.Minute
|
|
if h.Store != nil {
|
|
ttl = time.Duration(h.Store.ResponsesStoreTTLSeconds()) * time.Second
|
|
}
|
|
h.responses = newResponseStore(ttl)
|
|
}
|
|
return h.responses
|
|
}
|