package models import ( "github.com/TeaOSLab/EdgeCommon/pkg/configutils" "github.com/TeaOSLab/EdgeCommon/pkg/nodeconfigs" _ "github.com/go-sql-driver/mysql" "github.com/iwind/TeaGo/Tea" "github.com/iwind/TeaGo/dbs" "github.com/iwind/TeaGo/maps" "github.com/iwind/TeaGo/types" "strings" "time" ) type NodeTaskType = string const ( // CDN鐩稿叧 NodeTaskTypeConfigChanged NodeTaskType = "configChanged" // 鑺傜偣鏁翠綋閰嶇疆鍙樺寲 NodeTaskTypeDDosProtectionChanged NodeTaskType = "ddosProtectionChanged" // 鑺傜偣DDoS閰嶇疆鍙樻洿 NodeTaskTypeGlobalServerConfigChanged NodeTaskType = "globalServerConfigChanged" // 鍏ㄥ眬鏈嶅姟璁剧疆鍙樺寲 NodeTaskTypeIPListDeleted NodeTaskType = "ipListDeleted" // IPList琚垹闄? NodeTaskTypeIPItemChanged NodeTaskType = "ipItemChanged" // IP鏉$洰鍙樻洿 NodeTaskTypeNodeVersionChanged NodeTaskType = "nodeVersionChanged" // 鑺傜偣鐗堟湰鍙樺寲 NodeTaskTypeScriptsChanged NodeTaskType = "scriptsChanged" // 鑴氭湰閰嶇疆鍙樺寲 NodeTaskTypeNodeLevelChanged NodeTaskType = "nodeLevelChanged" // 鑺傜偣绾у埆鍙樺寲 NodeTaskTypeUserServersStateChanged NodeTaskType = "userServersStateChanged" // 鐢ㄦ埛鏈嶅姟鐘舵€佸彉鍖? NodeTaskTypeUAMPolicyChanged NodeTaskType = "uamPolicyChanged" // UAM绛栫暐鍙樺寲 NodeTaskTypeHTTPPagesPolicyChanged NodeTaskType = "httpPagesPolicyChanged" // 鑷畾涔夐〉闈㈠彉鍖? NodeTaskTypeHTTPCCPolicyChanged NodeTaskType = "httpCCPolicyChanged" // CC绛栫暐鍙樺寲 NodeTaskTypeHTTP3PolicyChanged NodeTaskType = "http3PolicyChanged" // HTTP3绛栫暐鍙樺寲 NodeTaskTypeNetworkSecurityPolicyChanged NodeTaskType = "networkSecurityPolicyChanged" // 缃戠粶瀹夊叏绛栫暐鍙樺寲 NodeTaskTypeWebPPolicyChanged NodeTaskType = "webPPolicyChanged" // WebP绛栫暐鍙樺寲 NodeTaskTypeUpdatingServers NodeTaskType = "updatingServers" // 鏇存柊涓€缁勬湇鍔? NodeTaskTypeTOAChanged NodeTaskType = "toaChanged" // TOA閰嶇疆鍙樺寲 NodeTaskTypePlanChanged NodeTaskType = "planChanged" // 濂楅鍙樺寲 // NS鐩稿叧 NSNodeTaskTypeConfigChanged NodeTaskType = "nsConfigChanged" NSNodeTaskTypeDomainChanged NodeTaskType = "nsDomainChanged" NSNodeTaskTypeRecordChanged NodeTaskType = "nsRecordChanged" NSNodeTaskTypeRouteChanged NodeTaskType = "nsRouteChanged" NSNodeTaskTypeKeyChanged NodeTaskType = "nsKeyChanged" NSNodeTaskTypeDDosProtectionChanged NodeTaskType = "nsDDoSProtectionChanged" // 鑺傜偣DDoS閰嶇疆鍙樻洿 // HTTPDNS相关 HTTPDNSNodeTaskTypeConfigChanged NodeTaskType = "httpdnsConfigChanged" HTTPDNSNodeTaskTypeAppChanged NodeTaskType = "httpdnsAppChanged" HTTPDNSNodeTaskTypeDomainChanged NodeTaskType = "httpdnsDomainChanged" HTTPDNSNodeTaskTypeRuleChanged NodeTaskType = "httpdnsRuleChanged" HTTPDNSNodeTaskTypeTLSChanged NodeTaskType = "httpdnsTLSChanged" ) type NodeTaskDAO dbs.DAO func NewNodeTaskDAO() *NodeTaskDAO { return dbs.NewDAO(&NodeTaskDAO{ DAOObject: dbs.DAOObject{ DB: Tea.Env, Table: "edgeNodeTasks", Model: new(NodeTask), PkName: "id", }, }).(*NodeTaskDAO) } var SharedNodeTaskDAO *NodeTaskDAO func init() { dbs.OnReady(func() { SharedNodeTaskDAO = NewNodeTaskDAO() }) } // CreateNodeTask 鍒涘缓鍗曚釜鑺傜偣浠诲姟 func (this *NodeTaskDAO) CreateNodeTask(tx *dbs.Tx, role string, clusterId int64, nodeId int64, userId int64, serverId int64, taskType NodeTaskType) error { if clusterId <= 0 || nodeId <= 0 { return nil } var uniqueId = role + "@" + types.String(nodeId) + "@node@" + types.String(serverId) + "@" + taskType // 鐢ㄦ埛淇℃伅 // 娌℃湁鐩存帴鍔犲叆鍒?uniqueId 涓紝鏄负浜嗗吋瀹逛互鍓嶇殑瀛楁鍊? if userId > 0 { uniqueId += "@" + types.String(userId) } version, err := this.increaseVersion(tx) if err != nil { return err } var updatedAt = time.Now().Unix() _, _, err = this.Query(tx). InsertOrUpdate(maps.Map{ "role": role, "clusterId": clusterId, "nodeId": nodeId, "userId": userId, "serverId": serverId, "type": taskType, "uniqueId": uniqueId, "updatedAt": updatedAt, "isDone": 0, "isOk": 0, "error": "", "version": version, }, maps.Map{ "clusterId": clusterId, "updatedAt": updatedAt, "isDone": 0, "isOk": 0, "error": "", "isNotified": 0, "version": version, "serverId": serverId, }) return err } // CreateClusterTask 鍒涘缓闆嗙兢浠诲姟 func (this *NodeTaskDAO) CreateClusterTask(tx *dbs.Tx, role string, clusterId int64, userId int64, serverId int64, taskType NodeTaskType) error { if clusterId <= 0 { return nil } var uniqueId = role + "@" + types.String(clusterId) + "@" + types.String(serverId) + "@cluster@" + taskType // 鐢ㄦ埛淇℃伅 // 娌℃湁鐩存帴鍔犲叆鍒?uniqueId 涓紝鏄负浜嗗吋瀹逛互鍓嶇殑瀛楁鍊? if userId > 0 { uniqueId += "@" + types.String(userId) } var updatedAt = time.Now().Unix() _, _, err := this.Query(tx). InsertOrUpdate(maps.Map{ "role": role, "clusterId": clusterId, "userId": userId, "serverId": serverId, "nodeId": 0, "type": taskType, "uniqueId": uniqueId, "updatedAt": updatedAt, "isDone": 0, "isOk": 0, "isNotified": 0, "error": "", "version": time.Now().UnixNano(), }, maps.Map{ "updatedAt": updatedAt, "isDone": 0, "isOk": 0, "isNotified": 0, "error": "", "version": time.Now().UnixNano(), "serverId": serverId, }) return err } // ExtractNodeClusterTask 鍒嗚В杈圭紭鑺傜偣闆嗙兢浠诲姟 func (this *NodeTaskDAO) ExtractNodeClusterTask(tx *dbs.Tx, clusterId int64, userId int64, serverId int64, taskType NodeTaskType) error { nodeIds, err := SharedNodeDAO.FindAllNodeIdsMatch(tx, clusterId, true, configutils.BoolStateYes) if err != nil { return err } _, err = this.Query(tx). Attr("role", nodeconfigs.NodeRoleNode). Attr("clusterId", clusterId). Attr("serverId", serverId). Gt("nodeId", 0). Attr("type", taskType). Delete() if err != nil { return err } for _, nodeId := range nodeIds { err = this.CreateNodeTask(tx, nodeconfigs.NodeRoleNode, clusterId, nodeId, userId, serverId, taskType) if err != nil { return err } } _, err = this.Query(tx). Attr("role", nodeconfigs.NodeRoleNode). Attr("clusterId", clusterId). Attr("nodeId", 0). Attr("type", taskType). Delete() if err != nil { return err } return nil } // ExtractAllClusterTasks 鍒嗚В鎵€鏈夐泦缇や换鍔? func (this *NodeTaskDAO) ExtractAllClusterTasks(tx *dbs.Tx, role string) error { ones, err := this.Query(tx). Attr("role", role). Attr("nodeId", 0). FindAll() if err != nil { return err } for _, one := range ones { var clusterId = int64(one.(*NodeTask).ClusterId) switch role { case nodeconfigs.NodeRoleNode: var nodeTask = one.(*NodeTask) err = this.ExtractNodeClusterTask(tx, clusterId, int64(nodeTask.UserId), int64(nodeTask.ServerId), nodeTask.Type) if err != nil { return err } case nodeconfigs.NodeRoleDNS: err = this.ExtractNSClusterTask(tx, clusterId, one.(*NodeTask).Type) if err != nil { return err } case nodeconfigs.NodeRoleHTTPDNS: err = this.ExtractHTTPDNSClusterTask(tx, clusterId, one.(*NodeTask).Type) if err != nil { return err } } } return nil } // DeleteAllClusterTasks 鍒犻櫎闆嗙兢鎵€鏈夌浉鍏充换鍔? func (this *NodeTaskDAO) DeleteAllClusterTasks(tx *dbs.Tx, role string, clusterId int64) error { _, err := this.Query(tx). Attr("role", role). Attr("clusterId", clusterId). Delete() return err } // DeleteNodeTasks 鍒犻櫎鑺傜偣鐩稿叧浠诲姟 func (this *NodeTaskDAO) DeleteNodeTasks(tx *dbs.Tx, role string, nodeId int64) error { _, err := this.Query(tx). Attr("role", role). Attr("nodeId", nodeId). Delete() return err } // DeleteAllNodeTasks 鍒犻櫎鎵€鏈夎妭鐐圭浉鍏充换鍔? func (this *NodeTaskDAO) DeleteAllNodeTasks(tx *dbs.Tx) error { return this.Query(tx). DeleteQuickly() } // FindDoingNodeTasks 鏌ヨ涓€涓妭鐐圭殑鎵€鏈変换鍔? func (this *NodeTaskDAO) FindDoingNodeTasks(tx *dbs.Tx, role string, nodeId int64, version int64) (result []*NodeTask, err error) { if nodeId <= 0 { return } var query = this.Query(tx). Attr("role", role). Attr("nodeId", nodeId). UseIndex("nodeId"). Asc("version") if version > 0 { query.Lt("LENGTH(version)", 19) // 鍏煎浠ュ線鐗堟湰 query.Gt("version", version) } else { // 绗竴娆¤闂椂鍙彇褰撳墠姝e湪鎵ц鐨勬垨鑰呮墽琛屽け璐ョ殑 query.Where("(isDone=0 OR (isDone=1 AND isOk=0))") } _, err = query. Slice(&result). FindAll() return } // UpdateNodeTaskDone 淇敼鑺傜偣浠诲姟鐨勫畬鎴愮姸鎬? func (this *NodeTaskDAO) UpdateNodeTaskDone(tx *dbs.Tx, taskId int64, isOk bool, errorMessage string) error { if isOk { // 鐗规畩浠诲姟鍒犻櫎 taskType, err := this.Query(tx). Pk(taskId). Result("type"). FindStringCol("") if err != nil { return err } if strings.HasPrefix(taskType, NodeTaskTypeIPListDeleted+"@") { return this.Query(tx). Pk(taskId). DeleteQuickly() } } // 鍏朵粬浠诲姟鏍囪涓哄畬鎴? var query = this.Query(tx). Pk(taskId) if !isOk { version, err := this.increaseVersion(tx) if err != nil { return err } query.Set("version", version) } _, err := query. Set("isDone", true). Set("isOk", isOk). Set("error", errorMessage). Update() return err } // FindAllDoingTaskClusterIds 鏌ユ壘姝e湪鏇存柊鐨勯泦缇Ds func (this *NodeTaskDAO) FindAllDoingTaskClusterIds(tx *dbs.Tx, role string) ([]int64, error) { ones, _, err := this.Query(tx). Result("DISTINCT(clusterId) AS clusterId"). Attr("role", role). Where("(nodeId=0 OR (isDone=0 OR (isDone=1 AND isOk=0)))"). FindOnes() if err != nil { return nil, err } result := []int64{} for _, one := range ones { result = append(result, one.GetInt64("clusterId")) } return result, nil } // FindAllDoingNodeTasksWithClusterId 鏌ヨ鏌愪釜闆嗙兢涓嬫墍鏈夌殑浠诲姟 func (this *NodeTaskDAO) FindAllDoingNodeTasksWithClusterId(tx *dbs.Tx, role string, clusterId int64) (result []*NodeTask, err error) { _, err = this.Query(tx). Attr("role", role). Attr("clusterId", clusterId). Gt("nodeId", 0). Where("(isDone=0 OR (isDone=1 AND isOk=0))"). Desc("isDone"). Asc("nodeId"). AscPk(). Slice(&result). FindAll() return } // FindAllDoingNodeIds 鏌ヨ鏈変换鍔$殑鑺傜偣IDs func (this *NodeTaskDAO) FindAllDoingNodeIds(tx *dbs.Tx, role string) ([]int64, error) { ones, err := this.Query(tx). Result("DISTINCT(nodeId) AS nodeId"). Attr("role", role). Gt("nodeId", 0). Attr("isDone", false). Attr("isNotified", 0). FindAll() if err != nil { return nil, err } var result []int64 for _, one := range ones { result = append(result, int64(one.(*NodeTask).NodeId)) } return result, nil } // ExistsDoingNodeTasks 妫€鏌ユ槸鍚︽湁姝e湪鎵ц鐨勪换鍔? func (this *NodeTaskDAO) ExistsDoingNodeTasks(tx *dbs.Tx, role string, excludeTypes []NodeTaskType) (bool, error) { var query = this.Query(tx). Attr("role", role). Where("(isDone=0 OR (isDone=1 AND isOk=0))"). Gt("nodeId", 0) if len(excludeTypes) > 0 { for _, excludeType := range excludeTypes { query.Neq("type", excludeType) } } return query.Exist() } // ExistsErrorNodeTasks 鏄惁鏈夐敊璇殑浠诲姟 func (this *NodeTaskDAO) ExistsErrorNodeTasks(tx *dbs.Tx, role string, excludeTypes []NodeTaskType) (bool, error) { var query = this.Query(tx). Attr("role", role). Where("(isDone=1 AND isOk=0)") if len(excludeTypes) > 0 { for _, excludeType := range excludeTypes { query.Neq("type", excludeType) } } return query.Exist() } // DeleteNodeTask 鍒犻櫎浠诲姟 func (this *NodeTaskDAO) DeleteNodeTask(tx *dbs.Tx, taskId int64) error { _, err := this.Query(tx). Pk(taskId). Delete() return err } // CountDoingNodeTasks 璁$畻姝e湪鎵ц鐨勪换鍔? func (this *NodeTaskDAO) CountDoingNodeTasks(tx *dbs.Tx, role string) (int64, error) { return this.Query(tx). Attr("isDone", 0). Attr("role", role). Gt("nodeId", 0). Count() } // FindNotifyingNodeTasks 鏌ユ壘闇€瑕侀€氱煡鐨勪换鍔? func (this *NodeTaskDAO) FindNotifyingNodeTasks(tx *dbs.Tx, role string, size int64) (result []*NodeTask, err error) { _, err = this.Query(tx). Attr("role", role). Gt("nodeId", 0). Attr("isNotified", 0). Attr("isDone", 0). Limit(size). Slice(&result). FindAll() return } // UpdateTasksNotified 璁剧疆浠诲姟宸查€氱煡 func (this *NodeTaskDAO) UpdateTasksNotified(tx *dbs.Tx, taskIds []int64) error { if len(taskIds) == 0 { return nil } for _, taskId := range taskIds { _, err := this.Query(tx). Pk(taskId). Set("isNotified", 1). Update() if err != nil { return err } } return nil } // 鐢熸垚涓€涓増鏈彿 func (this *NodeTaskDAO) increaseVersion(tx *dbs.Tx) (version int64, err error) { return SharedSysLockerDAO.Increase(tx, "NODE_TASK_VERSION", 0) }