Browse Source

api: fix concurrency issue when creating multiple path configs at once (#542)

pull/591/head
aler9 4 years ago
parent
commit
ddcd0c34cf
  1. 21
      internal/core/api.go
  2. 18
      internal/core/core.go

21
internal/core/api.go

@ -361,10 +361,10 @@ func (a *api) onConfigSet(ctx *gin.Context) { @@ -361,10 +361,10 @@ func (a *api) onConfigSet(ctx *gin.Context) {
}
a.mutex.Lock()
defer a.mutex.Unlock()
var newConf conf.Conf
cloneStruct(a.conf, &newConf)
a.mutex.Unlock()
fillStruct(&newConf, in)
err = newConf.CheckAndFillMissing()
@ -373,9 +373,7 @@ func (a *api) onConfigSet(ctx *gin.Context) { @@ -373,9 +373,7 @@ func (a *api) onConfigSet(ctx *gin.Context) {
return
}
a.mutex.Lock()
a.conf = &newConf
a.mutex.Unlock()
// since reloading the configuration can cause the shutdown of the API,
// call it in a goroutine
@ -394,9 +392,10 @@ func (a *api) onConfigPathsAdd(ctx *gin.Context) { @@ -394,9 +392,10 @@ func (a *api) onConfigPathsAdd(ctx *gin.Context) {
name := ctx.Param("name")
a.mutex.Lock()
defer a.mutex.Unlock()
var newConf conf.Conf
cloneStruct(a.conf, &newConf)
a.mutex.Unlock()
if _, ok := newConf.Paths[name]; ok {
ctx.AbortWithStatus(http.StatusBadRequest)
@ -413,9 +412,7 @@ func (a *api) onConfigPathsAdd(ctx *gin.Context) { @@ -413,9 +412,7 @@ func (a *api) onConfigPathsAdd(ctx *gin.Context) {
return
}
a.mutex.Lock()
a.conf = &newConf
a.mutex.Unlock()
// since reloading the configuration can cause the shutdown of the API,
// call it in a goroutine
@ -434,9 +431,10 @@ func (a *api) onConfigPathsEdit(ctx *gin.Context) { @@ -434,9 +431,10 @@ func (a *api) onConfigPathsEdit(ctx *gin.Context) {
name := ctx.Param("name")
a.mutex.Lock()
defer a.mutex.Unlock()
var newConf conf.Conf
cloneStruct(a.conf, &newConf)
a.mutex.Unlock()
newConfPath, ok := newConf.Paths[name]
if !ok {
@ -452,9 +450,7 @@ func (a *api) onConfigPathsEdit(ctx *gin.Context) { @@ -452,9 +450,7 @@ func (a *api) onConfigPathsEdit(ctx *gin.Context) {
return
}
a.mutex.Lock()
a.conf = &newConf
a.mutex.Unlock()
// since reloading the configuration can cause the shutdown of the API,
// call it in a goroutine
@ -467,9 +463,10 @@ func (a *api) onConfigPathsDelete(ctx *gin.Context) { @@ -467,9 +463,10 @@ func (a *api) onConfigPathsDelete(ctx *gin.Context) {
name := ctx.Param("name")
a.mutex.Lock()
defer a.mutex.Unlock()
var newConf conf.Conf
cloneStruct(a.conf, &newConf)
a.mutex.Unlock()
if _, ok := newConf.Paths[name]; !ok {
ctx.AbortWithStatus(http.StatusBadRequest)
@ -484,9 +481,7 @@ func (a *api) onConfigPathsDelete(ctx *gin.Context) { @@ -484,9 +481,7 @@ func (a *api) onConfigPathsDelete(ctx *gin.Context) {
return
}
a.mutex.Lock()
a.conf = &newConf
a.mutex.Unlock()
// since reloading the configuration can cause the shutdown of the API,
// call it in a goroutine

18
internal/core/core.go

@ -83,7 +83,7 @@ func New(args []string) (*Core, bool) { @@ -83,7 +83,7 @@ func New(args []string) (*Core, bool) {
err = p.createResources(true)
if err != nil {
p.Log(logger.Info, "ERR: %s", err)
p.closeResources(nil)
p.closeResources(nil, false)
return nil, false
}
@ -91,7 +91,7 @@ func New(args []string) (*Core, bool) { @@ -91,7 +91,7 @@ func New(args []string) (*Core, bool) {
p.confWatcher, err = confwatcher.New(p.confPath)
if err != nil {
p.Log(logger.Info, "ERR: %s", err)
p.closeResources(nil)
p.closeResources(nil, false)
return nil, false
}
}
@ -143,7 +143,7 @@ outer: @@ -143,7 +143,7 @@ outer:
break outer
}
err = p.reloadConf(newConf)
err = p.reloadConf(newConf, false)
if err != nil {
p.Log(logger.Info, "ERR: %s", err)
break outer
@ -152,7 +152,7 @@ outer: @@ -152,7 +152,7 @@ outer:
case newConf := <-p.apiConfigSet:
p.Log(logger.Info, "reloading configuration (API request)")
err := p.reloadConf(newConf)
err := p.reloadConf(newConf, true)
if err != nil {
p.Log(logger.Info, "ERR: %s", err)
break outer
@ -165,7 +165,7 @@ outer: @@ -165,7 +165,7 @@ outer:
p.ctxCancel()
p.closeResources(nil)
p.closeResources(nil, false)
if p.confWatcher != nil {
p.confWatcher.Close()
@ -361,7 +361,7 @@ func (p *Core) createResources(initial bool) error { @@ -361,7 +361,7 @@ func (p *Core) createResources(initial bool) error {
return nil
}
func (p *Core) closeResources(newConf *conf.Conf) {
func (p *Core) closeResources(newConf *conf.Conf, calledByAPI bool) {
closeStats := false
if newConf == nil {
closeStats = true
@ -489,7 +489,7 @@ func (p *Core) closeResources(newConf *conf.Conf) { @@ -489,7 +489,7 @@ func (p *Core) closeResources(newConf *conf.Conf) {
if closeAPI {
p.api.close()
p.api = nil
} else {
} else if !calledByAPI { // avoid a loop
p.api.OnConfReload(newConf)
}
}
@ -539,8 +539,8 @@ func (p *Core) closeResources(newConf *conf.Conf) { @@ -539,8 +539,8 @@ func (p *Core) closeResources(newConf *conf.Conf) {
}
}
func (p *Core) reloadConf(newConf *conf.Conf) error {
p.closeResources(newConf)
func (p *Core) reloadConf(newConf *conf.Conf, calledByAPI bool) error {
p.closeResources(newConf, calledByAPI)
p.conf = newConf
return p.createResources(false)

Loading…
Cancel
Save