Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(102)

Unified Diff: server/internal/logdog/config/config.go

Issue 1610993002: LogDog: Add collector service implementation. (Closed) Base URL: https://github.com/luci/luci-go@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: server/internal/logdog/config/config.go
diff --git a/server/internal/logdog/config/config.go b/server/internal/logdog/config/config.go
new file mode 100644
index 0000000000000000000000000000000000000000..190c83f15b8f154f37e0b6e016068dcf9c0f0ccf
--- /dev/null
+++ b/server/internal/logdog/config/config.go
@@ -0,0 +1,137 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
dnj (Google) 2016/01/21 04:36:25 Daemon configuration support. Basically owns a luc
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package config
+
+import (
+ "time"
+
+ "github.com/golang/protobuf/proto"
+ "github.com/luci/luci-go/common/clock"
+ "github.com/luci/luci-go/common/config"
+ log "github.com/luci/luci-go/common/logging"
+ "github.com/luci/luci-go/common/proto/logdog/services"
+ "golang.org/x/net/context"
+)
+
+// Options is the set of options used to set up a Manager.
+//
+// The configuration is loaded from a services.Config protobuf.
+type Options struct {
+ // Config is the configuration service to load from.
+ Config config.Interface
+
+ // ConfigSet is the name of the ConfigSet to load.
+ ConfigSet string
+ // ConfigPath is the name of the ConfigPath to load.
+ ConfigPath string
+
+ // KillFunc is called if a configuration change has been detected. If nil,
+ // it will call os.Exit with ConfigChangedReturnCode.
+ KillFunc func()
+
+ // KillCheckInterval, if >0, starts a goroutine that polls every interval to
+ // see if the configuration has changed. If it has, KillFunc will be invoked.
+ KillCheckInterval time.Duration
+}
+
+func (o *Options) startKillPoller(c context.Context, hash string) {
+ for {
+ log.Fields{
+ "timeout": o.KillCheckInterval,
+ }.Debugf(c, "Entering kill check poll loop...")
+
+ select {
+ case <-c.Done():
+ log.WithError(c.Err()).Debugf(c, "Context cancelled, shutting down kill poller.")
+ return
+
+ case <-clock.After(c, o.KillCheckInterval):
+ log.Infof(c, "Kill check timeout triggered, reloading configuration...")
+
+ cfg, err := o.getConfig(true)
+ if err != nil {
+ log.WithError(err).Warningf(c, "Failed to reload configuration.")
+ continue
+ }
+
+ if cfg.ContentHash != hash {
+ log.Fields{
+ "currentHash": hash,
+ "newHash": cfg.ContentHash,
+ }.Errorf(c, "Configuration content hash has changed.")
+ o.runKillFunc()
+ return
+ }
+
+ log.Fields{
+ "currentHash": hash,
+ }.Debugf(c, "Content hash matches.")
+ }
+ }
+}
+
+func (o *Options) runKillFunc() {
+ if o.KillFunc != nil {
+ o.KillFunc()
+ }
+}
+
+func (o *Options) getConfig(hashOnly bool) (*config.Config, error) {
+ return o.Config.GetConfig(o.ConfigSet, o.ConfigPath, hashOnly)
+}
+
+// Manager holds and exposes a service configuration.
+//
+// It can also periodically refresh that configuration and invoke a shutdown
+// function if its content changes.
+type Manager struct {
+ o *Options
+
+ cfg *services.Config
+ contentHash string
+}
+
+// NewManager generates a new Manager and loads the initial configuration.
+func NewManager(c context.Context, o Options) (*Manager, error) {
+ m := Manager{
+ o: &o,
+ }
+
+ // Load the initial configuration.
+ if err := m.reloadConfig(c); err != nil {
+ return nil, err
+ }
+
+ if o.KillCheckInterval > 0 {
+ go m.o.startKillPoller(c, m.contentHash)
+ }
+
+ return &m, nil
+}
+
+// Config returns the service configuration instance.
+func (m *Manager) Config() *services.Config {
+ return m.cfg
+}
+
+func (m *Manager) reloadConfig(c context.Context) error {
+ cfg, err := m.o.getConfig(false)
+ if err != nil {
+ return err
+ }
+
+ scfg := services.Config{}
+ if err := proto.UnmarshalText(cfg.Content, &scfg); err != nil {
+ log.Fields{
+ log.ErrorKey: err,
+ "hash": cfg.ContentHash,
+ }.Errorf(c, "Failed to unmarshal configuration.")
+ return err
+ }
+
+ m.cfg = &scfg
+ m.contentHash = cfg.ContentHash
+ return nil
+}

Powered by Google App Engine
This is Rietveld 408576698