view pkg/geoserver/reconf.go @ 890:0a563fef64a9 geo-style

Reconfiguring GeoServer is now queued async. We should not reconfigure the remote until the initial config is done.
author Sascha L. Teichmann <teichmann@intevation.de>
date Tue, 02 Oct 2018 12:58:20 +0200
parents
children a244b18cb916
line wrap: on
line source

package geoserver

import (
	"container/list"
	"log"
	"net"
	"net/url"
	"sync"
	"time"
)

var (
	confQueue     = list.New()
	confQueueCond = sync.NewCond(new(sync.Mutex))
)

func init() {
	go asyncConfigure()
}

func asyncConfigure() {
	for {
		var fn func() error
		confQueueCond.L.Lock()
		for confQueue.Len() == 0 {
			confQueueCond.Wait()
		}
		fn = confQueue.Remove(confQueue.Front()).(func() error)
		confQueueCond.L.Unlock()
		if err := reconfigure(fn); err != nil {
			log.Printf("warn: configure GeoServer failed: %v\n", err)
		}
	}
}

func reconfigure(fn func() error) error {
	log.Println("Configure GeoServer...")
	const (
		maxTries = 10
		sleep    = time.Second * 5
	)
	var err error
	for try := 1; try <= maxTries; try++ {
		if err = fn(); err == nil {
			break
		}
		if try < maxTries {
			if uerr, ok := err.(*url.Error); ok {
				if oerr, ok := uerr.Err.(*net.OpError); ok && oerr.Op == "dial" {
					log.Printf("Failed attempt %d of %d to configure GeoServer. "+
						"Will try again in %s...\n", try, maxTries, sleep)
					time.Sleep(sleep)
					continue
				}
			}
		}
		break
	}
	return err
}

func Reconfigure(fn func() error) {
	confQueueCond.L.Lock()
	defer confQueueCond.L.Unlock()
	confQueue.PushBack(fn)
	confQueueCond.Signal()
}