package mediaapi import "sync" // waiters wakes the downloads blocked on a reserved media ID when its // content arrives. // // It is in memory, which is enough for one process: the upload and the // download that waits for it are both requests to this server. type waiters struct { mu sync.Mutex next uint64 subs map[string]map[uint64]chan struct{} } func newWaiters() *waiters { return &waiters{subs: map[string]map[uint64]chan struct{}{}} } // subscribe returns a channel closed when the media's content arrives, and // a function to call when no longer waiting. func (w *waiters) subscribe(origin, mediaID string) (<-chan struct{}, func()) { key := origin + "/" + mediaID ch := make(chan struct{}) w.mu.Lock() defer w.mu.Unlock() w.next++ id := w.next if w.subs[key] == nil { w.subs[key] = map[uint64]chan struct{}{} } w.subs[key][id] = ch return ch, func() { w.mu.Lock() defer w.mu.Unlock() if subs := w.subs[key]; subs != nil { delete(subs, id) if len(subs) == 0 { delete(w.subs, key) } } } } // wake releases everybody waiting for the media. func (w *waiters) wake(origin, mediaID string) { key := origin + "/" + mediaID w.mu.Lock() defer w.mu.Unlock() for _, ch := range w.subs[key] { close(ch) } delete(w.subs, key) }