Skip to content

Commit c88b967

Browse files
authored
Merge pull request #6 from FishGoddess/develop
v0.2.4
2 parents dfb309d + 39e2bd7 commit c88b967

File tree

7 files changed

+115
-64
lines changed

7 files changed

+115
-64
lines changed

FUTURE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
### v0.3.x
44

5+
* [ ] 使用令牌+链表的方式实现
56
* [ ] 增加生命周期检测,资源检查回调
67

78
### v0.2.x

HISTORY.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
## 📜 历史版本的特性介绍
22

3+
### v0.2.4
4+
5+
> 此版本发布于 2025-05-03
6+
7+
* 修复 DefaultReleaseFunc 定义错误的问题
8+
* 调整平均等待时间的上报逻辑
9+
310
### v0.2.3
411

512
> 此版本发布于 2025-05-03

_icons/coverage.svg

Lines changed: 2 additions & 2 deletions
Loading

pool.go

Lines changed: 13 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,12 @@ import (
1010
"time"
1111
)
1212

13-
// Status is the statistics of pool.
14-
type Status struct {
15-
// Limit is the maximum quantity of resources in pool.
16-
Limit uint64 `json:"limit"`
13+
var _ ReleaseFunc[int] = DefaultReleaseFunc[int]
1714

18-
// Active is the quantity of resources in pool including idle and using.
19-
Active uint64 `json:"active"`
20-
21-
// Idle is the quantity of idle resources in pool.
22-
Idle uint64 `json:"idle"`
23-
24-
// Waiting is the quantity of waiting for a resource.
25-
Waiting uint64 `json:"waiting"`
26-
27-
// AverageWaitDuration is the average wait duration for new resources.
28-
AverageWaitDuration time.Duration `json:"average_wait_duration"`
15+
// DefaultReleaseFunc is a default func to release a resource.
16+
// It does nothing to the resource.
17+
func DefaultReleaseFunc[T any](ctx context.Context, resource T) error {
18+
return nil
2919
}
3020

3121
// AcquireFunc is a function acquires a new resource and returns error if failed.
@@ -34,12 +24,6 @@ type AcquireFunc[T any] func(ctx context.Context) (T, error)
3424
// ReleaseFunc is a function releases a resource and returns error if failed.
3525
type ReleaseFunc[T any] func(ctx context.Context, resource T) error
3626

37-
// DefaultReleaseFunc is a default func to release a resource.
38-
// It does nothing to the resource.
39-
func DefaultReleaseFunc[T any](resource T) error {
40-
return nil
41-
}
42-
4327
// Pool stores resources for reusing.
4428
type Pool[T any] struct {
4529
conf config
@@ -51,7 +35,7 @@ type Pool[T any] struct {
5135
active uint64
5236
waiting uint64
5337

54-
totalTaken uint64
38+
totalWaited uint64
5539
totalWaitedDuration time.Duration
5640

5741
resources chan T
@@ -140,8 +124,6 @@ func (p *Pool[T]) Take(ctx context.Context) (resource T, err error) {
140124
return resource, err
141125
}
142126

143-
p.totalTaken++
144-
145127
var ok bool
146128
if resource, ok = p.tryToTake(); ok {
147129
p.lock.Unlock()
@@ -183,24 +165,25 @@ func (p *Pool[T]) Take(ctx context.Context) (resource T, err error) {
183165

184166
p.lock.Lock()
185167
p.waiting--
168+
p.totalWaited++
186169
p.totalWaitedDuration += waitDuration
187170
p.lock.Unlock()
188171
}()
189172

190173
return p.waitToTake(ctx)
191174
}
192175

193-
// Status returns the status of the pool.
194-
func (p *Pool[T]) Status() Status {
176+
// Status returns the statistics of the pool.
177+
func (p *Pool[T]) Status() PoolStatus {
195178
p.lock.RLock()
196179
defer p.lock.RUnlock()
197180

198181
var averageWaitDuration time.Duration
199-
if p.totalTaken > 0 {
200-
averageWaitDuration = p.totalWaitedDuration / time.Duration(p.totalTaken)
182+
if p.totalWaited > 0 {
183+
averageWaitDuration = p.totalWaitedDuration / time.Duration(p.totalWaited)
201184
}
202185

203-
status := Status{
186+
status := PoolStatus{
204187
Limit: p.limit,
205188
Active: p.active,
206189
Idle: uint64(len(p.resources)),
@@ -239,7 +222,7 @@ func (p *Pool[T]) Close(ctx context.Context) error {
239222

240223
p.active = 0
241224
p.waiting = 0
242-
p.totalTaken = 0
225+
p.totalWaited = 0
243226
p.totalWaitedDuration = 0
244227
p.closed = true
245228

pool_test.go

Lines changed: 14 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,7 @@ func TestPool(t *testing.T) {
7171
}
7272
}()
7373

74-
totalTaken1 := 1024
75-
for i := 0; i < totalTaken1; i++ {
74+
for i := 0; i < 1024; i++ {
7675
resource, err := pool.Take(ctx)
7776
if err != nil {
7877
t.Fatal(err)
@@ -97,17 +96,17 @@ func TestPool(t *testing.T) {
9796

9897
t.Logf("%+v", pool.Status())
9998

100-
if pool.totalTaken != uint64(totalTaken1) {
101-
t.Fatalf("pool.totalTaken %d is wrong", pool.totalTaken)
99+
if pool.totalWaited != 0 {
100+
t.Fatalf("pool.totalWaited %d is wrong", pool.totalWaited)
102101
}
103102

104103
if pool.totalWaitedDuration != 0 {
105104
t.Fatalf("pool.totalWaitedDuration %d is wrong", pool.totalWaitedDuration)
106105
}
107106

107+
var totalWaited = 65536
108108
var wg sync.WaitGroup
109-
totalTaken2 := 65536
110-
for i := 0; i < totalTaken2; i++ {
109+
for i := 0; i < totalWaited; i++ {
111110
wg.Add(1)
112111
go func() {
113112
defer wg.Done()
@@ -131,39 +130,22 @@ func TestPool(t *testing.T) {
131130
t.Errorf("status.Idle %d is wrong", status.Idle)
132131
return
133132
}
133+
134+
if status.Waiting > 0 && pool.totalWaited > 0 && status.AverageWaitDuration <= 0 {
135+
t.Errorf("status.AverageWaitDuration %d is wrong", status.AverageWaitDuration)
136+
return
137+
}
134138
}()
135139
}
136140

137141
wg.Wait()
138142
t.Logf("%+v", pool.Status())
139143

140-
if pool.totalTaken != uint64(totalTaken1)+uint64(totalTaken2) {
141-
t.Fatalf("pool.totalTaken %d is wrong", pool.totalTaken)
144+
if pool.totalWaited > uint64(totalWaited) {
145+
t.Fatalf("pool.totalWaited %d is wrong", pool.totalWaited)
142146
}
143147

144-
totalTaken1 = 4096
145-
for i := 0; i < totalTaken1; i++ {
146-
resource, err := pool.Take(ctx)
147-
if err != nil {
148-
t.Fatal(err)
149-
}
150-
151-
time.Sleep(time.Millisecond)
152-
pool.Put(ctx, resource)
153-
154-
status := pool.Status()
155-
if status.Active != uint64(limit) {
156-
t.Fatalf("status.Active %d is wrong", status.Active)
157-
}
158-
159-
if status.Idle != uint64(limit) {
160-
t.Fatalf("status.Idle %d is wrong", status.Idle)
161-
}
162-
163-
if status.AverageWaitDuration == 0 {
164-
t.Fatalf("status.AverageWaitDuration %d is wrong", status.AverageWaitDuration)
165-
}
148+
if pool.totalWaited > 0 && pool.totalWaitedDuration <= 0 {
149+
t.Fatalf("pool.totalWaitedDuration %d is wrong", pool.totalWaitedDuration)
166150
}
167-
168-
t.Logf("%+v", pool.Status())
169151
}

status.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2025 FishGoddess. All rights reserved.
2+
// Use of this source code is governed by a MIT style
3+
// license that can be found in the LICENSE file.
4+
5+
package rego
6+
7+
import "time"
8+
9+
// PoolStatus is the statistics of pool.
10+
type PoolStatus struct {
11+
// Limit is the maximum quantity of resources in pool.
12+
Limit uint64 `json:"limit"`
13+
14+
// Active is the quantity of resources in pool including idle and using.
15+
Active uint64 `json:"active"`
16+
17+
// Idle is the quantity of idle resources in pool.
18+
Idle uint64 `json:"idle"`
19+
20+
// Waiting is the quantity of waiting for a resource.
21+
Waiting uint64 `json:"waiting"`
22+
23+
// AverageWaitDuration is the average wait duration for new resources.
24+
AverageWaitDuration time.Duration `json:"average_wait_duration"`
25+
}

status_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright 2025 FishGoddess. All rights reserved.
2+
// Use of this source code is governed by a MIT style
3+
// license that can be found in the LICENSE file.
4+
5+
package rego
6+
7+
import (
8+
"context"
9+
"testing"
10+
"time"
11+
)
12+
13+
// go test -v -cover -run=^TestPoolStatus$
14+
func TestPoolStatus(t *testing.T) {
15+
limit := 16
16+
17+
pool := &Pool[int]{
18+
limit: uint64(limit),
19+
release: DefaultReleaseFunc[int],
20+
active: 4,
21+
waiting: 8,
22+
totalWaited: 0,
23+
totalWaitedDuration: 0,
24+
resources: make(chan int, limit),
25+
}
26+
27+
ctx := context.Background()
28+
defer pool.Close(ctx)
29+
30+
for i := range limit {
31+
pool.resources <- i
32+
}
33+
34+
poolStatus := PoolStatus{
35+
Limit: pool.limit,
36+
Active: pool.active,
37+
Idle: uint64(len(pool.resources)),
38+
Waiting: pool.waiting,
39+
AverageWaitDuration: 0,
40+
}
41+
42+
if pool.Status() != poolStatus {
43+
t.Fatalf("pool.Status %+v != %+v", pool.Status(), poolStatus)
44+
}
45+
46+
pool.totalWaited = 2
47+
pool.totalWaitedDuration = time.Second
48+
poolStatus.AverageWaitDuration = pool.totalWaitedDuration / time.Duration(pool.totalWaited)
49+
50+
if pool.Status() != poolStatus {
51+
t.Fatalf("pool.Status %+v != %+v", pool.Status(), poolStatus)
52+
}
53+
}

0 commit comments

Comments
 (0)