// NewServer returns a new instance of Server built from a config. func NewServer(c *Config, version string) (*Server, error) { s := &Server{ version: version, err: make(chan error), closing: make(chan struct{}), Hostname: c.Meta.Hostname, BindAddress: c.Meta.BindAddress, MetaStore: meta.NewStore(c.Meta), DataStore: db.NewStore(c.Data.Dir), reportingDisabled: c.ReportingDisabled, } // Copy TSDB configuration. s.DataStore.MaxWALSize = c.Data.MaxWALSize s.DataStore.WALFlushInterval = time.Duration(c.Data.WALFlushInterval) s.DataStore.WALPartitionFlushDelay = time.Duration(c.Data.WALPartitionFlushDelay) // Set the shard mapper s.ShardMapper = cluster.NewShardMapper(time.Duration(c.Cluster.ShardMapperTimeout)) s.ShardMapper.ForceRemoteMapping = c.Cluster.ForceRemoteShardMapping s.ShardMapper.MetaStore = s.MetaStore s.ShardMapper.DataStore = s.DataStore // Initialize query executor. s.QueryExecutor = db.NewQueryExecutor(s.DataStore) s.QueryExecutor.MetaStore = s.MetaStore s.QueryExecutor.MetaStatementExecutor = &meta.StatementExecutor{Store: s.MetaStore} // Set the shard writer s.ShardWriter = cluster.NewShardWriter(time.Duration(c.Cluster.ShardWriterTimeout)) s.ShardWriter.MetaStore = s.MetaStore // Create the hinted handoff service s.HintedHandoff = hh.NewService(c.HintedHandoff, s.ShardWriter) // Initialize points writer. s.MessagesWriter = cluster.NewMessagesWriter() s.MessagesWriter.WriteTimeout = time.Duration(c.Cluster.WriteTimeout) s.MessagesWriter.MetaStore = s.MetaStore s.MessagesWriter.DataStore = s.DataStore s.MessagesWriter.ShardWriter = s.ShardWriter s.MessagesWriter.HintedHandoff = s.HintedHandoff // Append services. s.appendClusterService(c.Cluster) s.appendSnapshotterService() s.appendAdminService(c.Admin) s.appendHTTPDService(c.HTTPD) s.appendRetentionPolicyService(c.Retention) return s, nil }
// Ensure the shard writer returns an error when reading times out. func TestShardWriter_Write_ErrReadTimeout(t *testing.T) { ln, err := net.Listen("tcp", "127.0.0.1:0") if err != nil { t.Fatal(err) } w := cluster.NewShardWriter(time.Millisecond) w.MetaStore = &metaStore{host: ln.Addr().String()} now := time.Now() shardID := uint64(1) ownerID := uint64(2) var messages []db.Message messages = append(messages, db.NewMessage(now)) if err := w.WriteShard(shardID, ownerID, messages); err == nil || !strings.Contains(err.Error(), "i/o timeout") { t.Fatalf("unexpected error: %s", err) } }
// Ensure the shard writer can successful write a multiple requests. func TestShardWriter_WriteShard_Multiple(t *testing.T) { ts := newTestWriteService(writeShardSuccess) s := cluster.NewService(cluster.Config{}) s.Listener = ts.muxln s.DataStore = ts if err := s.Open(); err != nil { t.Fatal(err) } defer s.Close() defer ts.Close() w := cluster.NewShardWriter(time.Minute) w.MetaStore = &metaStore{host: ts.ln.Addr().String()} // Build a single point. now := time.Now() var messages []db.Message messages = append(messages, db.NewMessage(now)) // Write to shard twice and close. if err := w.WriteShard(1, 2, messages); err != nil { t.Fatal(err) } else if err := w.WriteShard(1, 2, messages); err != nil { t.Fatal(err) } else if err := w.Close(); err != nil { t.Fatal(err) } // Validate response. responses, err := ts.ResponseN(1) if err != nil { t.Fatal(err) } else if responses[0].shardID != 1 { t.Fatalf("unexpected shard id: %d", responses[0].shardID) } // Validate message. m := responses[0].messages[0] if m.Time().UnixNano() != now.UnixNano() { t.Fatalf("unexpected time: %s", m.Time()) } }
// Ensure the shard writer returns an error when the server fails to accept the write. func TestShardWriter_WriteShard_Error(t *testing.T) { ts := newTestWriteService(writeShardFail) s := cluster.NewService(cluster.Config{}) s.Listener = ts.muxln s.DataStore = ts if err := s.Open(); err != nil { t.Fatal(err) } defer s.Close() defer ts.Close() w := cluster.NewShardWriter(time.Minute) w.MetaStore = &metaStore{host: ts.ln.Addr().String()} now := time.Now() shardID := uint64(1) ownerID := uint64(2) var messages []db.Message messages = append(messages, db.NewMessage(now)) if err := w.WriteShard(shardID, ownerID, messages); err == nil || err.Error() != "error code 1: write shard 1: failed to write" { t.Fatalf("unexpected error: %v", err) } }
// Ensure the shard writer returns an error when dialing times out. func TestShardWriter_Write_ErrDialTimeout(t *testing.T) { ts := newTestWriteService(writeShardSuccess) s := cluster.NewService(cluster.Config{}) s.Listener = ts.muxln s.DataStore = ts if err := s.Open(); err != nil { t.Fatal(err) } defer s.Close() defer ts.Close() w := cluster.NewShardWriter(time.Nanosecond) w.MetaStore = &metaStore{host: ts.ln.Addr().String()} now := time.Now() shardID := uint64(1) ownerID := uint64(2) var messages []db.Message messages = append(messages, db.NewMessage(now)) if err, exp := w.WriteShard(shardID, ownerID, messages), "i/o timeout"; err == nil || !strings.Contains(err.Error(), exp) { t.Fatalf("expected error %v, to contain %s", err, exp) } }