Created
August 2, 2016 22:21
-
-
Save gallir/5231bd5e836883625fb7245853b3f3fc to your computer and use it in GitHub Desktop.
A time serie cache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"sync" | |
"time" | |
) | |
type SerieElement struct { | |
ts time.Time | |
data *BookingData | |
} | |
type Serie struct { | |
sync.RWMutex | |
ids map[string]bool | |
elements []*SerieElement | |
maxCache time.Duration | |
lastTs time.Time | |
removeCh chan bool | |
} | |
func NewSerie(maxCache time.Duration) (s *Serie) { | |
s = &Serie{ | |
elements: make([]*SerieElement, 0), | |
maxCache: maxCache, | |
ids: make(map[string]bool), | |
removeCh: make(chan bool), | |
} | |
go s.removeOldActor() | |
return | |
} | |
func (s *Serie) Append(b *BookingData, ts time.Time) { | |
s.Lock() | |
defer s.Unlock() | |
defer s.removeOld() | |
_, ok := s.ids[b.id] | |
if ok { | |
// Element already inserted | |
return | |
} | |
e := &SerieElement{ | |
ts: ts, | |
data: b, | |
} | |
s.ids[e.data.id] = true | |
s.elements = append(s.elements, e) | |
if ts.After(s.lastTs) { | |
s.lastTs = ts | |
} | |
} | |
func (s *Serie) Get(fromTime time.Time) (elements []*SerieElement) { | |
s.RLock() | |
defer s.RUnlock() | |
defer s.removeOld() | |
first := len(s.elements) | |
for i := first - 1; i >= 0; i-- { | |
if s.elements[i].ts.After(fromTime) { | |
first = i | |
} else { | |
break | |
} | |
} | |
if first < len(s.elements) { | |
elements = s.elements[first:] | |
} | |
return | |
} | |
func (s *Serie) removeOld() { | |
// Asynchronous, the Actor will ignore if there are frequent calls | |
select { | |
case s.removeCh <- true: | |
default: | |
} | |
} | |
func (s *Serie) removeOldActor() { | |
for { | |
<-s.removeCh | |
s.Lock() | |
now := time.Now() | |
olds := 0 | |
for _, e := range s.elements { | |
if e.ts.Before(now.Add(-s.maxCache)) { | |
delete(s.ids, e.data.id) | |
olds++ | |
} else { | |
break | |
} | |
} | |
if olds > 0 { | |
s.elements = s.elements[olds:] | |
} | |
s.Unlock() | |
time.Sleep(5 * time.Second) // To ignore frequent and innecesary calls | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment