1
0
Fork 0
mirror of https://github.com/anyproto/any-sync.git synced 2025-06-09 17:45:03 +09:00
any-sync/commonspace/sync/requestpool.go
2024-06-24 21:29:16 +02:00

84 lines
1.7 KiB
Go

package sync
import (
"context"
"sync"
)
type RequestPool interface {
TryTake(peerId, objectId string) bool
Release(peerId, objectId string)
QueueRequestAction(peerId, objectId string, action func(ctx context.Context), remove func()) (err error)
Close()
}
type requestPool struct {
mu sync.Mutex
peerGuard *guard
pools map[string]*tryAddQueue
ctx context.Context
cancel context.CancelFunc
isClosed bool
}
func NewRequestPool() RequestPool {
ctx, cancel := context.WithCancel(context.Background())
return &requestPool{
ctx: ctx,
cancel: cancel,
pools: make(map[string]*tryAddQueue),
peerGuard: newGuard(),
}
}
func (rp *requestPool) TryTake(peerId, objectId string) bool {
rp.mu.Lock()
defer rp.mu.Unlock()
if rp.isClosed {
return false
}
return rp.peerGuard.TryTake(fullId(peerId, objectId))
}
func (rp *requestPool) Release(peerId, objectId string) {
rp.peerGuard.Release(fullId(peerId, objectId))
}
func (rp *requestPool) QueueRequestAction(peerId, objectId string, action func(ctx context.Context), remove func()) (err error) {
rp.mu.Lock()
if rp.isClosed {
rp.mu.Unlock()
return nil
}
var (
pool *tryAddQueue
exists bool
)
pool, exists = rp.pools[peerId]
if !exists {
pool = newTryAddQueue(100, 100)
rp.pools[peerId] = pool
pool.Run()
}
rp.mu.Unlock()
var wrappedAction func()
wrappedAction = func() {
if !rp.TryTake(peerId, objectId) {
return
}
action(rp.ctx)
rp.Release(peerId, objectId)
}
pool.Replace(objectId, wrappedAction, remove)
return nil
}
func (rp *requestPool) Close() {
rp.mu.Lock()
defer rp.mu.Unlock()
rp.isClosed = true
for _, pool := range rp.pools {
_ = pool.Close()
}
}