<commit_before>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package instancepoller

import (
	"time"

	"github.com/juju/ratelimit"
	"launchpad.net/tomb"

	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/errors"
	"launchpad.net/juju-core/instance"
)

type instanceGetter interface {
	Instances(ids []instance.Id) ([]instance.Instance, error)
}

type aggregator struct {
	environ instanceGetter
	reqc    chan instanceInfoReq
	tomb    tomb.Tomb
}

func newAggregator(env instanceGetter) *aggregator {
	a := &aggregator{
		environ: env,
		reqc:    make(chan instanceInfoReq),
	}
	go func() {
		defer a.tomb.Done()
		a.tomb.Kill(a.loop())
	}()
	return a
}

type instanceInfoReq struct {
	instId instance.Id
	reply  chan<- instanceInfoReply
}

type instanceInfoReply struct {
	info instanceInfo
	err  error
}

func (a *aggregator) instanceInfo(id instance.Id) (instanceInfo, error) {
	reply := make(chan instanceInfoReply)
	a.reqc <- instanceInfoReq{
		instId: id,
		reply:  reply,
	}
	r := <-reply
	return r.info, r.err
}

var gatherTime = 3 * time.Second
var capacity int64 = 1

func (a *aggregator) loop() error {
	timer := time.NewTimer(0)
	timer.Stop()
	var reqs []instanceInfoReq
	bucket := ratelimit.New(gatherTime, capacity)
	for {
		select {
		case <-a.tomb.Dying():
			return tomb.ErrDying
		case req := <-a.reqc:
			if len(reqs) == 0 {
				waitTime := bucket.Take(1)
				timer.Reset(waitTime)
			}
			reqs = append(reqs, req)
		case <-timer.C:
			ids := make([]instance.Id, len(reqs))
			for i, req := range reqs {
				ids[i] = req.instId
			}
			insts, err := a.environ.Instances(ids)
			for i, req := range reqs {
				var reply instanceInfoReply
				if err != nil && err != environs.ErrPartialInstances {
					reply.err = err
				} else {<commit_msg>Remove capacity variable and hardcode with comment<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package instancepoller

import (
	"time"

	"github.com/juju/ratelimit"
	"launchpad.net/tomb"

	"launchpad.net/juju-core/environs"
	"launchpad.net/juju-core/errors"
	"launchpad.net/juju-core/instance"
)

type instanceGetter interface {
	Instances(ids []instance.Id) ([]instance.Instance, error)
}

type aggregator struct {
	environ instanceGetter
	reqc    chan instanceInfoReq
	tomb    tomb.Tomb
}

func newAggregator(env instanceGetter) *aggregator {
	a := &aggregator{
		environ: env,
		reqc:    make(chan instanceInfoReq),
	}
	go func() {
		defer a.tomb.Done()
		a.tomb.Kill(a.loop())
	}()
	return a
}

type instanceInfoReq struct {
	instId instance.Id
	reply  chan<- instanceInfoReply
}

type instanceInfoReply struct {
	info instanceInfo
	err  error
}

func (a *aggregator) instanceInfo(id instance.Id) (instanceInfo, error) {
	reply := make(chan instanceInfoReply)
	a.reqc <- instanceInfoReq{
		instId: id,
		reply:  reply,
	}
	r := <-reply
	return r.info, r.err
}

var gatherTime = 3 * time.Second

func (a *aggregator) loop() error {
	timer := time.NewTimer(0)
	timer.Stop()
	var reqs []instanceInfoReq
        // We use a capacity of 1 so that sporadic requests will
        // be serviced immediately without having to wait.
	bucket := ratelimit.New(gatherTime, 1)
	for {
		select {
		case <-a.tomb.Dying():
			return tomb.ErrDying
		case req := <-a.reqc:
			if len(reqs) == 0 {
				waitTime := bucket.Take(1)
				timer.Reset(waitTime)
			}
			reqs = append(reqs, req)
		case <-timer.C:
			ids := make([]instance.Id, len(reqs))
			for i, req := range reqs {
				ids[i] = req.instId
			}
			insts, err := a.environ.Instances(ids)
			for i, req := range reqs {
				var reply instanceInfoReply
				if err != nil && err != environs.ErrPartialInstances {
					reply.err = err
				} else {
{'fraction_non_alphanumeric': 0.12523215707084107, 'fraction_numerical': 0.006102414433536747, 'mean_word_length': 3.4300822561692126, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5506777', 'n_tokens_mistral': 1516, 'n_tokens_neox': 1360, 'n_words': 350}