Skip to content

Commit

Permalink
Issue #213: Make sure we wait for configuration to be saved
Browse files Browse the repository at this point in the history
There might be a case where the program is terminated before
configuration is saved.

Also, avoid calling save() multiple times on shutdowns.

License: MIT
Signed-off-by: Hector Sanjuan <hector@protocol.ai>
  • Loading branch information
hsanjuan committed Oct 27, 2017
1 parent 8495816 commit 828236d
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 6 deletions.
1 change: 0 additions & 1 deletion cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,6 @@ func (c *Cluster) Shutdown() error {
time.Sleep(2 * time.Second)
}
c.config.Bootstrap = c.peerManager.peersAddrs()
c.config.NotifySave()
c.peerManager.resetPeers()
}

Expand Down
25 changes: 22 additions & 3 deletions config/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package config

import (
"context"
"encoding/json"
"errors"
"fmt"
Expand Down Expand Up @@ -67,6 +68,9 @@ type jsonSection map[string]*json.RawMessage
// central configuration file when doing LoadJSON(), and saved to it
// when doing SaveJSON().
type Manager struct {
ctx context.Context
cancel func()
wg sync.WaitGroup

// The Cluster configuration has a top-level
// special section.
Expand All @@ -87,17 +91,31 @@ type Manager struct {
// NewManager returns a correctly initialized Manager
// which is ready to accept component configurations.
func NewManager() *Manager {
ctx, cancel := context.WithCancel(context.Background())
return &Manager{
ctx: ctx,
cancel: cancel,
sections: make(map[SectionType]Section),
}

}

func (cfg *Manager) Shutdown() {
cfg.cancel()
cfg.wg.Wait()
}

func (cfg *Manager) watchSave(save <-chan struct{}) {
defer cfg.wg.Done()
for {
select {
case <-save:
cfg.SaveJSON("")
err := cfg.SaveJSON("")
if err != nil {
logger.Error(err)
}
case <-cfg.ctx.Done():
return
}
}
}
Expand Down Expand Up @@ -141,6 +159,7 @@ func (cfg *Manager) Default() error {

// RegisterComponent lets the Manager load and save component configurations
func (cfg *Manager) RegisterComponent(t SectionType, ccfg ComponentConfig) {
cfg.wg.Add(1)
go cfg.watchSave(ccfg.SaveCh())

if t == Cluster {
Expand Down Expand Up @@ -278,8 +297,7 @@ func (cfg *Manager) SaveJSON(path string) error {
return err
}

err = ioutil.WriteFile(path, bs, 0600)
return err
return ioutil.WriteFile(path, bs, 0600)
}

// ToJSON provides a JSON representation of the configuration by
Expand All @@ -297,6 +315,7 @@ func (cfg *Manager) ToJSON() ([]byte, error) {

if cfg.clusterConfig != nil {
raw, err := cfg.clusterConfig.ToJSON()

if err != nil {
return nil, err
}
Expand Down
1 change: 1 addition & 0 deletions ipfs-cluster-service/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@ func daemon(c *cli.Context) error {
case <-signalChan:
err = cluster.Shutdown()
checkErr("shutting down cluster", err)
cfg.Shutdown()
case <-cluster.Done():
return nil

Expand Down
5 changes: 3 additions & 2 deletions peer_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ func (pm *peerManager) rmPeer(pid peer.ID, selfShutdown bool) error {
time.Sleep(1 * time.Second)
pm.cluster.consensus.Shutdown()
pm.cluster.config.Bootstrap = pm.peersAddrs()
pm.cluster.config.NotifySave()
pm.resetPeers()
time.Sleep(4 * time.Second)
pm.cluster.Shutdown()
Expand All @@ -79,7 +78,9 @@ func (pm *peerManager) rmPeer(pid peer.ID, selfShutdown bool) error {
}

func (pm *peerManager) savePeers() {
pm.cluster.config.Peers = pm.peersAddrs()
peers := pm.peersAddrs()
logger.Debugf("saving peers: %s", peers)
pm.cluster.config.Peers = peers
pm.cluster.config.NotifySave()
}

Expand Down

0 comments on commit 828236d

Please sign in to comment.