func (a *Accumulator) Append(sample *model.Sample) error {
	a.m.Lock()
	defer a.m.Unlock()
	if sample.TimestampMS < a.chunks[0].End {
		return nil
	}
	chunks, err := a.chunks[0].Chunk.Add(pmodel.SamplePair{
		Timestamp: pmodel.Time(sample.TimestampMS),
		Value:     pmodel.SampleValue(sample.Value),
	})
	if err != nil {
		return err
	}
	switch len(chunks) {
	case 1:
		a.chunks[0].Chunk = chunks[0]
		a.chunks[0].End = sample.TimestampMS
	case 2:
		a.chunks[0].Chunk = chunks[0]
		next, err := chunk.NewForEncoding(chunk.Varbit)
		if err != nil {
			return err
		}
		iter := chunks[1].NewIterator()
		for iter.Scan() {
			chunks, err := next.Add(iter.Value())
			if err != nil {
				return err
			}
			if len(chunks) != 1 {
				panic("expected overflow samples to fit into new varbit chunk")
			}
			next = chunks[0]
		}
		a.chunks = append([]*chunkend{
			{
				Chunk: next,
				End:   sample.TimestampMS,
			},
		}, a.chunks...)
	default:
		panic("appending a sample to a chunk without error should always result in 1 or 2 elements in chunk slice")
	}
	cutoff := sample.TimestampMS - a.maxAge
	for len(a.chunks) > 0 {
		end := a.chunks[len(a.chunks)-1].End
		if end == 0 || end >= cutoff {
			break
		}
		a.chunks = a.chunks[:len(a.chunks)-1]
	}
	return nil
}
Append appends a sample to the accumulator.
package cacher
import (
	"sync"
	"time"
	"github.com/digitalocean/vulcan/model"
	pmodel "github.com/prometheus/common/model"
	"github.com/prometheus/prometheus/storage/local/chunk"
)
type AccumulatorConfig struct {
	MaxAge time.Duration
}
type chunkend struct {
	Chunk chunk.Chunk
	End   int64
}
type Accumulator struct {
	chunks []*chunkend
	m      sync.Mutex
	maxAge int64
}
func NewAccumulator(cfg *AccumulatorConfig) (*Accumulator, error) {
	c, err := chunk.NewForEncoding(chunk.Varbit)
	if err != nil {
		return nil, err
	}
	a := &Accumulator{
		chunks: []*chunkend{
			&chunkend{
				Chunk: c,
				End:   0,
			},
		},
		maxAge: cfg.MaxAge.Nanoseconds() / int64(time.Millisecond),
	}
	return a, nil
}