mirror of
https://github.com/yusing/godoxy.git
synced 2026-04-23 16:58:31 +02:00
refactor(metrics): remove pointers from type parameter T to avoid unnecessary indirection
This commit is contained in:
@@ -6,7 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Entries[T any] struct {
|
type Entries[T any] struct {
|
||||||
entries [maxEntries]*T
|
entries [maxEntries]T
|
||||||
index int
|
index int
|
||||||
count int
|
count int
|
||||||
interval time.Duration
|
interval time.Duration
|
||||||
@@ -16,17 +16,14 @@ type Entries[T any] struct {
|
|||||||
const maxEntries = 100
|
const maxEntries = 100
|
||||||
|
|
||||||
func newEntries[T any](duration time.Duration) *Entries[T] {
|
func newEntries[T any](duration time.Duration) *Entries[T] {
|
||||||
interval := duration / maxEntries
|
interval := max(duration/maxEntries, time.Second)
|
||||||
if interval < time.Second {
|
|
||||||
interval = time.Second
|
|
||||||
}
|
|
||||||
return &Entries[T]{
|
return &Entries[T]{
|
||||||
interval: interval,
|
interval: interval,
|
||||||
lastAdd: time.Now(),
|
lastAdd: time.Now(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Entries[T]) Add(now time.Time, info *T) {
|
func (e *Entries[T]) Add(now time.Time, info T) {
|
||||||
if now.Sub(e.lastAdd) < e.interval {
|
if now.Sub(e.lastAdd) < e.interval {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -38,11 +35,11 @@ func (e *Entries[T]) Add(now time.Time, info *T) {
|
|||||||
e.lastAdd = now
|
e.lastAdd = now
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Entries[T]) Get() []*T {
|
func (e *Entries[T]) Get() []T {
|
||||||
if e.count < maxEntries {
|
if e.count < maxEntries {
|
||||||
return e.entries[:e.count]
|
return e.entries[:e.count]
|
||||||
}
|
}
|
||||||
res := make([]*T, maxEntries)
|
res := make([]T, maxEntries)
|
||||||
copy(res, e.entries[e.index:])
|
copy(res, e.entries[e.index:])
|
||||||
copy(res[maxEntries-e.index:], e.entries[:e.index])
|
copy(res[maxEntries-e.index:], e.entries[:e.index])
|
||||||
return res
|
return res
|
||||||
@@ -57,7 +54,7 @@ func (e *Entries[T]) MarshalJSON() ([]byte, error) {
|
|||||||
|
|
||||||
func (e *Entries[T]) UnmarshalJSON(data []byte) error {
|
func (e *Entries[T]) UnmarshalJSON(data []byte) error {
|
||||||
var v struct {
|
var v struct {
|
||||||
Entries []*T `json:"entries"`
|
Entries []T `json:"entries"`
|
||||||
Interval time.Duration `json:"interval"`
|
Interval time.Duration `json:"interval"`
|
||||||
}
|
}
|
||||||
if err := json.Unmarshal(data, &v); err != nil {
|
if err := json.Unmarshal(data, &v); err != nil {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package period
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
@@ -29,6 +30,7 @@ type ResponseType[AggregateT any] struct {
|
|||||||
//
|
//
|
||||||
// If the request is a websocket request, it serves the data for the given period for every interval.
|
// If the request is a websocket request, it serves the data for the given period for every interval.
|
||||||
func (p *Poller[T, AggregateT]) ServeHTTP(c *gin.Context) {
|
func (p *Poller[T, AggregateT]) ServeHTTP(c *gin.Context) {
|
||||||
|
period := Filter(c.Query("period"))
|
||||||
query := c.Request.URL.Query()
|
query := c.Request.URL.Query()
|
||||||
|
|
||||||
if httpheaders.IsWebsocket(c.Request.Header) {
|
if httpheaders.IsWebsocket(c.Request.Header) {
|
||||||
@@ -42,10 +44,10 @@ func (p *Poller[T, AggregateT]) ServeHTTP(c *gin.Context) {
|
|||||||
interval = minInterval
|
interval = minInterval
|
||||||
}
|
}
|
||||||
websocket.PeriodicWrite(c, interval, func() (any, error) {
|
websocket.PeriodicWrite(c, interval, func() (any, error) {
|
||||||
return p.getRespData(c.Request)
|
return p.getRespData(period, query)
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
data, err := p.getRespData(c.Request)
|
data, err := p.getRespData(period, query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Error(apitypes.InternalServerError(err, "failed to get response data"))
|
c.Error(apitypes.InternalServerError(err, "failed to get response data"))
|
||||||
return
|
return
|
||||||
@@ -58,13 +60,11 @@ func (p *Poller[T, AggregateT]) ServeHTTP(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Poller[T, AggregateT]) getRespData(r *http.Request) (any, error) {
|
func (p *Poller[T, AggregateT]) getRespData(period Filter, query url.Values) (any, error) {
|
||||||
query := r.URL.Query()
|
|
||||||
period := query.Get("period")
|
|
||||||
if period == "" {
|
if period == "" {
|
||||||
return p.GetLastResult(), nil
|
return p.GetLastResult(), nil
|
||||||
}
|
}
|
||||||
rangeData, ok := p.Get(Filter(period))
|
rangeData, ok := p.Get(period)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, errors.New("invalid period")
|
return nil, errors.New("invalid period")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ func NewPeriod[T any]() *Period[T] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Period[T]) Add(info *T) {
|
func (p *Period[T]) Add(info T) {
|
||||||
p.mu.Lock()
|
p.mu.Lock()
|
||||||
defer p.mu.Unlock()
|
defer p.mu.Unlock()
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
@@ -41,7 +41,7 @@ func (p *Period[T]) Add(info *T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Period[T]) Get(filter Filter) ([]*T, bool) {
|
func (p *Period[T]) Get(filter Filter) ([]T, bool) {
|
||||||
p.mu.RLock()
|
p.mu.RLock()
|
||||||
defer p.mu.RUnlock()
|
defer p.mu.RUnlock()
|
||||||
period, ok := p.Entries[filter]
|
period, ok := p.Entries[filter]
|
||||||
|
|||||||
@@ -17,16 +17,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
PollFunc[T any] func(ctx context.Context, lastResult *T) (*T, error)
|
PollFunc[T any] func(ctx context.Context, lastResult T) (T, error)
|
||||||
AggregateFunc[T any, AggregateT json.Marshaler] func(entries []*T, query url.Values) (total int, result AggregateT)
|
AggregateFunc[T any, AggregateT json.Marshaler] func(entries []T, query url.Values) (total int, result AggregateT)
|
||||||
FilterFunc[T any] func(entries []*T, keyword string) (filtered []*T)
|
FilterFunc[T any] func(entries []T, keyword string) (filtered []T)
|
||||||
Poller[T any, AggregateT json.Marshaler] struct {
|
Poller[T any, AggregateT json.Marshaler] struct {
|
||||||
name string
|
name string
|
||||||
poll PollFunc[T]
|
poll PollFunc[T]
|
||||||
aggregate AggregateFunc[T, AggregateT]
|
aggregate AggregateFunc[T, AggregateT]
|
||||||
resultFilter FilterFunc[T]
|
resultFilter FilterFunc[T]
|
||||||
period *Period[T]
|
period *Period[T]
|
||||||
lastResult atomic.Value[*T]
|
lastResult atomic.Value[T]
|
||||||
errs []pollErr
|
errs []pollErr
|
||||||
}
|
}
|
||||||
pollErr struct {
|
pollErr struct {
|
||||||
@@ -188,10 +188,10 @@ func (p *Poller[T, AggregateT]) Start() {
|
|||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Poller[T, AggregateT]) Get(filter Filter) ([]*T, bool) {
|
func (p *Poller[T, AggregateT]) Get(filter Filter) ([]T, bool) {
|
||||||
return p.period.Get(filter)
|
return p.period.Get(filter)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Poller[T, AggregateT]) GetLastResult() *T {
|
func (p *Poller[T, AggregateT]) GetLastResult() T {
|
||||||
return p.lastResult.Load()
|
return p.lastResult.Load()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user