package cardflow import ( "math" "time" ) // 队列写入判断结果,与采集记录的写入判断取值一致。 const ( QueueWrite = "written" QueueNotFull = "queue_not_full" QueueSlopeNegative = "slope_negative" QueueOutOfOrder = "out_of_order" ) // QueuePoint 是采集队列中的一个点:采集时间与运营商原始读数。 type QueuePoint struct { ObservedAt time.Time `json:"observed_at"` ReadingMB float64 `json:"reading_mb"` } // JudgeQueue 判断本次新点能否写入:新点在队尾、队列满 size 个点、相邻两点后一个 ≥ 前一个 − 回退容差。 // 不满足时返回不写原因;满足时写入的是队列最后一个点(即本次新点)。 func JudgeQueue(points []QueuePoint, newPointIsTail bool, size int, dropToleranceMB float64) string { if !newPointIsTail { return QueueOutOfOrder } if len(points) < size { return QueueNotFull } for i := 1; i < len(points); i++ { if points[i].ReadingMB < points[i-1].ReadingMB-dropToleranceMB { return QueueSlopeNegative } } return QueueWrite } // MaxCollectionInterval 返回启用中轮询配置流量采集间隔的上限:留 2 次冗余, // 跨天清空开启时为 24 小时 ÷ (N+2),关闭时为最长点龄 ÷ (N+2);最长点龄为 0(不限)时不设上限,返回 0。 func MaxCollectionInterval(size int, clearOnNewDay bool, maxPointAgeHours int, spare int) time.Duration { window := 24 * time.Hour if !clearOnNewDay { if maxPointAgeHours <= 0 { return 0 } window = time.Duration(maxPointAgeHours) * time.Hour } return time.Duration(math.Floor(float64(window) / float64(size+spare))) }