Files
ttstd-infinite-canvas/backend/internal/app/text_replay_cache.go

53 lines
1.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package app
import (
"context"
"errors"
"time"
"infinite-canvas/backend/internal/model"
"infinite-canvas/backend/internal/platform"
)
type textReplayCacheKey struct {
userID, taskID string
after int64
}
func (s *Service) initReadCaches() {
s.readCachesOnce.Do(func() {
s.concurrencyReadCache = platform.NewBoundedReadCache[string, platform.RuntimeTaskPolicy](1, 1024, 1, 2*time.Second)
s.textReplayReadCache = platform.NewBoundedReadCache[textReplayCacheKey, *TextReplayResult](256, 8<<20, 8, 750*time.Millisecond)
s.routeVersionReadCache = platform.NewBoundedReadCache[string, int64](1, 1024, 1, 250*time.Millisecond)
})
}
// SSE 展示专用,不用于写路径和权限决策;userID 进入 key,回源仍检查任务归属。
// 游标保留在 key 中,避免重连读取到其他客户端已经越过的增量窗口。
func (s *Service) CachedTaskTextReplay(ctx context.Context, userID, taskID string, after int64) (*TextReplayResult, error) {
s.initReadCaches()
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
defer cancel()
value, err := s.textReplayReadCache.Get(ctx, textReplayCacheKey{userID, taskID, after}, func(ctx context.Context) (*TextReplayResult, int, error) {
reader := &Service{repo: s.repo.WithContext(ctx)}
value, err := reader.TaskTextReplay(userID, taskID, after)
if err != nil {
return nil, 0, err
}
bytes := 512 + len(value.TextDraft) + len(value.FinalText) + len(value.Error) + len(value.Stage)
for _, delta := range value.Deltas {
bytes += 256 + len(delta.Content) + len(delta.ID) + len(delta.UserID) + len(delta.TaskID)
}
return value, bytes, nil
})
if errors.Is(err, platform.ErrReadCacheBusy) {
return nil, &AppError{Status: 503, Code: 503, Message: "任务状态查询繁忙,请稍后重试", Retryable: true}
}
if err != nil {
return nil, err
}
copy := *value
copy.Deltas = append([]model.TaskTextDelta(nil), value.Deltas...)
return &copy, nil
}