Chromium Code Reviews| Index: logdog/server/service/config/poller.go |
| diff --git a/logdog/server/service/config/poller.go b/logdog/server/service/config/poller.go |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..a24ed961b0e90967d0a5e97e6cf796314abf95d8 |
| --- /dev/null |
| +++ b/logdog/server/service/config/poller.go |
| @@ -0,0 +1,91 @@ |
| +// Copyright 2016 The LUCI Authors. All rights reserved. |
| +// Use of this source code is governed under the Apache License, Version 2.0 |
| +// that can be found in the LICENSE file. |
| + |
| +package config |
| + |
| +import ( |
| + "time" |
| + |
| + "github.com/luci/luci-go/common/clock" |
| + "github.com/luci/luci-go/common/errors" |
| + log "github.com/luci/luci-go/common/logging" |
| + "github.com/luci/luci-go/luci_config/common/cfgtypes" |
| + "github.com/luci/luci-go/luci_config/server/cfgclient" |
| + |
| + "golang.org/x/net/context" |
| +) |
| + |
| +// ChangePoller polls a configuration files for changes. If it changes, |
| +// the OnChange function will be called and the polling will stop. |
|
iannucci
2017/01/21 00:09:12
what's the reason for having the loop stop on the
dnj
2017/01/21 01:17:54
The application will quit after this, so there's n
|
| +type ChangePoller struct { |
| + // ConfigSet is the slice of config paths to watch. |
| + ConfigSet cfgtypes.ConfigSet |
| + // Path is the path of the config to watch. |
| + Path string |
| + |
| + // if the configuration has changed. If it has, KillFunc will be invoked. |
|
iannucci
2017/01/21 00:09:12
something went wrong with this comment I think. Al
dnj
2017/01/21 01:17:54
Fixed.
|
| + CheckInterval time.Duration |
| + // OnChange is the function that will be called if a configuration hash change |
| + // has been observed. |
| + OnChange func() |
| + |
| + // ContentHash is the config's hash. If empty, it will be populated when first |
| + // polled. |
| + ContentHash string |
| +} |
| + |
| +// Run starts polling for changes. It will stop when the Context is cancelled. |
| +func (p *ChangePoller) Run(c context.Context) { |
| + if p.CheckInterval <= 0 { |
| + return |
| + } |
| + |
| + for { |
| + if err := c.Err(); err != nil { |
|
iannucci
2017/01/21 00:09:12
so remember that thing we talked about last febura
dnj
2017/01/21 01:17:54
Done.
|
| + log.WithError(err).Warningf(c, "Terminating poll loop: context has been cancelled.") |
| + return |
| + } |
| + |
| + log.Fields{ |
| + "timeout": p.CheckInterval, |
| + }.Debugf(c, "Entering change check poll loop...") |
| + if tr := clock.Sleep(c, p.CheckInterval); tr.Incomplete() { |
| + log.WithError(tr.Err).Debugf(c, "Context cancelled, shutting down change poller.") |
| + return |
| + } |
| + |
| + log.Infof(c, "Change check timeout triggered, checking configuration...") |
| + lastHash := p.ContentHash |
| + switch err := p.refresh(c); { |
| + case err != nil: |
| + log.WithError(err).Errorf(c, "Failed to refresh config.") |
| + |
| + case lastHash != p.ContentHash: |
| + log.Fields{ |
| + "originalHash": lastHash, |
| + "newHash": p.ContentHash, |
| + }.Warningf(c, "Configuration content hash has changed.") |
| + if p.OnChange != nil { |
| + p.OnChange() |
| + } |
| + return |
| + |
| + default: |
| + log.Fields{ |
| + "currentHash": lastHash, |
| + }.Debugf(c, "Content hash matches.") |
| + } |
| + } |
| +} |
| + |
| +func (p *ChangePoller) refresh(c context.Context) error { |
| + var meta cfgclient.Meta |
| + if err := cfgclient.Get(c, cfgclient.AsService, p.ConfigSet, p.Path, nil, &meta); err != nil { |
| + return errors.Annotate(err).Reason("failed to reload config %(configSet)s :: %(path)s"). |
| + D("configSet", p.ConfigSet).D("path", p.Path).Err() |
|
iannucci
2017/01/21 00:09:12
how would
return errors.Annotate(err).
Reas
dnj
2017/01/21 01:17:54
Taller, but sure.
|
| + } |
| + |
| + p.ContentHash = meta.ContentHash |
| + return nil |
| +} |