Atlas › Test
TestCleanup
Exact test identity: go.temporal.io/server/common/quotas/TestMapRequestRateLimiterSuite/TestCleanup
- Package
go.temporal.io/server/common/quotas
- Suite / test hierarchy
TestMapRequestRateLimiterSuite/TestCleanup
- Test
TestCleanup
- Introduced at
- map_request_rate_limiter_impl.go ×2 Frontier kind: Joint frontier
- Covered ranges
- 10
- Covered lines
- 59
- Covered files
- 2
Covered source
Expand a file to inspect source; the > gutter marks covered lines.
go.temporal.io/server/common/quotas/map_request_rate_limiter_impl.go 56 covered LOC · 9 ranges
Open complete file
40
rateLimiterGenFn RequestRateLimiterFn,
41
rateLimiterKeyFn RequestRateLimiterKeyFn[K],
43
>
return &MapRequestRateLimiterImpl[K]{
44
>
rateLimiterGenFn: rateLimiterGenFn,
45
>
rateLimiterKeyFn: rateLimiterKeyFn,
46
>
rateLimiters: make(map[K]*rateLimiterEntry),
47
>
ttlNano: int64(rateLimiterTTL),
48
>
cleanupTicker: time.NewTicker(rateLimiterCleanupInterval),
49
>
}
50
>
}
51
52
func namespaceRequestRateLimiterKeyFn(req Request) string {
66
now time.Time,
67
request Request,
69
>
rateLimiter := r.getOrInitRateLimiter(now, request)
70
>
return rateLimiter.Allow(now, request)
71
>
}
72
73
// Reserve returns a Reservation that indicates how long the caller
94
now time.Time,
95
req Request,
97
>
r.maybeCleanup(now)
98
>
99
>
key := r.rateLimiterKeyFn(req)
100
>
nowNano := now.UnixNano()
101
>
102
>
r.RLock()
103
>
entry, ok := r.rateLimiters[key]
104
>
r.RUnlock()
105
>
106
>
if ok {
107
entry.lastAccess.Store(nowNano)
108
return entry.rateLimiter
109
}
110
112
>
r.Lock()
113
>
defer r.Unlock()
114
>
115
>
if entry, ok := r.rateLimiters[key]; ok {
116
entry.lastAccess.Store(nowNano)
117
return entry.rateLimiter
118
}
119
121
>
entry.lastAccess.Store(nowNano)
122
>
r.rateLimiters[key] = entry
123
>
return newRateLimiter
124
}
125
127
// receive drains at most one ticker tick, so only one sweeper starts even if many
128
// callers reach here at once.
130
>
select {
131
case <-r.cleanupTicker.C:
132
go r.cleanup(now)
134
}
135
}
139
// 2. For each candidate: Lock, re-check, delete, Unlock
140
// This ensures read operations are only briefly blocked during actual deletions.
142
>
nowNano := now.UnixNano()
143
>
ttlNano := r.ttlNano
144
>
145
>
// Phase 1: collect expired keys under read lock
146
>
var expiredKeys []K
147
>
r.RLock()
148
>
for k, e := range r.rateLimiters {
149
>
if nowNano-e.lastAccess.Load() > ttlNano {
150
>
expiredKeys = append(expiredKeys, k)
151
>
}
152
}
154
>
155
>
// Phase 2: delete each expired key individually
156
>
for _, k := range expiredKeys {
157
>
r.Lock()
158
>
if e, ok := r.rateLimiters[k]; ok && nowNano-e.lastAccess.Load() > ttlNano {
159
>
delete(r.rateLimiters, k)
160
>
}
161
>
r.Unlock()
162
}
163
}
go.temporal.io/server/common/quotas/noop_request_rate_limiter_impl.go 3 covered LOC · 1 range
Open complete file
16
_ time.Time,
17
_ Request,
19
>
return true
20
>
}
21
22
func (r *NoopRequestRateLimiterImpl) Reserve(