Download internal/upstream/idle.go from a3216/gcli2api: direct link, hf CLI and curl.
- Browser
- Download file 2.18 kB
-
https://huggingface.co/spaces/a3216/gcli2api/resolve/main/internal/upstream/idle.go
- Command line
-
hf download hf://spaces/a3216/gcli2api/internal/upstream/idle.go
-
curl -L -o idle.go https://huggingface.co/spaces/a3216/gcli2api/resolve/main/internal/upstream/idle.go
2.18 kB
| // idle.go 聊天 SSE 流中空闲监控:活跃吐数据续命不掐,静默超过阈值才断流(释放租约)。 | |
| package upstream | |
| import ( | |
| "context" | |
| "io" | |
| "sync" | |
| "time" | |
| ) | |
| // idleMonitoringBody 包在聊天 SSE body 外层: | |
| // 每次读到底层数据(n>0)就刷新 lastRead;后台 goroutine 周期检查, | |
| // 静默超过 idle 就 cancel 请求 context,中断阻塞中的 Read。 | |
| type idleMonitoringBody struct { | |
| rc io.ReadCloser | |
| mu sync.Mutex | |
| lastRead time.Time | |
| stopOnce sync.Once | |
| stopCh chan struct{} | |
| cancel context.CancelFunc | |
| } | |
| func (b *idleMonitoringBody) Read(p []byte) (int, error) { | |
| n, err := b.rc.Read(p) | |
| if n > 0 { | |
| b.mu.Lock() | |
| b.lastRead = time.Now() | |
| b.mu.Unlock() | |
| } | |
| return n, err | |
| } | |
| // Close 停掉后台 goroutine、取消请求 context、关闭底流,保证无泄漏。 | |
| func (b *idleMonitoringBody) Close() error { | |
| b.stopOnce.Do(func() { close(b.stopCh) }) | |
| b.cancel() | |
| return b.rc.Close() | |
| } | |
| func (b *idleMonitoringBody) idleFor() time.Duration { | |
| b.mu.Lock() | |
| defer b.mu.Unlock() | |
| return time.Since(b.lastRead) | |
| } | |
| // monitorBody 若 idle<=0 直接返回原底流(禁用空闲监控); | |
| // 否则包上流中空闲监控。计时从返回 body 之后开始——首字节阶段由 | |
| // Transport.ResponseHeaderTimeout 管,这里不抢跑。 | |
| func monitorBody(rc io.ReadCloser, idle time.Duration, cancel context.CancelFunc) io.ReadCloser { | |
| if idle <= 0 { | |
| return rc | |
| } | |
| b := &idleMonitoringBody{ | |
| rc: rc, | |
| lastRead: time.Now(), | |
| stopCh: make(chan struct{}), | |
| cancel: cancel, | |
| } | |
| go func() { | |
| t := time.NewTicker(idleTick(idle)) | |
| defer t.Stop() | |
| for { | |
| select { | |
| case <-b.stopCh: | |
| return | |
| case <-t.C: | |
| if b.idleFor() > idle { | |
| cancel() | |
| return | |
| } | |
| } | |
| } | |
| }() | |
| return b | |
| } | |
| // idleTick 返回监控周期:idle/4,钳在 [10ms, 1s]。小 idle 也能快速发现,大小值避免空转。 | |
| func idleTick(idle time.Duration) time.Duration { | |
| d := idle / 4 | |
| if d > time.Second { | |
| d = time.Second | |
| } | |
| if d < 10*time.Millisecond { | |
| d = 10 * time.Millisecond | |
| } | |
| return d | |
| } | |