Handle error returned by GetClusterInfos() (#30919)

A recent change to the enterprise cluster code introduced a change to the enterprise API interface. GetClusterInfos() can now return an error. This commit introduces code to handle that error.
Этот коммит содержится в:
David Krauser
2025-05-12 13:37:58 -04:00
коммит произвёл GitHub
родитель dfe6478fd7
Коммит 4b64eb0e39
10 изменённых файлов: 48 добавлений и 28 удалений

Просмотреть файл

@@ -20,7 +20,12 @@ func getClusterStatus(c *Context, w http.ResponseWriter, r *http.Request) {
return return
} }
infos := c.App.GetClusterStatus(c.AppContext) infos, err := c.App.GetClusterStatus(c.AppContext)
if err != nil {
c.Err = model.NewAppError("getClusterStatus", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err)
return
}
js, err := json.Marshal(infos) js, err := json.Marshal(infos)
if err != nil { if err != nil {
c.Err = model.NewAppError("getClusterStatus", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err) c.Err = model.NewAppError("getClusterStatus", "api.marshal_error", nil, "", http.StatusInternalServerError).Wrap(err)

Просмотреть файл

@@ -131,14 +131,11 @@ func (a *App) GetLogsSkipSend(rctx request.CTX, page, perPage int, logFilter *mo
return a.Srv().GetLogsSkipSend(rctx, page, perPage, logFilter) return a.Srv().GetLogsSkipSend(rctx, page, perPage, logFilter)
} }
func (a *App) GetClusterStatus(rctx request.CTX) []*model.ClusterInfo { func (a *App) GetClusterStatus(rctx request.CTX) ([]*model.ClusterInfo, error) {
infos := make([]*model.ClusterInfo, 0) if a.Cluster() == nil {
return make([]*model.ClusterInfo, 0), nil
if a.Cluster() != nil {
infos = a.Cluster().GetClusterInfos()
} }
return a.Cluster().GetClusterInfos()
return infos
} }
func (s *Server) InvalidateAllCaches() *model.AppError { func (s *Server) InvalidateAllCaches() *model.AppError {

Просмотреть файл

@@ -138,11 +138,11 @@ func (c *ClusterMock) StartInterNodeCommunication() {}
func (c *ClusterMock) StopInterNodeCommunication() {} func (c *ClusterMock) StopInterNodeCommunication() {}
func (c *ClusterMock) RegisterClusterMessageHandler(event model.ClusterEvent, crm einterfaces.ClusterMessageHandler) { func (c *ClusterMock) RegisterClusterMessageHandler(event model.ClusterEvent, crm einterfaces.ClusterMessageHandler) {
} }
func (c *ClusterMock) GetClusterId() string { return "cluster_mock" } func (c *ClusterMock) GetClusterId() string { return "cluster_mock" }
func (c *ClusterMock) IsLeader() bool { return false } func (c *ClusterMock) IsLeader() bool { return false }
func (c *ClusterMock) GetMyClusterInfo() *model.ClusterInfo { return nil } func (c *ClusterMock) GetMyClusterInfo() *model.ClusterInfo { return nil }
func (c *ClusterMock) GetClusterInfos() []*model.ClusterInfo { return nil } func (c *ClusterMock) GetClusterInfos() ([]*model.ClusterInfo, error) { return nil, nil }
func (c *ClusterMock) NotifyMsg(buf []byte) {} func (c *ClusterMock) NotifyMsg(buf []byte) {}
func (c *ClusterMock) GetClusterStats(rctx request.CTX) ([]*model.ClusterStats, *model.AppError) { func (c *ClusterMock) GetClusterStats(rctx request.CTX) ([]*model.ClusterStats, *model.AppError) {
return nil, nil return nil, nil
} }

Просмотреть файл

@@ -139,11 +139,11 @@ func (c *ClusterMock) StartInterNodeCommunication() {}
func (c *ClusterMock) StopInterNodeCommunication() {} func (c *ClusterMock) StopInterNodeCommunication() {}
func (c *ClusterMock) RegisterClusterMessageHandler(event model.ClusterEvent, crm einterfaces.ClusterMessageHandler) { func (c *ClusterMock) RegisterClusterMessageHandler(event model.ClusterEvent, crm einterfaces.ClusterMessageHandler) {
} }
func (c *ClusterMock) GetClusterId() string { return "cluster_mock" } func (c *ClusterMock) GetClusterId() string { return "cluster_mock" }
func (c *ClusterMock) IsLeader() bool { return false } func (c *ClusterMock) IsLeader() bool { return false }
func (c *ClusterMock) GetMyClusterInfo() *model.ClusterInfo { return nil } func (c *ClusterMock) GetMyClusterInfo() *model.ClusterInfo { return nil }
func (c *ClusterMock) GetClusterInfos() []*model.ClusterInfo { return nil } func (c *ClusterMock) GetClusterInfos() ([]*model.ClusterInfo, error) { return nil, nil }
func (c *ClusterMock) NotifyMsg(buf []byte) {} func (c *ClusterMock) NotifyMsg(buf []byte) {}
func (c *ClusterMock) GetClusterStats(rctx request.CTX) ([]*model.ClusterStats, *model.AppError) { func (c *ClusterMock) GetClusterStats(rctx request.CTX) ([]*model.ClusterStats, *model.AppError) {
return nil, nil return nil, nil
} }

Просмотреть файл

@@ -141,8 +141,12 @@ func (ps *PlatformService) getSupportPacketDiagnostics(rctx request.CTX) (*model
/* Cluster */ /* Cluster */
if cluster := ps.Cluster(); cluster != nil { if cluster := ps.Cluster(); cluster != nil {
d.Cluster.ID = cluster.GetClusterId() d.Cluster.ID = cluster.GetClusterId()
clusterInfo := cluster.GetClusterInfos() clusterInfo, e := cluster.GetClusterInfos()
d.Cluster.NumberOfNodes = len(clusterInfo) if e != nil {
rErr = multierror.Append(rErr, errors.Wrap(e, "error while getting cluster infos"))
} else {
d.Cluster.NumberOfNodes = len(clusterInfo)
}
} }
/* LDAP */ /* LDAP */

Просмотреть файл

@@ -14,7 +14,7 @@ import (
) )
type BatchMigrationWorkerAppIFace interface { type BatchMigrationWorkerAppIFace interface {
GetClusterStatus(rctx request.CTX) []*model.ClusterInfo GetClusterStatus(rctx request.CTX) ([]*model.ClusterInfo, error)
} }
// BatchMigrationWorker processes database migration jobs in batches to help avoid table locks. // BatchMigrationWorker processes database migration jobs in batches to help avoid table locks.
@@ -87,7 +87,11 @@ func (worker *BatchMigrationWorker) doBatch(rctx *request.Context, job *model.Jo
// checkIsClusterInSync returns true if all nodes in the cluster are running the same version, // checkIsClusterInSync returns true if all nodes in the cluster are running the same version,
// logging a warning on the first mismatch found. // logging a warning on the first mismatch found.
func (worker *BatchMigrationWorker) checkIsClusterInSync(rctx request.CTX) bool { func (worker *BatchMigrationWorker) checkIsClusterInSync(rctx request.CTX) bool {
clusterStatus := worker.app.GetClusterStatus(rctx) clusterStatus, err := worker.app.GetClusterStatus(rctx)
if err != nil {
worker.logger.Error("Worker: Failed to get cluster status", mlog.Err(err))
return false
}
for i := 1; i < len(clusterStatus); i++ { for i := 1; i < len(clusterStatus); i++ {
if clusterStatus[i].SchemaVersion != clusterStatus[0].SchemaVersion { if clusterStatus[i].SchemaVersion != clusterStatus[0].SchemaVersion {
rctx.Logger().Warn( rctx.Logger().Warn(

Просмотреть файл

@@ -20,8 +20,8 @@ type MockApp struct {
clusterInfo []*model.ClusterInfo clusterInfo []*model.ClusterInfo
} }
func (ma MockApp) GetClusterStatus(rctx request.CTX) []*model.ClusterInfo { func (ma MockApp) GetClusterStatus(rctx request.CTX) ([]*model.ClusterInfo, error) {
return ma.clusterInfo return ma.clusterInfo, nil
} }
func (ma *MockApp) SetInSync() { func (ma *MockApp) SetInSync() {

Просмотреть файл

@@ -35,7 +35,7 @@ func (c *FakeClusterInterface) IsLeader() bool { return false }
func (c *FakeClusterInterface) GetMyClusterInfo() *model.ClusterInfo { return nil } func (c *FakeClusterInterface) GetMyClusterInfo() *model.ClusterInfo { return nil }
func (c *FakeClusterInterface) GetClusterInfos() []*model.ClusterInfo { return nil } func (c *FakeClusterInterface) GetClusterInfos() ([]*model.ClusterInfo, error) { return nil, nil }
func (c *FakeClusterInterface) SendClusterMessage(message *model.ClusterMessage) { func (c *FakeClusterInterface) SendClusterMessage(message *model.ClusterMessage) {
c.mut.Lock() c.mut.Lock()

Просмотреть файл

@@ -21,7 +21,7 @@ type ClusterInterface interface {
// and zero means "totally healthy". // and zero means "totally healthy".
HealthScore() int HealthScore() int
GetMyClusterInfo() *model.ClusterInfo GetMyClusterInfo() *model.ClusterInfo
GetClusterInfos() []*model.ClusterInfo GetClusterInfos() ([]*model.ClusterInfo, error)
SendClusterMessage(msg *model.ClusterMessage) SendClusterMessage(msg *model.ClusterMessage)
SendClusterMessageToNode(nodeID string, msg *model.ClusterMessage) error SendClusterMessageToNode(nodeID string, msg *model.ClusterMessage) error
NotifyMsg(buf []byte) NotifyMsg(buf []byte)

Просмотреть файл

@@ -87,7 +87,7 @@ func (_m *ClusterInterface) GetClusterId() string {
} }
// GetClusterInfos provides a mock function with given fields: // GetClusterInfos provides a mock function with given fields:
func (_m *ClusterInterface) GetClusterInfos() []*model.ClusterInfo { func (_m *ClusterInterface) GetClusterInfos() ([]*model.ClusterInfo, error) {
ret := _m.Called() ret := _m.Called()
if len(ret) == 0 { if len(ret) == 0 {
@@ -95,6 +95,10 @@ func (_m *ClusterInterface) GetClusterInfos() []*model.ClusterInfo {
} }
var r0 []*model.ClusterInfo var r0 []*model.ClusterInfo
var r1 error
if rf, ok := ret.Get(0).(func() ([]*model.ClusterInfo, error)); ok {
return rf()
}
if rf, ok := ret.Get(0).(func() []*model.ClusterInfo); ok { if rf, ok := ret.Get(0).(func() []*model.ClusterInfo); ok {
r0 = rf() r0 = rf()
} else { } else {
@@ -103,7 +107,13 @@ func (_m *ClusterInterface) GetClusterInfos() []*model.ClusterInfo {
} }
} }
return r0 if rf, ok := ret.Get(1).(func() error); ok {
r1 = rf()
} else {
r1 = ret.Error(1)
}
return r0, r1
} }
// GetClusterStats provides a mock function with given fields: rctx // GetClusterStats provides a mock function with given fields: rctx