Skip to content

Instantly share code, notes, and snippets.

@yudai
Last active March 22, 2018 20:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yudai/da0cf189c8c445973615671b33765c7d to your computer and use it in GitHub Desktop.
Save yudai/da0cf189c8c445973615671b33765c7d to your computer and use it in GitHub Desktop.
func (t *Periodic) Run() {
t.ctx, t.cancel = context.WithCancel(context.Background())
interval := t.getInterval()
num := int(t.period / interval) // number of revs to keep for t.period
notify := make(chan struct{}) // interval is defined as "duration from the last successfull compaction"
// notify := make(chan struct{}, 1) // interval is defined as "duration from the last expexcted time of compaction nethersless its result"
retryInterval := interval / 10
// periodically updates t.revs and notify to the other goroutine
go func() {
for {
rev := t.rg.Rev()
t.mu.Lock()
t.revs = append(t.revs, rev)
if len(t.revs) > num {
t.revs = t.revs[1:] // t.revs[0] is always the rev at t.period ago
}
t.mu.Unlock()
select {
case notify <- struct{}{}:
default:
// compaction can take time more than interval
}
select {
case <-t.ctx.Done():
return
case <-t.clock.After(interval):
}
}
}()
// run compaction triggered by the other goroutine thorough the notify channel
// or internal periodic retry
go func() {
var lastCompactedRev int64
for {
select {
case <-t.ctx.Done():
return
case <-notify:
// from the other goroutine
case <-t.clock.After(retryInterval):
// for retry
// when t.rev is not updated, this event will be ignored later,
// so we don't need to think about race with <-notify.
}
t.mu.Lock()
p := t.paused
rev := t.revs[0]
t.mu.Unlock()
if p {
continue
}
// if t.revs is not updated, we can ignore the event.
// it's not the first time to try comapction in this interval.
if rev == lastCompactedRev {
continue
}
plog.Noticef("Starting auto-compaction at revision %d (retention: %v)", rev, t.period)
_, err := t.c.Compact(t.ctx, &pb.CompactionRequest{Revision: rev})
if err == nil || err == mvcc.ErrCompacted {
plog.Noticef("Finished auto-compaction at revision %d", rev)
lastCompactedRev = rev
} else {
plog.Noticef("Failed auto-compaction at revision %d (%v)", rev, err)
plog.Noticef("Retry after %s", retryInterval)
}
}
}()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment