Browse Source

metric: update date_counter

fatedier 8 years ago
parent
commit
6a95a63fd4
1 changed files with 29 additions and 49 deletions
  1. 29 49
      utils/metric/date_counter.go

+ 29 - 49
utils/metric/date_counter.go

@@ -26,7 +26,6 @@ type DateCounter interface {
 	Dec(int64)
 	Snapshot() DateCounter
 	Clear()
-	Close()
 }
 
 func NewDateCounter(reserveDays int64) DateCounter {
@@ -40,24 +39,26 @@ type StandardDateCounter struct {
 	reserveDays int64
 	counts      []int64
 
-	closeCh chan struct{}
-	closed  bool
-	mu      sync.Mutex
+	lastUpdateDate time.Time
+	mu             sync.Mutex
 }
 
 func newStandardDateCounter(reserveDays int64) *StandardDateCounter {
+	now := time.Now()
+	now = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
 	s := &StandardDateCounter{
-		reserveDays: reserveDays,
-		counts:      make([]int64, reserveDays),
-		closeCh:     make(chan struct{}),
+		reserveDays:    reserveDays,
+		counts:         make([]int64, reserveDays),
+		lastUpdateDate: now,
 	}
-	s.startRotateWorker()
 	return s
 }
 
 func (c *StandardDateCounter) TodayCount() int64 {
 	c.mu.Lock()
 	defer c.mu.Unlock()
+
+	c.rotate(time.Now())
 	return c.counts[0]
 }
 
@@ -69,6 +70,7 @@ func (c *StandardDateCounter) GetLastDaysCount(lastdays int64) []int64 {
 
 	c.mu.Lock()
 	defer c.mu.Unlock()
+	c.rotate(time.Now())
 	for i := 0; i < int(lastdays); i++ {
 		counts[i] = c.counts[i]
 	}
@@ -78,12 +80,14 @@ func (c *StandardDateCounter) GetLastDaysCount(lastdays int64) []int64 {
 func (c *StandardDateCounter) Inc(count int64) {
 	c.mu.Lock()
 	defer c.mu.Unlock()
+	c.rotate(time.Now())
 	c.counts[0] += count
 }
 
 func (c *StandardDateCounter) Dec(count int64) {
 	c.mu.Lock()
 	defer c.mu.Unlock()
+	c.rotate(time.Now())
 	c.counts[0] -= count
 }
 
@@ -108,50 +112,26 @@ func (c *StandardDateCounter) Clear() {
 	}
 }
 
-func (c *StandardDateCounter) Close() {
-	c.mu.Lock()
-	defer c.mu.Unlock()
-	if !c.closed {
-		close(c.closeCh)
-		c.closed = true
-	}
-}
+// rotate
+// Must hold the lock before calling this function.
+func (c *StandardDateCounter) rotate(now time.Time) {
+	now = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
+	days := int(now.Sub(c.lastUpdateDate).Hours() / 24)
 
-func (c *StandardDateCounter) rotate() {
-	c.mu.Lock()
-	defer c.mu.Unlock()
+	defer func() {
+		c.lastUpdateDate = now
+	}()
+
+	if days <= 0 {
+		return
+	} else if days >= 7 {
+		c.counts = make([]int64, c.reserveDays)
+		return
+	}
 	newCounts := make([]int64, c.reserveDays)
 
-	for i := 1; i < int(c.reserveDays-1); i++ {
-		newCounts[i] = c.counts[i+1]
+	for i := days; i < int(c.reserveDays); i++ {
+		newCounts[i] = c.counts[i-days]
 	}
 	c.counts = newCounts
 }
-
-func (c *StandardDateCounter) startRotateWorker() {
-	now := time.Now()
-	nextDayTimeStr := now.Add(24 * time.Hour).Format("20060102")
-	nextDay, _ := time.Parse("20060102", nextDayTimeStr)
-	d := nextDay.Sub(now)
-
-	firstTimer := time.NewTimer(d)
-	rotateTicker := time.NewTicker(24 * time.Hour)
-
-	go func() {
-		for {
-			select {
-			case <-firstTimer.C:
-				firstTimer.Stop()
-				rotateTicker.Stop()
-				rotateTicker = time.NewTicker(24 * time.Hour)
-				c.rotate()
-			case <-rotateTicker.C:
-				c.rotate()
-			case <-c.closeCh:
-				break
-			}
-		}
-		firstTimer.Stop()
-		rotateTicker.Stop()
-	}()
-}