diff --git a/server/internal/handler/app.go b/server/internal/handler/app.go index 6cf7d91..d4280e4 100644 --- a/server/internal/handler/app.go +++ b/server/internal/handler/app.go @@ -103,7 +103,6 @@ func (h *AppHandler) GetById(c *gin.Context) { type AddAppRequest struct { Id int `json:"id"` GroupId *int `json:"groupId"` - ParentId *int `json:"parentId"` Name string `json:"name" binding:"required"` Code string `json:"code" binding:"required"` ServiceId string `json:"serviceId"` @@ -141,7 +140,6 @@ func (h *AppHandler) Add(c *gin.Context) { app := model.Application{ GroupId: req.GroupId, - ParentId: req.ParentId, Name: req.Name, Code: req.Code, ServiceId: req.ServiceId, @@ -153,15 +151,6 @@ func (h *AppHandler) Add(c *gin.Context) { CreatedBy: userInfo.Name, } - if req.ParentId != nil { - var parent model.Application - if has, _ := dao.Engine.ID(*req.ParentId).Get(&parent); has { - app.GroupId = parent.GroupId - app.IsModule = true - app.Code = parent.Code + "-" + req.Code - } - } - dao.Engine.Insert(&app) c.JSON(http.StatusOK, model.WrapperResponse{Code: 0, Data: true}) diff --git a/server/internal/handler/config.go b/server/internal/handler/config.go index c3c48f9..2ebec9f 100644 --- a/server/internal/handler/config.go +++ b/server/internal/handler/config.go @@ -94,7 +94,7 @@ func (h *ConfigHandler) List(c *gin.Context) { } var results []countResult dao.Engine.Table("client_instance"). - Select("app_config_id, COUNT(DISTINCT ip) as cnt"). + Select("app_config_id, COUNT(*) as cnt"). In("app_config_id", configIds). GroupBy("app_config_id"). Find(&results) diff --git a/server/internal/handler/config_api.go b/server/internal/handler/config_api.go index a8f0994..e97b650 100644 --- a/server/internal/handler/config_api.go +++ b/server/internal/handler/config_api.go @@ -13,7 +13,7 @@ import ( ) type ConfigApiHandler struct { - parseService *service.ConfigParseService + parseService *service.ConfigParseService } func NewConfigApiHandler(parse *service.ConfigParseService) *ConfigApiHandler { @@ -86,20 +86,6 @@ func (h *ConfigApiHandler) FetchAllConfigs(c *gin.Context) { } } - // load parent app configs - if app.ParentId != nil { - var parentConfigs []model.AppConfig - dao.Engine.Where("env = ? AND version = ? AND enabled = 1 AND app_id = ?", - req.Env, version, *app.ParentId).Find(&parentConfigs) - for _, cfg := range parentConfigs { - configIds = append(configIds, cfg.Id) - kvMap := h.parseService.ParseConfigToKVMap(&cfg) - for k, v := range kvMap { - result[k] = v - } - } - } - // load app configs var appConfigs []model.AppConfig dao.Engine.Where("env = ? AND version = ? AND enabled = 1 AND app_id = ?", @@ -176,30 +162,41 @@ func (h *ConfigApiHandler) FetchChangedConfigs(c *gin.Context) { } } - // load parent app changed configs - if app.ParentId != nil { - var parentConfigs []model.AppConfig - dao.Engine.Where("env = ? AND version = ? AND enabled = 1 AND app_id = ? AND updated_at > ?", - req.Env, version, *app.ParentId, lastUpdateTime).Find(&parentConfigs) - for _, cfg := range parentConfigs { - configIds = append(configIds, cfg.Id) - h.addChangedConfigs(result, &cfg, req.FetchAll) - } - } - // load app changed configs - var appConfigs []model.AppConfig + var appConfigs1 []model.AppConfig dao.Engine.Where("env = ? AND version = ? AND enabled = 1 AND app_id = ? AND updated_at > ?", - req.Env, version, app.Id, lastUpdateTime).Find(&appConfigs) - for _, cfg := range appConfigs { + req.Env, version, app.Id, lastUpdateTime).Find(&appConfigs1) + for _, cfg := range appConfigs1 { configIds = append(configIds, cfg.Id) h.addChangedConfigs(result, &cfg, req.FetchAll) } result["latest.fetch.timestamp"] = strconv.FormatInt(time.Now().UnixMilli(), 10) + // query all config ids for this app to record client instances + var allConfigIds []int + if !req.IgnoreGlobal && app.GroupId != nil { + var globalConfigs []model.AppConfig + dao.Engine.Where("env = ? AND version = ? AND enabled = 1 AND group_id = ? AND (app_id is null OR app_id = 0)", + req.Env, version, *app.GroupId).Find(&globalConfigs) + for _, cfg := range globalConfigs { + allConfigIds = append(allConfigIds, cfg.Id) + } + } + var appConfigs2 []model.AppConfig + dao.Engine.Where("env = ? AND version = ? AND enabled = 1 AND app_id = ?", + req.Env, version, app.Id).Find(&appConfigs2) + for _, cfg := range appConfigs2 { + allConfigIds = append(allConfigIds, cfg.Id) + } + // record client instances asynchronously - go h.recordClientInstances(c.ClientIP(), configIds, req.AppName, req.Env, "fetchChanged") + // only update last_fetch_at if there are actual changes + fetchType := "" + if len(configIds) > 0 { + fetchType = "fetchChanged" + } + go h.recordClientInstances(c.ClientIP(), allConfigIds, req.AppName, req.Env, fetchType) c.JSON(http.StatusOK, model.WrapperResponse{Code: 0, Data: result}) } @@ -218,29 +215,41 @@ func (h *ConfigApiHandler) recordClientInstances(ip string, configIds []int, app now := time.Now() for _, configId := range configIds { var existing model.ClientInstance - has, _ := dao.Engine.Where("app_config_id = ? AND ip = ?", configId, ip).Get(&existing) + has, _ := dao.Engine.Where("app_config_id = ? AND app_name = ? AND env = ? AND ip = ?", configId, appName, env, ip).Get(&existing) if has { - existing.LastFetchAt = &now - existing.LastFetchType = fetchType + existing.LastPingAt = &now existing.UpdatedAt = &now - dao.Engine.ID(existing.Id).Cols("last_fetch_at", "last_fetch_type", "updated_at").Update(&existing) + if fetchType != "" { + existing.LastFetchAt = &now + existing.LastFetchType = fetchType + dao.Engine.ID(existing.Id).Cols("last_ping_at", "last_fetch_at", "last_fetch_type", "updated_at").Update(&existing) + } else { + dao.Engine.ID(existing.Id).Cols("last_ping_at", "updated_at").Update(&existing) + } } else { instance := model.ClientInstance{ AppConfigId: configId, AppName: appName, Env: env, - IP: ip, - LastFetchAt: &now, - LastFetchType: fetchType, + Ip: ip, + LastPingAt: &now, CreatedAt: &now, UpdatedAt: &now, } - dao.Engine.Insert(&instance) + if fetchType != "" { + instance.LastFetchAt = &now + instance.LastFetchType = fetchType + } + _, err := dao.Engine.Insert(&instance) + if err != nil { + fmt.Printf("[recordClientInstances] insert error: %v\n", err) + continue + } } } // cleanup records older than 5 minutes fiveMinutesAgo := now.Add(-5 * time.Minute) - dao.Engine.Where("last_fetch_at < ?", fiveMinutesAgo).Delete(&model.ClientInstance{}) + dao.Engine.Where("last_ping_at < ?", fiveMinutesAgo).Delete(&model.ClientInstance{}) } // func (h *ConfigApiHandler) Ping(c *gin.Context) { diff --git a/server/internal/model/application.go b/server/internal/model/application.go index afe83ed..bb768d1 100644 --- a/server/internal/model/application.go +++ b/server/internal/model/application.go @@ -5,12 +5,10 @@ import "time" type Application struct { Id int `xorm:"int autoincr pk" json:"id"` GroupId *int `xorm:"int" json:"groupId"` - ParentId *int `xorm:"int" json:"parentId"` Name string `xorm:"varchar(32)" json:"name"` Code string `xorm:"varchar(32)" json:"code"` ServiceId string `xorm:"varchar(64)" json:"serviceId"` Token string `xorm:"varchar(64)" json:"token"` - IsModule bool `xorm:"tinyint(1) default 1" json:"isModule"` OwnerId *int `xorm:"int" json:"ownerId"` OwnerName string `xorm:"varchar(16)" json:"ownerName"` Remarks string `xorm:"text" json:"remarks"` @@ -19,7 +17,5 @@ type Application struct { CreatedBy string `xorm:"varchar(32)" json:"createdBy"` UpdatedAt *time.Time `xorm:"datetime" json:"updatedAt"` UpdatedBy string `xorm:"varchar(32)" json:"updatedBy"` - ParentName string `xorm:"-" json:"parentName,omitempty"` - FullName string `xorm:"-" json:"fullName,omitempty"` GroupName string `xorm:"-" json:"groupName,omitempty"` } diff --git a/server/internal/model/client_instance.go b/server/internal/model/client_instance.go index 46c3ef6..f8f2304 100644 --- a/server/internal/model/client_instance.go +++ b/server/internal/model/client_instance.go @@ -4,10 +4,11 @@ import "time" type ClientInstance struct { Id int `xorm:"int autoincr pk" json:"id"` - AppConfigId int `xorm:"int index" json:"appConfigId"` - AppName string `xorm:"varchar(64) index" json:"appName"` - Env string `xorm:"varchar(32)" json:"env"` - IP string `xorm:"varchar(64)" json:"ip"` + AppConfigId int `xorm:"int unique(udx_aaei)" json:"appConfigId"` + AppName string `xorm:"varchar(64) unique(udx_aaei)" json:"appName"` + Env string `xorm:"varchar(32) unique(udx_aaei)" json:"env"` + Ip string `xorm:"varchar(64) unique(udx_aaei)" json:"ip"` + LastPingAt *time.Time `xorm:"datetime" json:"lastPingAt"` LastFetchAt *time.Time `xorm:"datetime" json:"lastFetchAt"` LastFetchType string `xorm:"varchar(16)" json:"lastFetchType"` CreatedAt *time.Time `xorm:"datetime" json:"createdAt"`