162 lines
3.6 KiB
Go
162 lines
3.6 KiB
Go
|
|
package mqe
|
||
|
|
|
||
|
|
import (
|
||
|
|
"sync"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"gordenko.dev/dima/qx"
|
||
|
|
)
|
||
|
|
|
||
|
|
type GroupBy string
|
||
|
|
|
||
|
|
// Для парсинга since и until
|
||
|
|
const (
|
||
|
|
NoAggregateFunc byte = 1
|
||
|
|
AggregateMin byte = 2
|
||
|
|
AggregateMax byte = 4
|
||
|
|
AggregateAvg byte = 8
|
||
|
|
|
||
|
|
ByHour GroupBy = "h"
|
||
|
|
ByDay GroupBy = "d"
|
||
|
|
ByMonth GroupBy = "m"
|
||
|
|
|
||
|
|
hourPeriodLayout = "2006010215"
|
||
|
|
dayPeriodLayout = "20060102"
|
||
|
|
monthPeriodLayout = "200601"
|
||
|
|
|
||
|
|
dateLayout = "2006-01-02"
|
||
|
|
)
|
||
|
|
|
||
|
|
type MetricMeasuresFilter struct {
|
||
|
|
MetricID int64 `json:"metricID"`
|
||
|
|
Since int64 `json:"since"` // уже учтен firstHourOfDay
|
||
|
|
Until int64 `json:"until"` // уже учтен firstHourOfDay
|
||
|
|
}
|
||
|
|
|
||
|
|
type MeasureQueryEngine struct {
|
||
|
|
db *qx.Db
|
||
|
|
location *time.Location
|
||
|
|
cumulativeCh chan *CumulativeTask
|
||
|
|
instantCh chan *InstantTask
|
||
|
|
aggregatedCumulativeCh chan *AggregatedCumulativeTask
|
||
|
|
aggregatedInstantCh chan *AggregatedInstantTask
|
||
|
|
cumulativeTotalCh chan *CumulativeTotalTask
|
||
|
|
metricReadingsCh chan *MetricReadingsTask
|
||
|
|
}
|
||
|
|
|
||
|
|
type Options struct {
|
||
|
|
Db *qx.Db
|
||
|
|
Location *time.Location
|
||
|
|
MinWorkers int
|
||
|
|
QueueSize int
|
||
|
|
}
|
||
|
|
|
||
|
|
func New(opt Options) *MeasureQueryEngine {
|
||
|
|
if opt.Db == nil {
|
||
|
|
panic("Db option is required")
|
||
|
|
}
|
||
|
|
|
||
|
|
if opt.Location == nil {
|
||
|
|
panic("Location option is required")
|
||
|
|
}
|
||
|
|
|
||
|
|
if opt.MinWorkers <= 0 {
|
||
|
|
panic("MinWorkers option is required")
|
||
|
|
}
|
||
|
|
|
||
|
|
if opt.QueueSize <= 0 {
|
||
|
|
panic("QueueSize option is required")
|
||
|
|
}
|
||
|
|
|
||
|
|
s := new(MeasureQueryEngine)
|
||
|
|
s.db = opt.Db
|
||
|
|
s.location = opt.Location
|
||
|
|
//
|
||
|
|
s.cumulativeCh = make(chan *CumulativeTask, opt.QueueSize)
|
||
|
|
s.instantCh = make(chan *InstantTask, opt.QueueSize)
|
||
|
|
s.aggregatedCumulativeCh = make(chan *AggregatedCumulativeTask, opt.QueueSize)
|
||
|
|
s.aggregatedInstantCh = make(chan *AggregatedInstantTask, opt.QueueSize)
|
||
|
|
s.cumulativeTotalCh = make(chan *CumulativeTotalTask, opt.QueueSize)
|
||
|
|
s.metricReadingsCh = make(chan *MetricReadingsTask, opt.QueueSize)
|
||
|
|
|
||
|
|
//
|
||
|
|
for i := 0; i < opt.MinWorkers; i++ {
|
||
|
|
go s.worker()
|
||
|
|
}
|
||
|
|
return s
|
||
|
|
}
|
||
|
|
|
||
|
|
func (s *MeasureQueryEngine) worker() {
|
||
|
|
for {
|
||
|
|
select {
|
||
|
|
case task := <-s.cumulativeCh:
|
||
|
|
task.Result, task.Err = s.listCumulativeMeasures(task.In)
|
||
|
|
task.WaitGroup.Done()
|
||
|
|
|
||
|
|
case task := <-s.instantCh:
|
||
|
|
task.Result, task.Err = s.listInstantMeasures(task.In)
|
||
|
|
task.WaitGroup.Done()
|
||
|
|
|
||
|
|
case task := <-s.aggregatedCumulativeCh:
|
||
|
|
task.Result, task.Err = s.listAggregatedCumulativeMeasures(task.In)
|
||
|
|
task.WaitGroup.Done()
|
||
|
|
|
||
|
|
case task := <-s.aggregatedInstantCh:
|
||
|
|
task.Result, task.Err = s.listAggregatedInstantMeasures(task.In)
|
||
|
|
task.WaitGroup.Done()
|
||
|
|
|
||
|
|
case task := <-s.cumulativeTotalCh:
|
||
|
|
task.Result, task.Err = s.getCumulativeTotal(task.In)
|
||
|
|
task.WaitGroup.Done()
|
||
|
|
|
||
|
|
case task := <-s.metricReadingsCh:
|
||
|
|
task.Result, task.Err = s.listMetricReadings(task.In)
|
||
|
|
task.WaitGroup.Done()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//
|
||
|
|
|
||
|
|
type CumulativeTask struct {
|
||
|
|
In MetricMeasuresFilter
|
||
|
|
WaitGroup *sync.WaitGroup
|
||
|
|
Result []Measure
|
||
|
|
Err error
|
||
|
|
}
|
||
|
|
|
||
|
|
type InstantTask struct {
|
||
|
|
In MetricMeasuresFilter
|
||
|
|
WaitGroup *sync.WaitGroup
|
||
|
|
Result []Measure
|
||
|
|
Err error
|
||
|
|
}
|
||
|
|
|
||
|
|
type AggregatedCumulativeTask struct {
|
||
|
|
In AggregatedMeasuresFilter
|
||
|
|
WaitGroup *sync.WaitGroup
|
||
|
|
Result []AggregatedMeasure
|
||
|
|
Err error
|
||
|
|
}
|
||
|
|
|
||
|
|
type AggregatedInstantTask struct {
|
||
|
|
In AggregatedInstantMeasuresIn
|
||
|
|
WaitGroup *sync.WaitGroup
|
||
|
|
Result []AggregatedMeasure
|
||
|
|
Err error
|
||
|
|
}
|
||
|
|
|
||
|
|
type MetricReadingsTask struct {
|
||
|
|
In MetricMeasuresFilter
|
||
|
|
WaitGroup *sync.WaitGroup
|
||
|
|
Result MetricReadings
|
||
|
|
Err error
|
||
|
|
}
|
||
|
|
|
||
|
|
type CumulativeTotalTask struct {
|
||
|
|
In getCumulativeTotalFilter
|
||
|
|
WaitGroup *sync.WaitGroup
|
||
|
|
Result *RangeTotal
|
||
|
|
Err error
|
||
|
|
}
|