add function to drop items taken from but not returned to the pool
This commit is contained in:
parent
8cbcba8458
commit
cde2ec1e6c
31
lib.go
31
lib.go
@ -31,6 +31,10 @@ type Stats struct {
|
||||
// Put is the number of put operations during the entire life cycle of the pool.
|
||||
Put int
|
||||
|
||||
// Drop is the number of items dropped without putting them back into the pool, during the entire life
|
||||
// cycle of the pool.
|
||||
Drop int
|
||||
|
||||
// Alloc is the number of allocations executed by the pool during the entire life cycle of the pool.
|
||||
Alloc int
|
||||
|
||||
@ -56,6 +60,9 @@ const (
|
||||
// PutOperation is the type of events sent after a put operation.
|
||||
PutOperation
|
||||
|
||||
// DropOperation is the type of events sent after a drop operation.
|
||||
DropOperation
|
||||
|
||||
// AllocateOperation is the type of events sent after an allocate operation.
|
||||
AllocateOperation
|
||||
|
||||
@ -70,7 +77,13 @@ const (
|
||||
AllocateError
|
||||
|
||||
// AllEvents can be used as a mask that includes all the event types.
|
||||
AllEvents = GetOperation | PutOperation | AllocateOperation | LoadOperation | FreeOperation | AllocateError
|
||||
AllEvents = GetOperation |
|
||||
PutOperation |
|
||||
DropOperation |
|
||||
AllocateOperation |
|
||||
LoadOperation |
|
||||
FreeOperation |
|
||||
AllocateError
|
||||
)
|
||||
|
||||
// Event values are sent by the pool after various operations, if a channel is provided to send the events to.
|
||||
@ -156,6 +169,10 @@ func (et EventType) String() string {
|
||||
s = append(s, "put")
|
||||
}
|
||||
|
||||
if et&DropOperation != 0 {
|
||||
s = append(s, "drop")
|
||||
}
|
||||
|
||||
if et&AllocateOperation != 0 {
|
||||
s = append(s, "allocate")
|
||||
}
|
||||
@ -187,11 +204,12 @@ func (ev Event) String() string {
|
||||
// String returns the string representation of a set of statistics about the pool.
|
||||
func (s Stats) String() string {
|
||||
return fmt.Sprintf(
|
||||
"idle: %d, active: %d, get: %d, put: %d, alloc: %d, load: %d, free: %d",
|
||||
"idle: %d, active: %d, get: %d, put: %d, drop: %d, alloc: %d, load: %d, free: %d",
|
||||
s.Idle,
|
||||
s.Active,
|
||||
s.Get,
|
||||
s.Put,
|
||||
s.Drop,
|
||||
s.Alloc,
|
||||
s.Load,
|
||||
s.Free,
|
||||
@ -272,6 +290,15 @@ func (p Pool[R]) Put(i R) {
|
||||
p.pool.put(i)
|
||||
}
|
||||
|
||||
// Drop indicates to the pool that an item received by Get was dropped and will not be put back into the pool.
|
||||
//
|
||||
// While it's not mandatory call it when item was dropped, it has a twofold purpose. Depending on the shrinking
|
||||
// algorithm, it may work more consistently, if the algorithm is notified about the change in the active items.
|
||||
// The other purpose is to allow the pool to reflect these cases in the events and the stats.
|
||||
func (p Pool[R]) Drop() {
|
||||
p.pool.drop()
|
||||
}
|
||||
|
||||
// Load can be used to populate the pool with items that were not allocated as the result of the Get operation.
|
||||
// It can be useful in scenarios where prewarming or preparing for a sudden traffic spike is necessary. If
|
||||
// events were configured, it triggers a LoadOperation event.
|
||||
|
||||
26
pool.go
26
pool.go
@ -146,6 +146,32 @@ func (p pool[R]) put(r R) {
|
||||
}
|
||||
}
|
||||
|
||||
func (p pool[R]) drop() {
|
||||
s := <-p.state
|
||||
defer func() {
|
||||
p.state <- s
|
||||
}()
|
||||
|
||||
var event EventType
|
||||
event |= DropOperation
|
||||
s.stats.Drop++
|
||||
if s.stats.Active > 0 {
|
||||
s.stats.Active--
|
||||
}
|
||||
|
||||
t, f := p.options.Algo.Target(s.stats)
|
||||
if t < len(s.items) {
|
||||
event |= FreeOperation
|
||||
s = p.freeItems(s, t)
|
||||
}
|
||||
|
||||
s.stats.Idle = len(s.items)
|
||||
p.sendEvent(event, s.stats)
|
||||
if f > 0 {
|
||||
s = p.forcedCheck(s, f)
|
||||
}
|
||||
}
|
||||
|
||||
func (p pool[R]) load(i []R) {
|
||||
s := <-p.state
|
||||
defer func() {
|
||||
|
||||
19
pool_test.go
19
pool_test.go
@ -323,4 +323,23 @@ func TestPool(t *testing.T) {
|
||||
t.Fatal(s)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("drop", func(t *testing.T) {
|
||||
alloc := func() ([]byte, error) { return make([]byte, 1<<9), nil }
|
||||
p := pool.Make(alloc, nil, pool.Options{})
|
||||
_, err := p.Get()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
s := p.Stats()
|
||||
e := pool.Stats{Alloc: 1, Get: 1, Active: 1}
|
||||
if s != e {
|
||||
t.Fatal(s)
|
||||
}
|
||||
|
||||
p.Drop()
|
||||
s = p.Stats()
|
||||
e = pool.Stats{Alloc: 1, Get: 1, Drop: 1}
|
||||
})
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user