diff --git a/api4/system.go b/api4/system.go index da1edfd8ba..41b63ccb3c 100644 --- a/api4/system.go +++ b/api4/system.go @@ -97,21 +97,14 @@ func getSystemPing(c *Context, w http.ResponseWriter, r *http.Request) { dbStatusKey := "database_status" s[dbStatusKey] = model.STATUS_OK - // Database Write Check - currentTime := fmt.Sprintf("%d", time.Now().Unix()) - healthCheckKey := fmt.Sprintf("health_check_%s", c.App.GetClusterId()) - - writeErr := c.App.Srv().Store.System().SaveOrUpdate(&model.System{ - Name: healthCheckKey, - Value: currentTime, - }) + writeErr := c.App.DBHealthCheckWrite() if writeErr != nil { mlog.Warn("Unable to write to database.", mlog.Err(writeErr)) s[dbStatusKey] = model.STATUS_UNHEALTHY s[model.STATUS] = model.STATUS_UNHEALTHY } - _, writeErr = c.App.Srv().Store.System().PermanentDeleteByName(healthCheckKey) + writeErr = c.App.DBHealthCheckDelete() if writeErr != nil { mlog.Warn("Unable to remove ping health check value from database.", mlog.Err(writeErr)) s[dbStatusKey] = model.STATUS_UNHEALTHY diff --git a/app/app.go b/app/app.go index dc94fd14fc..6f34ff4f42 100644 --- a/app/app.go +++ b/app/app.go @@ -10,6 +10,7 @@ import ( "net/http" "strconv" "strings" + "time" "github.com/mattermost/go-i18n/i18n" goi18n "github.com/mattermost/go-i18n/i18n" @@ -677,3 +678,21 @@ func (a *App) SetServer(srv *Server) { func (a *App) GetT() goi18n.TranslateFunc { return a.t } + +func (a *App) DBHealthCheckWrite() error { + currentTime := strconv.FormatInt(time.Now().Unix(), 10) + + return a.Srv().Store.System().SaveOrUpdate(&model.System{ + Name: a.dbHealthCheckKey(), + Value: currentTime, + }) +} + +func (a *App) DBHealthCheckDelete() error { + _, err := a.Srv().Store.System().PermanentDeleteByName(a.dbHealthCheckKey()) + return err +} + +func (a *App) dbHealthCheckKey() string { + return fmt.Sprintf("health_check_%s", a.GetClusterId()) +} diff --git a/app/app_iface.go b/app/app_iface.go index c2d0f96370..37edc24aac 100644 --- a/app/app_iface.go +++ b/app/app_iface.go @@ -436,6 +436,8 @@ type AppIface interface { CreateUserWithInviteId(user *model.User, inviteId, redirect string) (*model.User, *model.AppError) CreateUserWithToken(user *model.User, token *model.Token) (*model.User, *model.AppError) CreateWebhookPost(userId string, channel *model.Channel, text, overrideUsername, overrideIconUrl, overrideIconEmoji string, props model.StringInterface, postType string, postRootId string) (*model.Post, *model.AppError) + DBHealthCheckDelete() error + DBHealthCheckWrite() error DataRetention() einterfaces.DataRetentionInterface DeactivateGuests() *model.AppError DeactivateMfa(userId string) *model.AppError diff --git a/app/app_test.go b/app/app_test.go index 1b7b61c31a..8194fcd972 100644 --- a/app/app_test.go +++ b/app/app_test.go @@ -473,3 +473,27 @@ func TestDoEmojisPermissionsMigration(t *testing.T) { sort.Strings(systemAdmin2.Permissions) assert.Equal(t, expectedSystemAdmin, systemAdmin2.Permissions, fmt.Sprintf("'%v' did not have expected permissions", model.SYSTEM_ADMIN_ROLE_ID)) } + +func TestDBHealthCheckWriteAndDelete(t *testing.T) { + th := Setup(t) + defer th.TearDown() + + expectedKey := "health_check_" + th.App.GetClusterId() + assert.Equal(t, expectedKey, th.App.dbHealthCheckKey()) + + _, err := th.App.Srv().Store.System().GetByName(expectedKey) + assert.NotNil(t, err) + + err = th.App.DBHealthCheckWrite() + assert.Nil(t, err) + + systemVal, err := th.App.Srv().Store.System().GetByName(expectedKey) + assert.Nil(t, err) + assert.NotNil(t, systemVal) + + err = th.App.DBHealthCheckDelete() + assert.Nil(t, err) + + _, err = th.App.Srv().Store.System().GetByName(expectedKey) + assert.NotNil(t, err) +} diff --git a/app/opentracing/opentracing_layer.go b/app/opentracing/opentracing_layer.go index 6f7a2a199b..71b62e584d 100644 --- a/app/opentracing/opentracing_layer.go +++ b/app/opentracing/opentracing_layer.go @@ -2350,6 +2350,50 @@ func (a *OpenTracingAppLayer) CreateWebhookPost(userId string, channel *model.Ch return resultVar0, resultVar1 } +func (a *OpenTracingAppLayer) DBHealthCheckDelete() error { + origCtx := a.ctx + span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.DBHealthCheckDelete") + + a.ctx = newCtx + a.app.Srv().Store.SetContext(newCtx) + defer func() { + a.app.Srv().Store.SetContext(origCtx) + a.ctx = origCtx + }() + + defer span.Finish() + resultVar0 := a.app.DBHealthCheckDelete() + + if resultVar0 != nil { + span.LogFields(spanlog.Error(resultVar0)) + ext.Error.Set(span, true) + } + + return resultVar0 +} + +func (a *OpenTracingAppLayer) DBHealthCheckWrite() error { + origCtx := a.ctx + span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.DBHealthCheckWrite") + + a.ctx = newCtx + a.app.Srv().Store.SetContext(newCtx) + defer func() { + a.app.Srv().Store.SetContext(origCtx) + a.ctx = origCtx + }() + + defer span.Finish() + resultVar0 := a.app.DBHealthCheckWrite() + + if resultVar0 != nil { + span.LogFields(spanlog.Error(resultVar0)) + ext.Error.Set(span, true) + } + + return resultVar0 +} + func (a *OpenTracingAppLayer) DeactivateGuests() *model.AppError { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.DeactivateGuests")