func cloneConfigs(app *models.App, configs []*models.Config, userKey string) (err error) { newDataVersion := genNewDataVersion(memConfDataVersion) s := models.NewSession() defer s.Close() if err = s.Begin(); err != nil { return } if _, err = updateApp(app, newDataVersion, s); err != nil { return } for _, config := range configs { if _, err = updateConfig(config, userKey, newDataVersion, s); err != nil { s.Rollback() return } } _app, err := models.GetAppByKey(s, app.Key) if err != nil { s.Rollback() return err } node, err := models.GetNodeByURL(s, conf.ClientAddr) if err != nil { s.Rollback() return err } if err = s.Commit(); err != nil { s.Rollback() return } *app = *_app updateMemConf(app, newDataVersion, node) for _, config := range configs { updateMemConf(config, newDataVersion, node) } return }
func updateMemConf(i interface{}, newDataVersion *models.DataVersion, node *models.Node, auxData ...interface{}) { memConfMux.Lock() defer memConfMux.Unlock() switch m := i.(type) { case *models.User: oldUser := memConfUsers[m.Key] if oldUser != nil { memConfUsersByName[m.Name] = nil } memConfUsers[m.Key] = m memConfUsersByName[m.Name] = m case *models.App: oldApp := memConfApps[m.Key] if oldApp != nil { memConfAppsByName[oldApp.Name] = nil } memConfApps[m.Key] = m memConfAppsByName[m.Name] = m case *models.Config: isSysConf := isSysConfType(m.AppKey) if !isSysConf && len(auxData) > 0 { toUpdateApps := auxData[0].([]*models.App) app, err := models.GetAppByKey(nil, m.AppKey) if err != nil { panic("Failed to load app info from db") } memConfApps[m.AppKey] = app for _, _app := range toUpdateApps { _app.DataSign = app.DataSign } } oldConfig := memConfRawConfigs[m.Key] if oldConfig == nil { memConfAppConfigs[m.AppKey] = append(memConfAppConfigs[m.AppKey], transConfig(m)) } else { for ix, _config := range memConfAppConfigs[m.AppKey] { if m.Key == _config.Key { memConfAppConfigs[m.AppKey][ix] = transConfig(m) break } } } memConfRawConfigs[m.Key] = m case *models.WebHook: oldHookIdx := auxData[0].(int) if oldHookIdx == -1 { if m.Scope == models.WEBHOOK_SCOPE_GLOBAL { memConfGlobalWebHooks = append(memConfGlobalWebHooks, m) } else if m.Scope == models.WEBHOOK_SCOPE_APP { memConfAppWebHooks[m.AppKey] = append(memConfAppWebHooks[m.AppKey], m) } } else { if m.Scope == models.WEBHOOK_SCOPE_GLOBAL { memConfGlobalWebHooks[oldHookIdx] = m } else if m.Scope == models.WEBHOOK_SCOPE_APP { memConfAppWebHooks[m.AppKey][oldHookIdx] = m } } } memConfDataVersion = newDataVersion if node != nil { memConfNodes[node.URL] = node } }
func updateConfig(config *models.Config, userKey string, newDataVersion *models.DataVersion, ms *models.Session) (*models.Config, error) { var s *models.Session if ms != nil { s = ms } else { s = models.NewSession() defer s.Close() if err := s.Begin(); err != nil { s.Rollback() return nil, err } } isSysConf := isSysConfType(config.AppKey) node := *memConfNodes[conf.ClientAddr] oldConfig := memConfRawConfigs[config.Key] app, err := models.GetAppByKey(s, config.AppKey) if err != nil { return nil, err } if newDataVersion == nil { newDataVersion = genNewDataVersion(memConfDataVersion) } if err := updateNodeDataVersion(s, &node, newDataVersion); err != nil { if ms == nil { s.Rollback() } return nil, err } var configHistory *models.ConfigUpdateHistory if oldConfig == nil { configHistory = &models.ConfigUpdateHistory{ Id: utils.GenerateKey(), ConfigKey: config.Key, K: config.K, OldV: "", OldVType: "", NewV: config.V, NewVType: config.VType, Kind: models.CONFIG_UPDATE_KIND_NEW, UserKey: userKey, CreatedUTC: utils.GetNowSecond(), } if err := models.InsertRow(s, configHistory); err != nil { if ms == nil { s.Rollback() } return nil, err } config.LastUpdateId = configHistory.Id if err := models.InsertRow(s, config); err != nil { if ms == nil { s.Rollback() } return nil, err } if !isSysConf { app.KeyCount++ app.LastUpdateUTC = configHistory.CreatedUTC app.LastUpdateId = configHistory.Id app.UpdateTimes++ } } else { kind := models.CONFIG_UPDATE_KIND_UPDATE if config.Status != oldConfig.Status { if config.Status == models.CONF_STATUS_ACTIVE { kind = models.CONFIG_UPDATE_KIND_RECOVER } else { kind = models.CONFIG_UPDATE_KIND_HIDE } } configHistory = &models.ConfigUpdateHistory{ Id: utils.GenerateKey(), ConfigKey: config.Key, K: config.K, OldV: oldConfig.V, OldVType: oldConfig.VType, NewV: config.V, NewVType: config.VType, Kind: kind, UserKey: userKey, CreatedUTC: utils.GetNowSecond(), } if err := models.InsertRow(s, configHistory); err != nil { if ms == nil { s.Rollback() } return nil, err } config.UpdateTimes++ config.LastUpdateId = configHistory.Id if err := models.UpdateDBModel(s, config); err != nil { if ms == nil { s.Rollback() } return nil, err } if !isSysConf { app.LastUpdateUTC = configHistory.CreatedUTC app.LastUpdateId = configHistory.Id app.UpdateTimes++ } } var toUpdateApps []*models.App if !isSysConf { newDataSign := utils.GenerateKey() app.DataSign = newDataSign if err := models.UpdateDBModel(s, app); err != nil { if ms == nil { s.Rollback() } return nil, err } if app.Type == models.APP_TYPE_TEMPLATE { for _, _app := range memConfApps { if _app.Key == config.AppKey { continue } for _, _config := range memConfAppConfigs[_app.Key] { if _config.VType == models.CONF_V_TYPE_TEMPLATE && _config.V == config.AppKey { // this app has a config refer to this template app toUpdateApps = append(toUpdateApps, _app) break } } } } for _, app := range toUpdateApps { _app := *app _app.DataSign = newDataSign if err := models.UpdateDBModel(s, &_app); err != nil { if ms == nil { s.Rollback() } return nil, err } } } if ms == nil { if err := s.Commit(); err != nil { s.Rollback() return nil, err } if !isSysConf { go TriggerWebHooks(configHistory, app) } else { go TriggerWebHooks(configHistory, &models.App{Key: config.Key, Name: config.Key}) } updateMemConf(config, newDataVersion, &node, toUpdateApps) } return config, nil }