39 lines
817 B
Go
39 lines
817 B
Go
package agent
|
|
|
|
import "context"
|
|
|
|
type conversationLock struct {
|
|
gate chan struct{}
|
|
users int
|
|
}
|
|
|
|
// Serialize turns within each conversation while allowing different chats to stream.
|
|
func (s *Service) lockConversation(ctx context.Context, id string) (func(), error) {
|
|
s.chatMu.Lock()
|
|
if s.chatLocks == nil {
|
|
s.chatLocks = make(map[string]*conversationLock)
|
|
}
|
|
lock := s.chatLocks[id]
|
|
if lock == nil {
|
|
lock = &conversationLock{gate: make(chan struct{}, 1)}
|
|
s.chatLocks[id] = lock
|
|
}
|
|
lock.users++
|
|
s.chatMu.Unlock()
|
|
releaseRef := func() {
|
|
s.chatMu.Lock()
|
|
lock.users--
|
|
if lock.users == 0 {
|
|
delete(s.chatLocks, id)
|
|
}
|
|
s.chatMu.Unlock()
|
|
}
|
|
select {
|
|
case lock.gate <- struct{}{}:
|
|
return func() { <-lock.gate; releaseRef() }, nil
|
|
case <-ctx.Done():
|
|
releaseRef()
|
|
return nil, ctx.Err()
|
|
}
|
|
}
|