Skip to content

Commit

Permalink
Add cache test for admins (#31265)
Browse files Browse the repository at this point in the history
Add a test to probe the cache similar to the email test func.


![image](https://github.com/go-gitea/gitea/assets/24977596/700e2733-586d-4091-900f-f5f71e6e94bf)


![image](https://github.com/go-gitea/gitea/assets/24977596/2a953802-18fc-4e81-a37d-24ebe1297365)


![image](https://github.com/go-gitea/gitea/assets/24977596/e00d62ad-bb60-41cc-9138-09993daee156)

---------

Co-authored-by: delvh <dev.lh@web.de>
Co-authored-by: silverwind <me@silverwind.io>
  • Loading branch information
3 people committed Jun 17, 2024
1 parent 4b6eb46 commit 363c123
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 27 deletions.
32 changes: 32 additions & 0 deletions modules/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package cache

import (
"fmt"
"strconv"
"time"

Expand Down Expand Up @@ -35,6 +36,37 @@ func Init() error {
return nil
}

const (
testCacheKey = "DefaultCache.TestKey"
SlowCacheThreshold = 100 * time.Microsecond
)

func Test() (time.Duration, error) {
if defaultCache == nil {
return 0, fmt.Errorf("default cache not initialized")
}

testData := fmt.Sprintf("%x", make([]byte, 500))

start := time.Now()

if err := defaultCache.Delete(testCacheKey); err != nil {
return 0, fmt.Errorf("expect cache to delete data based on key if exist but got: %w", err)
}
if err := defaultCache.Put(testCacheKey, testData, 10); err != nil {
return 0, fmt.Errorf("expect cache to store data but got: %w", err)
}
testVal, hit := defaultCache.Get(testCacheKey)
if !hit {
return 0, fmt.Errorf("expect cache hit but got none")
}
if testVal != testData {
return 0, fmt.Errorf("expect cache to return same value as stored but got other")
}

return time.Since(start), nil
}

// GetCache returns the currently configured cache
func GetCache() StringCache {
return defaultCache
Expand Down
12 changes: 12 additions & 0 deletions modules/cache/cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ func TestNewContext(t *testing.T) {
assert.Nil(t, con)
}

func TestTest(t *testing.T) {
defaultCache = nil
_, err := Test()
assert.Error(t, err)

createTestCache()
elapsed, err := Test()
assert.NoError(t, err)
// mem cache should take from 300ns up to 1ms on modern hardware ...
assert.Less(t, elapsed, SlowCacheThreshold)
}

func TestGetCache(t *testing.T) {
createTestCache()

Expand Down
5 changes: 5 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ remove_all = Remove All
remove_label_str = Remove item "%s"
edit = Edit
view = View
test = Test

enabled = Enabled
disabled = Disabled
Expand Down Expand Up @@ -3225,6 +3226,10 @@ config.cache_adapter = Cache Adapter
config.cache_interval = Cache Interval
config.cache_conn = Cache Connection
config.cache_item_ttl = Cache Item TTL
config.cache_test = Test Cache
config.cache_test_failed = Failed to probe the cache: %v.
config.cache_test_slow = Cache test successful, but response is slow: %s.
config.cache_test_succeeded = Cache test successful, got a response in %s.

config.session_config = Session Configuration
config.session_provider = Session Provider
Expand Down
9 changes: 9 additions & 0 deletions routers/web/admin/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/httplib"
"code.gitea.io/gitea/modules/json"
Expand Down Expand Up @@ -222,6 +223,14 @@ func SelfCheck(ctx *context.Context) {

ctx.Data["DatabaseCheckHasProblems"] = hasProblem
}

elapsed, err := cache.Test()
if err != nil {
ctx.Data["CacheError"] = err
} else if elapsed > cache.SlowCacheThreshold {
ctx.Data["CacheSlow"] = fmt.Sprint(elapsed)
}

ctx.HTML(http.StatusOK, tplSelfCheck)
}

Expand Down
17 changes: 17 additions & 0 deletions routers/web/admin/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

system_model "code.gitea.io/gitea/models/system"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/cache"
"code.gitea.io/gitea/modules/git"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/log"
Expand Down Expand Up @@ -42,6 +43,22 @@ func SendTestMail(ctx *context.Context) {
ctx.Redirect(setting.AppSubURL + "/admin/config")
}

// TestCache test the cache settings
func TestCache(ctx *context.Context) {
elapsed, err := cache.Test()
if err != nil {
ctx.Flash.Error(ctx.Tr("admin.config.cache_test_failed", err))
} else {
if elapsed > cache.SlowCacheThreshold {
ctx.Flash.Warning(ctx.Tr("admin.config.cache_test_slow", elapsed))
} else {
ctx.Flash.Info(ctx.Tr("admin.config.cache_test_succeeded", elapsed))
}
}

ctx.Redirect(setting.AppSubURL + "/admin/config")
}

func shadowPasswordKV(cfgItem, splitter string) string {
fields := strings.Split(cfgItem, splitter)
for i := 0; i < len(fields); i++ {
Expand Down
1 change: 1 addition & 0 deletions routers/web/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -692,6 +692,7 @@ func registerRoutes(m *web.Route) {
m.Get("", admin.Config)
m.Post("", admin.ChangeConfig)
m.Post("/test_mail", admin.SendTestMail)
m.Post("/test_cache", admin.TestCache)
m.Get("/settings", admin.ConfigSettings)
})

Expand Down
12 changes: 10 additions & 2 deletions templates/admin/config.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -229,8 +229,8 @@
<dt>{{ctx.Locale.Tr "admin.config.mailer_user"}}</dt>
<dd>{{if .Mailer.User}}{{.Mailer.User}}{{else}}(empty){{end}}</dd>
<div class="divider"></div>
<dt class="tw-py-1">{{ctx.Locale.Tr "admin.config.send_test_mail"}}</dt>
<dd>
<dt class="tw-py-1 tw-flex tw-items-center">{{ctx.Locale.Tr "admin.config.send_test_mail"}}</dt>
<dd class="tw-py-0">
<form class="ui form ignore-dirty" action="{{AppSubUrl}}/admin/config/test_mail" method="post">
{{.CsrfTokenHtml}}
<div class="ui tiny input">
Expand Down Expand Up @@ -260,6 +260,14 @@
<dt>{{ctx.Locale.Tr "admin.config.cache_item_ttl"}}</dt>
<dd><code>{{.CacheItemTTL}}</code></dd>
{{end}}
<div class="divider"></div>
<dt class="tw-py-1 tw-flex tw-items-center">{{ctx.Locale.Tr "admin.config.cache_test"}}</dt>
<dd class="tw-py-0">
<form class="ui form ignore-dirty" action="{{AppSubUrl}}/admin/config/test_cache" method="post">
{{.CsrfTokenHtml}}
<button class="ui tiny primary button">{{ctx.Locale.Tr "test"}}</button>
</form>
</dd>
</dl>
</div>

Expand Down
58 changes: 33 additions & 25 deletions templates/admin/self_check.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,40 @@
<div class="ui attached segment tw-hidden self-check-problem" id="self-check-by-frontend"></div>

{{if .DatabaseCheckHasProblems}}
<div class="ui attached segment self-check-problem">
{{if .DatabaseType.IsMySQL}}
<div class="tw-p-2">{{ctx.Locale.Tr "admin.self_check.database_fix_mysql"}}</div>
{{else if .DatabaseType.IsMSSQL}}
<div class="tw-p-2">{{ctx.Locale.Tr "admin.self_check.database_fix_mssql"}}</div>
{{end}}
{{if .DatabaseCheckCollationMismatch}}
<div class="ui red message">{{ctx.Locale.Tr "admin.self_check.database_collation_mismatch" .DatabaseCheckResult.ExpectedCollation}}</div>
{{end}}
{{if .DatabaseCheckCollationCaseInsensitive}}
<div class="ui warning message">{{ctx.Locale.Tr "admin.self_check.database_collation_case_insensitive" .DatabaseCheckResult.DatabaseCollation}}</div>
{{end}}
{{if .DatabaseCheckInconsistentCollationColumns}}
<div class="ui red message">
<details>
<summary>{{ctx.Locale.Tr "admin.self_check.database_inconsistent_collation_columns" .DatabaseCheckResult.DatabaseCollation}}</summary>
<ul class="tw-w-full">
{{range .DatabaseCheckInconsistentCollationColumns}}
<li>{{.}}</li>
{{end}}
</ul>
</details>
</div>
{{end}}
</div>
<div class="ui attached segment self-check-problem">
{{if .DatabaseType.IsMySQL}}
<div class="tw-p-2">{{ctx.Locale.Tr "admin.self_check.database_fix_mysql"}}</div>
{{else if .DatabaseType.IsMSSQL}}
<div class="tw-p-2">{{ctx.Locale.Tr "admin.self_check.database_fix_mssql"}}</div>
{{end}}
{{if .DatabaseCheckCollationMismatch}}
<div class="ui red message">{{ctx.Locale.Tr "admin.self_check.database_collation_mismatch" .DatabaseCheckResult.ExpectedCollation}}</div>
{{end}}
{{if .DatabaseCheckCollationCaseInsensitive}}
<div class="ui warning message">{{ctx.Locale.Tr "admin.self_check.database_collation_case_insensitive" .DatabaseCheckResult.DatabaseCollation}}</div>
{{end}}
{{if .DatabaseCheckInconsistentCollationColumns}}
<div class="ui red message">
<details>
<summary>{{ctx.Locale.Tr "admin.self_check.database_inconsistent_collation_columns" .DatabaseCheckResult.DatabaseCollation}}</summary>
<ul class="tw-w-full">
{{range .DatabaseCheckInconsistentCollationColumns}}
<li>{{.}}</li>
{{end}}
</ul>
</details>
</div>
{{end}}
</div>
{{end}}

{{if .CacheError}}
<div class="ui red message">{{ctx.Locale.Tr "admin.config.cache_test_failed" .CacheError}}</div>
{{end}}
{{if .CacheSlow}}
<div class="ui warning message">{{ctx.Locale.Tr "admin.config.cache_test_slow" .CacheSlow}}</div>
{{end}}

{{/* only shown when there is no visible "self-check-problem" */}}
<div class="ui attached segment tw-hidden self-check-no-problem">
{{ctx.Locale.Tr "admin.self_check.no_problem_found"}}
Expand Down

0 comments on commit 363c123

Please sign in to comment.