mirror of
https://github.com/yusing/godoxy.git
synced 2025-05-20 04:42:33 +02:00

* chore: replace gopkg.in/yaml.v3 vs goccy/go-yaml; replace encoding/json with bytedance/sonic * fix: yaml unmarshal panic * feat: custom json marshaler implementation * chore: fix import and err marshal handling --------- Co-authored-by: yusing <yusing@6uo.me>
80 lines
1.5 KiB
Go
80 lines
1.5 KiB
Go
package period
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/yusing/go-proxy/pkg/json"
|
|
)
|
|
|
|
type Entries[T any] struct {
|
|
entries [maxEntries]*T
|
|
index int
|
|
count int
|
|
interval time.Duration
|
|
lastAdd time.Time
|
|
}
|
|
|
|
const maxEntries = 100
|
|
|
|
func newEntries[T any](duration time.Duration) *Entries[T] {
|
|
interval := duration / maxEntries
|
|
if interval < time.Second {
|
|
interval = time.Second
|
|
}
|
|
return &Entries[T]{
|
|
interval: interval,
|
|
lastAdd: time.Now(),
|
|
}
|
|
}
|
|
|
|
func (e *Entries[T]) Add(now time.Time, info *T) {
|
|
if now.Sub(e.lastAdd) < e.interval {
|
|
return
|
|
}
|
|
e.entries[e.index] = info
|
|
e.index = (e.index + 1) % maxEntries
|
|
if e.count < maxEntries {
|
|
e.count++
|
|
}
|
|
e.lastAdd = now
|
|
}
|
|
|
|
func (e *Entries[T]) Get() []*T {
|
|
if e.count < maxEntries {
|
|
return e.entries[:e.count]
|
|
}
|
|
res := make([]*T, maxEntries)
|
|
copy(res, e.entries[e.index:])
|
|
copy(res[maxEntries-e.index:], e.entries[:e.index])
|
|
return res
|
|
}
|
|
|
|
func (e *Entries[T]) MarshalJSONTo(buf []byte) []byte {
|
|
return json.MarshalTo(map[string]any{
|
|
"entries": e.Get(),
|
|
"interval": e.interval,
|
|
}, buf)
|
|
}
|
|
|
|
func (e *Entries[T]) UnmarshalJSON(data []byte) error {
|
|
var v struct {
|
|
Entries []*T `json:"entries"`
|
|
Interval time.Duration `json:"interval"`
|
|
}
|
|
if err := json.Unmarshal(data, &v); err != nil {
|
|
return err
|
|
}
|
|
if len(v.Entries) == 0 {
|
|
return nil
|
|
}
|
|
entries := v.Entries
|
|
if len(entries) > maxEntries {
|
|
entries = entries[:maxEntries]
|
|
}
|
|
now := time.Now()
|
|
for _, info := range entries {
|
|
e.Add(now, info)
|
|
}
|
|
e.interval = v.Interval
|
|
return nil
|
|
}
|