func (f *CVLTokenContractFilterers) StartCVLTokenContractFilterers(client bind.ContractBackend,
	pastEvents []*model.Event, nonSubOnly bool) ([]*model.Event, error) {
	contract, err := contract.NewCVLTokenContract(f.contractAddress, client)
	if err != nil {
		log.Errorf("Error initializing StartCVLTokenContract: err: %v", err)
		return pastEvents, err
	}
	f.contract = contract
	workerMultiplier := 1
	numWorkers := runtime.NumCPU() * workerMultiplier
	pool := tunny.NewFunc(numWorkers, func(payload interface{}) interface{} {
		f := payload.(func())
		f()
		return nil
	})
	defer pool.Close()
	wg := sync.WaitGroup{}
	resultsChan := make(chan []*model.Event)
	done := make(chan struct{})
	filtsRun := 0
	if !specs.IsEventDisabled("CVLTokenContract", "Approval") && (!nonSubOnly || !specs.IsListenerEnabledForEvent("CVLTokenContract", "Approval")) {
		wg.Add(1)
		go func() {
			filterFunc := func() {
				startBlock := f.eventToStartBlock["Approval"]
				pevents, e := f.startFilterApproval(startBlock, []*model.Event{})
				if e != nil {
					log.Errorf("Error retrieving Approval: err: %v", e)
					return
				}
				if len(pevents) > 0 {
					f.lastEventsMutex.Lock()
					f.lastEvents = append(f.lastEvents, pevents[len(pevents)-1])
					f.lastEventsMutex.Unlock()
					resultsChan <- pevents
				}
			}
			pool.Process(filterFunc)
			wg.Done()
		}()
		filtsRun++
	}
	if !specs.IsEventDisabled("CVLTokenContract", "OwnershipRenounced") && (!nonSubOnly || !specs.IsListenerEnabledForEvent("CVLTokenContract", "OwnershipRenounced")) {
		wg.Add(1)
		go func() {
			filterFunc := func() {
				startBlock := f.eventToStartBlock["OwnershipRenounced"]
				pevents, e := f.startFilterOwnershipRenounced(startBlock, []*model.Event{})
				if e != nil {
					log.Errorf("Error retrieving OwnershipRenounced: err: %v", e)
					return
				}
				if len(pevents) > 0 {
					f.lastEventsMutex.Lock()
					f.lastEvents = append(f.lastEvents, pevents[len(pevents)-1])
					f.lastEventsMutex.Unlock()
					resultsChan <- pevents
				}
			}
			pool.Process(filterFunc)
			wg.Done()
		}()
		filtsRun++
	}
	if !specs.IsEventDisabled("CVLTokenContract", "OwnershipTransferred") && (!nonSubOnly || !specs.IsListenerEnabledForEvent("CVLTokenContract", "OwnershipTransferred")) {
		wg.Add(1)
		go func() {
			filterFunc := func() {
				startBlock := f.eventToStartBlock["OwnershipTransferred"]
				pevents, e := f.startFilterOwnershipTransferred(startBlock, []*model.Event{})
				if e != nil {
					log.Errorf("Error retrieving OwnershipTransferred: err: %v", e)
					return
				}
				if len(pevents) > 0 {
					f.lastEventsMutex.Lock()
					f.lastEvents = append(f.lastEvents, pevents[len(pevents)-1])
					f.lastEventsMutex.Unlock()
					resultsChan <- pevents
				}
			}
			pool.Process(filterFunc)
			wg.Done()
		}()
		filtsRun++
	}
	if !specs.IsEventDisabled("CVLTokenContract", "Transfer") && (!nonSubOnly || !specs.IsListenerEnabledForEvent("CVLTokenContract", "Transfer")) {
		wg.Add(1)
		go func() {
			filterFunc := func() {
				startBlock := f.eventToStartBlock["Transfer"]
				pevents, e := f.startFilterTransfer(startBlock, []*model.Event{})
				if e != nil {
					log.Errorf("Error retrieving Transfer: err: %v", e)
					return
				}
				if len(pevents) > 0 {
					f.lastEventsMutex.Lock()
					f.lastEvents = append(f.lastEvents, pevents[len(pevents)-1])
					f.lastEventsMutex.Unlock()
					resultsChan <- pevents
				}
			}
			pool.Process(filterFunc)
			wg.Done()
		}()
		filtsRun++
	}
	go func() {
		wg.Wait()
		close(done)
		log.Info("Filtering routines complete")
	}()
Loop:
	for {
		select {
		case <-done:
			break Loop
		case pevents := <-resultsChan:
			f.pastEventsMutex.Lock()
			pastEvents = append(pastEvents, pevents...)
			f.pastEventsMutex.Unlock()
		}
	}
	log.Infof("Total filterers run: %v, events found: %v", filtsRun, len(pastEvents))
	return pastEvents, nil
}
StartCVLTokenContractFilterers retrieves events for CVLTokenContract
package filterer
import (
	log "github.com/golang/glog"
	"runtime"
	"sync"
	"github.com/Jeffail/tunny"
	"github.com/ethereum/go-ethereum/accounts/abi/bind"
	"github.com/ethereum/go-ethereum/common"
	specs "github.com/joincivil/civil-events-crawler/pkg/contractspecs"
	commongen "github.com/joincivil/civil-events-crawler/pkg/generated/common"
	"github.com/joincivil/civil-events-crawler/pkg/model"
	"github.com/joincivil/go-common/pkg/generated/contract"
	ctime "github.com/joincivil/go-common/pkg/time"
)
func NewCVLTokenContractFilterers(contractAddress common.Address) *CVLTokenContractFilterers {
	contractFilterers := &CVLTokenContractFilterers{
		contractAddress:   contractAddress,
		eventTypes:        commongen.EventTypesCVLTokenContract(),
		eventToStartBlock: make(map[string]uint64),
		lastEvents:        make([]*model.Event, 0),
	}
	for _, eventType := range contractFilterers.eventTypes {
		contractFilterers.eventToStartBlock[eventType] = 0
	}
	return contractFilterers
}
type CVLTokenContractFilterers struct {
	contractAddress   common.Address
	contract          *contract.CVLTokenContract
	eventTypes        []string
	eventToStartBlock map[string]uint64
	lastEvents        []*model.Event
	lastEventsMutex   sync.Mutex
	pastEventsMutex   sync.Mutex
}
func (f *CVLTokenContractFilterers) ContractName() string {
	return "CVLTokenContract"
}
func (f *CVLTokenContractFilterers) ContractAddress() common.Address {
	return f.contractAddress
}
func (f *CVLTokenContractFilterers) StartFilterers(client bind.ContractBackend,
	pastEvents []*model.Event, nonSubOnly bool) ([]*model.Event, error) {
	return f.StartCVLTokenContractFilterers(client, pastEvents, nonSubOnly)
}
func (f *CVLTokenContractFilterers) EventTypes() []string {
	return f.eventTypes
}
func (f *CVLTokenContractFilterers) UpdateStartBlock(eventType string, startBlock uint64) {
	f.eventToStartBlock[eventType] = startBlock
}
func (f *CVLTokenContractFilterers) LastEvents() []*model.Event {
	return f.lastEvents
}