1
0
mirror of https://github.com/Oxalide/vsphere-influxdb-go.git synced 2023-10-10 11:36:51 +00:00

add vendoring with go dep

This commit is contained in:
Adrian Todorov
2017-10-25 20:52:40 +00:00
parent 704f4d20d1
commit a59409f16b
1627 changed files with 489673 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
Shard Precreation
============
During normal operation when InfluxDB receives time-series data, it writes the data to files known as _shards_. Each shard only contains data for a specific range of time. Therefore, before data can be accepted by the system, the shards must exist and InfluxDB always checks that the required shards exist for every incoming data point. If the required shards do not exist, InfluxDB will create those shards. Because this requires a cluster to reach consensus, the process is not instantaneous and can temporarily impact write-throughput.
Since almost all time-series data is written sequentially in time, the system has an excellent idea of the timestamps of future data. Shard precreation takes advantage of this fact by creating required shards ahead of time, thereby ensuring the required shards exist by the time new time-series data actually arrives. Write-throughput is therefore not affected when data is first received for a range of time that would normally trigger shard creation.
Note that the shard-existence check must remain in place in the code, even with shard precreation. This is because while most data is written sequentially in time, this is not always the case. Data may be written with timestamps in the past, or farther in the future than shard precreation handles.
## Configuration
Shard precreation can be disabled if necessary, though this is not recommended. If it is disabled, then shards will be only be created when explicitly needed.
The interval between runs of the shard precreation service, as well as the time-in-advance the shards are created, are also configurable. The defaults should work for most deployments.

View File

@@ -0,0 +1,67 @@
package precreator
import (
"errors"
"time"
"github.com/influxdata/influxdb/monitor/diagnostics"
"github.com/influxdata/influxdb/toml"
)
const (
// DefaultCheckInterval is the shard precreation check time if none is specified.
DefaultCheckInterval = 10 * time.Minute
// DefaultAdvancePeriod is the default period ahead of the endtime of a shard group
// that its successor group is created.
DefaultAdvancePeriod = 30 * time.Minute
)
// Config represents the configuration for shard precreation.
type Config struct {
Enabled bool `toml:"enabled"`
CheckInterval toml.Duration `toml:"check-interval"`
AdvancePeriod toml.Duration `toml:"advance-period"`
}
// NewConfig returns a new Config with defaults.
func NewConfig() Config {
return Config{
Enabled: true,
CheckInterval: toml.Duration(DefaultCheckInterval),
AdvancePeriod: toml.Duration(DefaultAdvancePeriod),
}
}
// Validate returns an error if the Config is invalid.
func (c Config) Validate() error {
if !c.Enabled {
return nil
}
// TODO: Should we enforce a minimum interval?
// Polling every nanosecond, for instance, will greatly impact performance.
if c.CheckInterval <= 0 {
return errors.New("check-interval must be positive")
}
if c.AdvancePeriod <= 0 {
return errors.New("advance-period must be positive")
}
return nil
}
// Diagnostics returns a diagnostics representation of a subset of the Config.
func (c Config) Diagnostics() (*diagnostics.Diagnostics, error) {
if !c.Enabled {
return diagnostics.RowFromMap(map[string]interface{}{
"enabled": false,
}), nil
}
return diagnostics.RowFromMap(map[string]interface{}{
"enabled": true,
"check-interval": c.CheckInterval,
"advance-period": c.AdvancePeriod,
}), nil
}

View File

@@ -0,0 +1,62 @@
package precreator_test
import (
"testing"
"time"
"github.com/BurntSushi/toml"
"github.com/influxdata/influxdb/services/precreator"
)
func TestConfig_Parse(t *testing.T) {
// Parse configuration.
var c precreator.Config
if _, err := toml.Decode(`
enabled = true
check-interval = "2m"
advance-period = "10m"
`, &c); err != nil {
t.Fatal(err)
}
// Validate configuration.
if !c.Enabled {
t.Fatalf("unexpected enabled state: %v", c.Enabled)
} else if time.Duration(c.CheckInterval) != 2*time.Minute {
t.Fatalf("unexpected check interval: %s", c.CheckInterval)
} else if time.Duration(c.AdvancePeriod) != 10*time.Minute {
t.Fatalf("unexpected advance period: %s", c.AdvancePeriod)
}
}
func TestConfig_Validate(t *testing.T) {
c := precreator.NewConfig()
if err := c.Validate(); err != nil {
t.Fatalf("unexpected validation fail from NewConfig: %s", err)
}
c = precreator.NewConfig()
c.CheckInterval = 0
if err := c.Validate(); err == nil {
t.Fatal("expected error for check-interval = 0, got nil")
}
c = precreator.NewConfig()
c.CheckInterval *= -1
if err := c.Validate(); err == nil {
t.Fatal("expected error for negative check-interval, got nil")
}
c = precreator.NewConfig()
c.AdvancePeriod = 0
if err := c.Validate(); err == nil {
t.Fatal("expected error for advance-period = 0, got nil")
}
c = precreator.NewConfig()
c.AdvancePeriod *= -1
if err := c.Validate(); err == nil {
t.Fatal("expected error for negative advance-period, got nil")
}
}

View File

@@ -0,0 +1,96 @@
// Package precreator provides the shard precreation service.
package precreator // import "github.com/influxdata/influxdb/services/precreator"
import (
"fmt"
"sync"
"time"
"github.com/uber-go/zap"
)
// Service manages the shard precreation service.
type Service struct {
checkInterval time.Duration
advancePeriod time.Duration
Logger zap.Logger
done chan struct{}
wg sync.WaitGroup
MetaClient interface {
PrecreateShardGroups(now, cutoff time.Time) error
}
}
// NewService returns an instance of the precreation service.
func NewService(c Config) (*Service, error) {
s := Service{
checkInterval: time.Duration(c.CheckInterval),
advancePeriod: time.Duration(c.AdvancePeriod),
Logger: zap.New(zap.NullEncoder()),
}
return &s, nil
}
// WithLogger sets the logger for the service.
func (s *Service) WithLogger(log zap.Logger) {
s.Logger = log.With(zap.String("service", "shard-precreation"))
}
// Open starts the precreation service.
func (s *Service) Open() error {
if s.done != nil {
return nil
}
s.Logger.Info(fmt.Sprintf("Starting precreation service with check interval of %s, advance period of %s",
s.checkInterval, s.advancePeriod))
s.done = make(chan struct{})
s.wg.Add(1)
go s.runPrecreation()
return nil
}
// Close stops the precreation service.
func (s *Service) Close() error {
if s.done == nil {
return nil
}
close(s.done)
s.wg.Wait()
s.done = nil
return nil
}
// runPrecreation continually checks if resources need precreation.
func (s *Service) runPrecreation() {
defer s.wg.Done()
for {
select {
case <-time.After(s.checkInterval):
if err := s.precreate(time.Now().UTC()); err != nil {
s.Logger.Info(fmt.Sprintf("failed to precreate shards: %s", err.Error()))
}
case <-s.done:
s.Logger.Info("Precreation service terminating")
return
}
}
}
// precreate performs actual resource precreation.
func (s *Service) precreate(now time.Time) error {
cutoff := now.Add(s.advancePeriod).UTC()
if err := s.MetaClient.PrecreateShardGroups(now, cutoff); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,55 @@
package precreator
import (
"sync"
"testing"
"time"
"github.com/influxdata/influxdb/toml"
)
func Test_ShardPrecreation(t *testing.T) {
t.Parallel()
now := time.Now().UTC()
advancePeriod := 5 * time.Minute
// A test metastaore which returns 2 shard groups, only 1 of which requires a successor.
var wg sync.WaitGroup
wg.Add(1)
ms := metaClient{
PrecreateShardGroupsFn: func(v, u time.Time) error {
wg.Done()
if u != now.Add(advancePeriod) {
t.Fatalf("precreation called with wrong time, got %s, exp %s", u, now)
}
return nil
},
}
srv, err := NewService(Config{
CheckInterval: toml.Duration(time.Minute),
AdvancePeriod: toml.Duration(advancePeriod),
})
if err != nil {
t.Fatalf("failed to create shard precreation service: %s", err.Error())
}
srv.MetaClient = ms
err = srv.precreate(now)
if err != nil {
t.Fatalf("failed to precreate shards: %s", err.Error())
}
wg.Wait() // Ensure metaClient test function is called.
return
}
// PointsWriter represents a mock impl of PointsWriter.
type metaClient struct {
PrecreateShardGroupsFn func(now, cutoff time.Time) error
}
func (m metaClient) PrecreateShardGroups(now, cutoff time.Time) error {
return m.PrecreateShardGroupsFn(now, cutoff)
}