Skip to content
Snippets Groups Projects
results.go 1.71 KiB
Newer Older
  • Learn to ignore specific revisions
  • ale's avatar
    ale committed
    package probes
    
    import (
    	"fmt"
    	"sync"
    	"time"
    )
    
    type Result struct {
    	ID       string
    	Spec     SpecCommon
    	Ok       bool
    	Start    time.Time
    	Duration time.Duration
    	Logs     string
    }
    
    // Nice displayable string.
    func (r *Result) String() string {
    	return fmt.Sprintf("%s(%s)", r.Spec.Name, r.ID)
    }
    
    type ResultStore interface {
    	Push(*Result)
    	DoOk(func(*Result))
    	DoErrs(func(*Result))
    	Find(string) *Result
    }
    
    
    // Very simple overwriting circular buffer of results.
    type resultBuffer struct {
    	buf      []*Result
    	sz, head int
    }
    
    func newResultBuffer(sz int) *resultBuffer {
    	return &resultBuffer{
    		buf: make([]*Result, sz),
    		sz:  sz,
    	}
    }
    
    func (b *resultBuffer) Push(result *Result) {
    	b.buf[b.head] = result
    	b.head++
    	if b.head >= b.sz {
    		b.head -= b.sz
    	}
    }
    
    func (b *resultBuffer) Each(f func(*Result)) {
    	for i := 0; i < b.sz; i++ {
    		pos := b.head + i
    		if pos >= b.sz {
    			pos -= b.sz
    		}
    		if b.buf[pos] != nil {
    			f(b.buf[pos])
    		}
    	}
    }
    
    // ResultStore that keeps recent results in memory.
    
    ale's avatar
    ale committed
    type memResultStore struct {
    	mx   sync.Mutex
    
    	last *resultBuffer
    	errs *resultBuffer
    
    ale's avatar
    ale committed
    }
    
    func NewResultStore(numOk, numErrs int) ResultStore {
    	return &memResultStore{
    
    		last: newResultBuffer(numOk),
    		errs: newResultBuffer(numErrs),
    
    ale's avatar
    ale committed
    	}
    }
    
    func (r *memResultStore) Push(result *Result) {
    	r.mx.Lock()
    
    	r.last.Push(result)
    
    ale's avatar
    ale committed
    	if !result.Ok {
    
    		r.errs.Push(result)
    
    ale's avatar
    ale committed
    	}
    	r.mx.Unlock()
    }
    
    func (r *memResultStore) DoOk(f func(*Result)) {
    	r.mx.Lock()
    
    	r.last.Each(f)
    
    ale's avatar
    ale committed
    	r.mx.Unlock()
    }
    
    func (r *memResultStore) DoErrs(f func(*Result)) {
    	r.mx.Lock()
    
    	r.errs.Each(f)
    
    ale's avatar
    ale committed
    	r.mx.Unlock()
    }
    
    func (r *memResultStore) Find(id string) (out *Result) {
    	r.mx.Lock()
    
    	r.last.Each(func(r *Result) {
    		if r.ID == id {
    			out = r
    
    ale's avatar
    ale committed
    		}
    	})
    	r.mx.Unlock()
    	return
    }