Files
qb/worker/worker.go

540 lines
12 KiB
Go
Raw Normal View History

2026-06-13 22:43:17 +00:00
package worker
2026-02-10 14:02:11 +00:00
import (
"fmt"
2026-06-13 19:53:27 +03:00
"sync"
2026-02-10 14:02:11 +00:00
2026-05-14 16:06:37 +03:00
qb "gordenko.dev/dima/qb"
2026-02-10 14:02:11 +00:00
"gordenko.dev/dima/qb/atree"
2026-06-09 08:16:16 +03:00
"gordenko.dev/dima/qb/enc"
2026-06-13 22:43:17 +00:00
"gordenko.dev/dima/qb/inbox"
2026-05-10 19:15:11 +00:00
"gordenko.dev/dima/qb/proto"
2026-06-10 06:18:45 +03:00
"gordenko.dev/dima/qb/storage"
2026-02-10 14:02:11 +00:00
"gordenko.dev/dima/qb/transform"
)
2026-05-31 20:01:28 +00:00
// AddMetric - create metric in map and set Xlock, rwad - append to queue
// DeleteMetric - set Xlock
// DeleteSince - xLock (тупо редкая операция)
// Якийсь прапор поставити для pendingDelete, щоб read операції вставали в чергу
2026-02-10 14:02:11 +00:00
const (
2026-06-14 23:12:03 +03:00
QueryDone = 1
UntilFound = 2
UntilNotFound = 3
RangeFound = 15
NoMeasures = 16
NoMetric = 4
MetricDuplicate = 5
Succeed = 6
ExpiredMeasure = 8
NonMonotonicValue = 9
WrongMetricType = 11
NoMeasuresToDelete = 12
//DeleteFromAtreeNotNeeded = 13
//DeleteFromAtreeRequired = 14
2026-02-10 14:02:11 +00:00
)
2026-06-13 19:53:27 +03:00
type Worker struct {
2026-06-13 22:43:17 +00:00
inbox *inbox.Inbox
storageInbox *inbox.Inbox
2026-06-13 19:53:27 +03:00
dir string
2026-06-14 23:12:03 +03:00
databaseName string
2026-06-13 19:53:27 +03:00
snapshotNumber int
tmp []byte
2026-06-13 22:43:17 +00:00
metrics map[uint32]*Metric
2026-06-13 19:53:27 +03:00
exitCh chan struct{}
waitGroup *sync.WaitGroup
}
2026-06-14 07:57:01 +03:00
type Options struct {
Inbox *inbox.Inbox
StorageInbox *inbox.Inbox
ReplayMetrics map[uint32]*storage.ReplayMetric
Dir string
2026-06-14 23:12:03 +03:00
DatabaseName string
2026-06-14 07:57:01 +03:00
ExitCh chan struct{}
WaitGroup *sync.WaitGroup
2026-06-13 19:53:27 +03:00
}
2026-06-14 07:57:01 +03:00
func New(opt Options) *Worker {
s := &Worker{
2026-06-13 22:43:17 +00:00
inbox: opt.Inbox,
storageInbox: opt.StorageInbox,
dir: opt.Dir,
2026-06-14 23:12:03 +03:00
databaseName: opt.DatabaseName,
2026-06-13 22:43:17 +00:00
tmp: make([]byte, 26),
2026-06-14 07:57:01 +03:00
metrics: make(map[uint32]*Metric),
2026-06-13 22:43:17 +00:00
exitCh: opt.ExitCh,
waitGroup: opt.WaitGroup,
2026-06-13 19:53:27 +03:00
}
2026-06-14 07:57:01 +03:00
for metricID, x := range opt.ReplayMetrics {
databuf := x.Buf[:storage.DataPagePayloadSize]
values := enc.NewValueDeltaCompressor(x.MetricType, x.FracDigits, databuf, x.ValuesSize)
s.metrics[metricID] = &Metric{
metricType: x.MetricType,
fracDigits: x.FracDigits,
lastPageNo: x.LastPageNo,
lastValue: values.LastValue(),
buffer: x.Buf,
timestamps: enc.NewTimeDeltaCompressor(databuf, x.TimestampsSize),
values: values,
indexLevelTails: x.IndexLevelTails,
}
}
return s
2026-06-13 19:53:27 +03:00
}
func (s *Worker) ReleaseRLock(metricID uint32) {
2026-06-13 22:43:17 +00:00
// s.mutex.Lock()
// //s.rLocksToRelease = append(s.rLocksToRelease, metricID)
// s.mutex.Unlock()
2026-06-13 19:53:27 +03:00
2026-06-13 22:43:17 +00:00
// select {
// case s.signalCh <- struct{}{}:
// default:
// }
2026-06-13 19:53:27 +03:00
}
func (s *Worker) Run() {
2026-02-10 14:02:11 +00:00
for {
select {
2026-06-13 22:43:17 +00:00
case <-s.inbox.Ready():
2026-06-13 19:53:27 +03:00
s.doWork()
case <-s.exitCh:
fmt.Println("worker done")
s.waitGroup.Done()
return
2026-02-10 14:02:11 +00:00
}
}
}
2026-06-13 19:53:27 +03:00
func (s *Worker) doWork() {
2026-06-13 22:43:17 +00:00
queue := s.inbox.Drain()
2026-06-13 19:53:27 +03:00
//rLocksToRelease := s.rLocksToRelease
//s.rLocksToRelease = nil
2026-02-10 14:02:11 +00:00
2026-06-13 19:53:27 +03:00
// for _, metricID := range rLocksToRelease {
// metric, ok := s.metrics[metricID]
// if !ok {
// qb.Abort(qb.NoMetricBug,
// fmt.Errorf("drainQueues: metric %d not found", metricID))
// }
2026-02-10 14:02:11 +00:00
2026-06-13 19:53:27 +03:00
// if metric.XLock {
// qb.Abort(qb.XLockBug,
// fmt.Errorf("drainQueues: xlock is set for the metric %d",
// metricID))
// }
2026-02-10 14:02:11 +00:00
2026-06-13 19:53:27 +03:00
// if metric.RLocks <= 0 {
// qb.Abort(qb.NoRLockBug,
// fmt.Errorf("drainQueues: rlock not set for the metric %d",
// metricID))
// }
2026-02-10 14:02:11 +00:00
2026-06-13 19:53:27 +03:00
// metric.RLocks--
2026-02-10 14:02:11 +00:00
2026-06-13 19:53:27 +03:00
// if len(metric.WaitQueue) > 0 {
// s.processMetricQueue(metricID, metric)
// }
// }
2026-02-10 14:02:11 +00:00
2026-06-13 19:53:27 +03:00
for _, untyped := range queue {
2026-02-10 14:02:11 +00:00
switch req := untyped.(type) {
2026-06-13 22:43:17 +00:00
case AppendMeasuresReq:
s.AppendMeasures(req)
2026-06-10 06:18:45 +03:00
case storage.Changes:
2026-06-13 07:13:03 +00:00
s.applyCommits(req) // all metrics only
2026-06-13 22:43:17 +00:00
case ListCurrentValuesReq:
2026-06-14 23:12:03 +03:00
s.ListCurrentValues(req) // all metrics only
2026-06-13 22:43:17 +00:00
case RangeScanReq:
s.RangeScan(req)
case FullScanReq:
2026-06-14 23:12:03 +03:00
s.FullScan(req)
2026-06-13 22:43:17 +00:00
case AddMetricReq:
s.AddMetric(req)
case DeleteMetricReq:
s.DeleteMetric(req)
case DeleteMeasuresReq:
s.DeleteMeasures(req)
case GetMetricReq:
s.GetMetric(req)
2026-02-10 14:02:11 +00:00
default:
2026-05-14 16:06:37 +03:00
qb.Abort(qb.UnknownWorkerQueueItemBug,
2026-02-10 14:02:11 +00:00
fmt.Errorf("bug: unknown worker queue item type %T", req))
}
}
}
2026-05-31 20:01:28 +00:00
// суть у тому що треба запускати запити, пока не зустріну XLock
2026-06-13 22:43:17 +00:00
func (s *Worker) processMetricQueue(metricID uint32, metric *Metric, tmp []byte) {
2026-06-15 05:32:15 +03:00
if len(metric.waitQueue) == 0 {
2026-02-10 14:02:11 +00:00
return
}
2026-06-15 05:32:15 +03:00
for _, untyped := range metric.waitQueue {
2026-02-10 14:02:11 +00:00
switch req := untyped.(type) {
2026-06-13 22:43:17 +00:00
case RangeScanReq:
2026-05-31 20:01:28 +00:00
metric.StartRangeScan(req)
2026-06-13 22:43:17 +00:00
case FullScanReq:
2026-05-31 20:01:28 +00:00
metric.StartFullScan(req)
2026-06-13 22:43:17 +00:00
case GetMetricReq:
s.GetMetric(req)
case AppendMeasuresReq:
2026-06-14 23:12:03 +03:00
metric.AppendMeasures(req, tmp, s.storageInbox)
2026-06-13 22:43:17 +00:00
case DeleteMetricReq:
2026-06-15 05:32:15 +03:00
s.DeleteMetric(req)
2026-06-13 22:43:17 +00:00
case DeleteMeasuresReq:
2026-06-15 05:32:15 +03:00
metric.DeleteMeasures(req)
2026-05-31 20:01:28 +00:00
default:
qb.Abort(qb.UnknownMetricWaitQueueItemBug,
fmt.Errorf("bug: unknown metric wait queue item type %T", req))
2026-02-10 14:02:11 +00:00
}
}
}
2026-06-13 22:43:17 +00:00
type AddMetricReq struct {
2026-06-14 23:12:03 +03:00
MetricID uint32
MetricType qb.MetricType
FracDigits byte
ResultCh chan byte
2026-02-10 14:02:11 +00:00
}
2026-06-13 22:43:17 +00:00
func (s *Worker) AddMetric(req AddMetricReq) {
2026-02-10 14:02:11 +00:00
_, ok := s.metrics[req.MetricID]
if ok {
req.ResultCh <- MetricDuplicate
return
}
2026-06-14 23:12:03 +03:00
var (
buf = make([]byte, storage.DataPageSize)
databuf = buf[:storage.DataPagePayloadSize]
)
s.metrics[req.MetricID] = &Metric{
metricType: req.MetricType,
fracDigits: req.FracDigits,
buffer: buf,
timestamps: enc.NewTimeDeltaCompressor(databuf, 0),
values: enc.NewValueDeltaCompressor(req.MetricType, req.FracDigits, databuf, 0),
xLock: true,
}
s.storageInbox.Push(storage.MetricAdd{
MetricID: req.MetricID,
MetricType: req.MetricType,
FracDigits: req.FracDigits,
ResultCh: req.ResultCh,
})
2026-02-10 14:02:11 +00:00
}
2026-06-13 22:43:17 +00:00
type GetMetricResult struct {
MetricType qb.MetricType
FracDigits byte
ResultCode byte
}
type GetMetricReq struct {
2026-02-10 14:02:11 +00:00
MetricID uint32
2026-06-13 22:43:17 +00:00
ResultCh chan GetMetricResult
2026-02-10 14:02:11 +00:00
}
2026-06-13 22:43:17 +00:00
func (s *Worker) GetMetric(req GetMetricReq) {
2026-02-10 14:02:11 +00:00
metric, ok := s.metrics[req.MetricID]
if ok {
2026-06-13 22:43:17 +00:00
req.ResultCh <- GetMetricResult{
2026-02-10 14:02:11 +00:00
ResultCode: Succeed,
2026-06-14 07:57:01 +03:00
MetricType: metric.MetricType(),
FracDigits: metric.FracDigits(),
2026-02-10 14:02:11 +00:00
}
} else {
2026-06-13 22:43:17 +00:00
req.ResultCh <- GetMetricResult{
2026-02-10 14:02:11 +00:00
ResultCode: NoMetric,
}
}
}
2026-06-13 22:43:17 +00:00
type DeleteMetricReq struct {
2026-02-10 14:02:11 +00:00
MetricID uint32
2026-06-15 05:32:15 +03:00
ResultCh chan byte
2026-02-10 14:02:11 +00:00
}
2026-06-13 22:43:17 +00:00
func (s *Worker) DeleteMetric(req DeleteMetricReq) {
2026-06-15 05:32:15 +03:00
metric, ok := s.metrics[req.MetricID]
if !ok {
req.ResultCh <- NoMetric
return
}
if metric.xLock {
metric.waitQueue = append(metric.waitQueue, req)
} else {
// collect all pages, than
s.storageInbox.Push(storage.MetricDelete{
MetricID: req.MetricID,
FreeIndexPages: nil,
FreeDataPages: nil,
ResultCh: req.ResultCh,
})
}
2026-06-13 22:43:17 +00:00
}
type DeleteMeasuresReq struct {
2026-02-10 14:02:11 +00:00
MetricID uint32
Since uint32
2026-06-15 05:32:15 +03:00
ResultCh chan byte
2026-02-10 14:02:11 +00:00
}
2026-06-13 22:43:17 +00:00
func (s *Worker) DeleteMeasures(req DeleteMeasuresReq) {
2026-06-15 05:32:15 +03:00
metric, ok := s.metrics[req.MetricID]
2026-06-13 07:13:03 +00:00
if !ok {
2026-06-15 05:32:15 +03:00
req.ResultCh <- NoMetric
return
2026-06-13 07:13:03 +00:00
}
2026-06-15 05:32:15 +03:00
metric.DeleteMeasures(req)
2026-02-10 14:02:11 +00:00
}
2026-06-13 22:43:17 +00:00
type AppendMeasuresReq struct {
2026-02-10 14:02:11 +00:00
MetricID uint32
2026-05-10 19:15:11 +00:00
Measures []proto.Measure
2026-06-14 23:12:03 +03:00
ResultCh chan storage.MeasuresAppendResult
2026-02-10 14:02:11 +00:00
}
2026-06-13 22:43:17 +00:00
func (s *Worker) AppendMeasures(req AppendMeasuresReq) {
2026-02-10 14:02:11 +00:00
metric, ok := s.metrics[req.MetricID]
if !ok {
2026-06-14 23:12:03 +03:00
req.ResultCh <- storage.MeasuresAppendResult{
2026-02-10 14:02:11 +00:00
ResultCode: NoMetric,
}
return
}
2026-06-14 23:12:03 +03:00
if metric.xLock {
2026-06-15 05:32:15 +03:00
metric.waitQueue = append(metric.waitQueue, req)
} else {
metric.AppendMeasures(req, s.tmp, s.storageInbox)
2026-02-10 14:02:11 +00:00
}
}
2026-06-13 22:43:17 +00:00
type RangeScanResult struct {
ResultCode byte
FracDigits byte
RootPageNo uint32
LastPageNo uint32
}
type RangeScanReq struct {
2026-02-10 14:02:11 +00:00
MetricID uint32
Since uint32
Until uint32
2026-05-14 16:06:37 +03:00
MetricType qb.MetricType
2026-02-10 14:02:11 +00:00
ResponseWriter atree.WorkerMeasureConsumer
2026-06-13 22:43:17 +00:00
ResultCh chan RangeScanResult
2026-02-10 14:02:11 +00:00
}
2026-06-13 22:43:17 +00:00
func (s *Worker) RangeScan(req RangeScanReq) {
2026-02-10 14:02:11 +00:00
metric, ok := s.metrics[req.MetricID]
if !ok {
2026-06-13 22:43:17 +00:00
req.ResultCh <- RangeScanResult{
2026-02-10 14:02:11 +00:00
ResultCode: NoMetric,
}
return
}
2026-06-14 07:57:01 +03:00
if metric.MetricType() != req.MetricType {
2026-06-13 22:43:17 +00:00
req.ResultCh <- RangeScanResult{
2026-02-10 14:02:11 +00:00
ResultCode: WrongMetricType,
}
return
}
2026-06-14 23:12:03 +03:00
if metric.xLock {
2026-06-15 05:32:15 +03:00
metric.waitQueue = append(metric.waitQueue, req)
} else {
metric.StartRangeScan(req)
2026-02-10 14:02:11 +00:00
}
}
2026-06-13 22:43:17 +00:00
type FullScanResult struct {
ResultCode byte
FracDigits byte
LastPageNo uint32
}
type FullScanReq struct {
2026-02-10 14:02:11 +00:00
MetricID uint32
2026-05-14 16:06:37 +03:00
MetricType qb.MetricType
2026-02-10 14:02:11 +00:00
ResponseWriter atree.WorkerMeasureConsumer
2026-06-13 22:43:17 +00:00
ResultCh chan FullScanResult
2026-02-10 14:02:11 +00:00
}
2026-06-14 23:12:03 +03:00
func (s *Worker) FullScan(req FullScanReq) {
2026-02-10 14:02:11 +00:00
metric, ok := s.metrics[req.MetricID]
if !ok {
2026-06-13 22:43:17 +00:00
req.ResultCh <- FullScanResult{
2026-02-10 14:02:11 +00:00
ResultCode: NoMetric,
}
return
}
2026-06-14 07:57:01 +03:00
if metric.MetricType() != req.MetricType {
2026-06-13 22:43:17 +00:00
req.ResultCh <- FullScanResult{
2026-02-10 14:02:11 +00:00
ResultCode: WrongMetricType,
}
return
}
2026-06-14 23:12:03 +03:00
if metric.xLock {
2026-06-15 05:32:15 +03:00
metric.waitQueue = append(metric.waitQueue, req)
} else {
metric.StartFullScan(req)
2026-02-10 14:02:11 +00:00
}
}
2026-06-13 22:43:17 +00:00
type ListCurrentValuesReq struct {
2026-02-10 14:02:11 +00:00
MetricIDs []uint32
ResponseWriter *transform.CurrentValueWriter
ResultCh chan struct{}
}
2026-06-14 23:12:03 +03:00
func (s *Worker) ListCurrentValues(req ListCurrentValuesReq) {
2026-02-10 14:02:11 +00:00
for _, metricID := range req.MetricIDs {
metric, ok := s.metrics[metricID]
if ok {
req.ResponseWriter.BufferValue(transform.CurrentValue{
MetricID: metricID,
2026-06-13 08:01:42 +03:00
Timestamp: metric.LastTimestamp(),
Value: metric.LastValue(),
2026-02-10 14:02:11 +00:00
})
}
}
req.ResultCh <- struct{}{}
}
///////////////////////////////////////////////////////
2026-06-13 19:53:27 +03:00
func (s *Worker) applyCommits(req storage.Changes) {
2026-06-13 07:13:03 +00:00
for _, untyped := range req.Commits {
2026-02-10 14:02:11 +00:00
switch rec := untyped.(type) {
2026-06-13 07:13:03 +00:00
case storage.MetricAddCommited:
s.onMetricAddCommited(rec)
2026-02-10 14:02:11 +00:00
2026-06-13 07:13:03 +00:00
case storage.MetricDeleteCommited:
s.onMetricDeleteCommited(rec)
2026-02-10 14:02:11 +00:00
2026-06-13 07:13:03 +00:00
case storage.MeasuresAppendCommited:
s.onMeasuresAppendCommited(rec)
2026-02-10 14:02:11 +00:00
2026-06-13 08:01:42 +03:00
case storage.MeasuresAppendWithGrowCommited:
2026-06-13 07:13:03 +00:00
s.onMeasuresAppendWithGrowCommited(rec)
2026-02-10 14:02:11 +00:00
2026-06-13 07:13:03 +00:00
case storage.MeasuresDeleteCommited:
s.onMeasuresDeleteCommited(rec)
2026-02-10 14:02:11 +00:00
}
}
2026-06-09 08:16:16 +03:00
if req.SnapshotNumberCh != nil {
s.snapshotNumber++
2026-06-14 23:12:03 +03:00
err := writeSnapshot(
qb.GetSnapshotFilePath(s.dir, s.databaseName, s.snapshotNumber),
WriteSnapshotIn{
SnapshotNumber: s.snapshotNumber,
WriteBufferSize: 4 * 1024 * 1024, // 4mb
Metrics: s.metrics,
FrozenIndexPagesCount: req.FrozenIndexPagesCount,
IndexPageNumbers: req.IndexPageNumbers,
FrozenDataPagesCount: req.FrozenDataPagesCount,
DataPageNumbers: req.DataPageNumbers,
})
2026-06-09 08:16:16 +03:00
if err != nil {
qb.Abort(qb.WriteSnapshotFailed, err)
2026-05-31 20:01:28 +00:00
}
2026-06-09 08:16:16 +03:00
req.SnapshotNumberCh <- s.snapshotNumber
2026-02-10 14:02:11 +00:00
}
}
2026-06-13 19:53:27 +03:00
func (s *Worker) onMetricAddCommited(rec storage.MetricAddCommited) {
2026-06-14 23:12:03 +03:00
metric, ok := s.metrics[rec.MetricID]
if !ok {
2026-05-14 16:06:37 +03:00
qb.Abort(qb.MetricAddedBug,
2026-06-15 05:32:15 +03:00
fmt.Errorf("onMetricAddCommited: metric %d not found", rec.MetricID))
2026-02-10 14:02:11 +00:00
}
2026-06-14 23:12:03 +03:00
metric.xLock = false
2026-06-15 05:32:15 +03:00
rec.ResultCh <- Succeed
2026-02-10 14:02:11 +00:00
}
2026-06-13 19:53:27 +03:00
func (s *Worker) onMetricDeleteCommited(rec storage.MetricDeleteCommited) {
2026-05-31 20:01:28 +00:00
metric, ok := s.metrics[rec.MetricID]
2026-02-10 14:02:11 +00:00
if !ok {
2026-05-14 16:06:37 +03:00
qb.Abort(qb.NoMetricBug,
2026-06-15 05:32:15 +03:00
fmt.Errorf("onMetricDeleteCommited: metric %d not found", rec.MetricID))
2026-02-10 14:02:11 +00:00
}
2026-06-15 05:32:15 +03:00
if len(metric.waitQueue) > 0 {
for _, untyped := range metric.waitQueue {
2026-02-10 14:02:11 +00:00
switch req := untyped.(type) {
2026-06-15 05:32:15 +03:00
case AppendMeasuresReq:
req.ResultCh <- storage.MeasuresAppendResult{
ResultCode: NoMetric,
WrittenCount: 0,
}
2026-06-13 22:43:17 +00:00
case RangeScanReq:
req.ResultCh <- RangeScanResult{
2026-02-10 14:02:11 +00:00
ResultCode: NoMetric,
}
2026-06-13 22:43:17 +00:00
case FullScanReq:
req.ResultCh <- FullScanResult{
2026-02-10 14:02:11 +00:00
ResultCode: NoMetric,
}
2026-06-13 22:43:17 +00:00
case DeleteMetricReq:
2026-06-15 05:32:15 +03:00
req.ResultCh <- NoMetric
2026-06-13 22:43:17 +00:00
case DeleteMeasuresReq:
2026-06-15 05:32:15 +03:00
req.ResultCh <- NoMetric
2026-06-13 22:43:17 +00:00
case GetMetricReq:
req.ResultCh <- GetMetricResult{
2026-02-10 14:02:11 +00:00
ResultCode: NoMetric,
}
default:
2026-05-14 16:06:37 +03:00
qb.Abort(qb.UnknownMetricWaitQueueItemBug,
2026-02-10 14:02:11 +00:00
fmt.Errorf("bug: unknown metric wait queue item type %T", req))
}
}
}
delete(s.metrics, rec.MetricID)
2026-06-15 05:32:15 +03:00
//
rec.ResultCh <- Succeed
}
2026-02-10 14:02:11 +00:00
2026-06-15 05:32:15 +03:00
func (s *Worker) onMeasuresAppendCommited(rec storage.MeasuresAppendCommited) {
metric, ok := s.metrics[rec.MetricID]
if !ok {
qb.Abort(qb.NoMetricBug,
fmt.Errorf("onMeasuresAppendCommited: metric %d not found",
rec.MetricID))
2026-02-10 14:02:11 +00:00
}
2026-06-15 05:32:15 +03:00
metric.OnMeasuresAppendCommited(rec)
2026-02-10 14:02:11 +00:00
}
2026-06-15 05:32:15 +03:00
func (s *Worker) onMeasuresAppendWithGrowCommited(rec storage.MeasuresAppendWithGrowCommited) {
2026-02-10 14:02:11 +00:00
metric, ok := s.metrics[rec.MetricID]
if !ok {
2026-05-14 16:06:37 +03:00
qb.Abort(qb.NoMetricBug,
2026-06-15 05:32:15 +03:00
fmt.Errorf("onMeasuresAppendWithGrowCommited: metric %d not found",
2026-02-10 14:02:11 +00:00
rec.MetricID))
}
2026-06-15 05:32:15 +03:00
metric.OnMeasuresAppendWithGrowCommited(rec)
}
2026-02-10 14:02:11 +00:00
2026-06-15 05:32:15 +03:00
func (s *Worker) onMeasuresDeleteCommited(rec storage.MeasuresDeleteCommited) {
metric, ok := s.metrics[rec.MetricID]
if !ok {
qb.Abort(qb.NoMetricBug,
fmt.Errorf("onMeasuresDeleteCommited: metric %d not found", rec.MetricID))
2026-02-10 14:02:11 +00:00
}
2026-06-13 07:13:03 +00:00
metric.OnMeasuresDeleteCommited(rec)
2026-06-14 23:12:03 +03:00
metric.xLock = false
2026-06-15 05:32:15 +03:00
2026-06-13 19:53:27 +03:00
//s.doAfterReleaseXLock(rec.MetricID, metric)
2026-02-10 14:02:11 +00:00
}
2026-06-13 19:53:27 +03:00
// func (s *Database) doAfterReleaseXLock(metricID uint32, metric *_metric) {
// if len(metric.WaitQueue) > 0 {
// s.processMetricQueue(metricID, metric)
// }
// }