mirror of https://github.com/go-gitea/gitea.git
Add cache test for admins (#31265)
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>
This commit is contained in:
parent
4b6eb46e69
commit
363c123598
|
@ -4,6 +4,7 @@
|
||||||
package cache
|
package cache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -35,6 +36,37 @@ func Init() error {
|
||||||
return nil
|
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
|
// GetCache returns the currently configured cache
|
||||||
func GetCache() StringCache {
|
func GetCache() StringCache {
|
||||||
return defaultCache
|
return defaultCache
|
||||||
|
|
|
@ -34,6 +34,18 @@ func TestNewContext(t *testing.T) {
|
||||||
assert.Nil(t, con)
|
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) {
|
func TestGetCache(t *testing.T) {
|
||||||
createTestCache()
|
createTestCache()
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,7 @@ remove_all = Remove All
|
||||||
remove_label_str = Remove item "%s"
|
remove_label_str = Remove item "%s"
|
||||||
edit = Edit
|
edit = Edit
|
||||||
view = View
|
view = View
|
||||||
|
test = Test
|
||||||
|
|
||||||
enabled = Enabled
|
enabled = Enabled
|
||||||
disabled = Disabled
|
disabled = Disabled
|
||||||
|
@ -3225,6 +3226,10 @@ config.cache_adapter = Cache Adapter
|
||||||
config.cache_interval = Cache Interval
|
config.cache_interval = Cache Interval
|
||||||
config.cache_conn = Cache Connection
|
config.cache_conn = Cache Connection
|
||||||
config.cache_item_ttl = Cache Item TTL
|
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_config = Session Configuration
|
||||||
config.session_provider = Session Provider
|
config.session_provider = Session Provider
|
||||||
|
|
|
@ -15,6 +15,7 @@ import (
|
||||||
activities_model "code.gitea.io/gitea/models/activities"
|
activities_model "code.gitea.io/gitea/models/activities"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
|
"code.gitea.io/gitea/modules/cache"
|
||||||
"code.gitea.io/gitea/modules/graceful"
|
"code.gitea.io/gitea/modules/graceful"
|
||||||
"code.gitea.io/gitea/modules/httplib"
|
"code.gitea.io/gitea/modules/httplib"
|
||||||
"code.gitea.io/gitea/modules/json"
|
"code.gitea.io/gitea/modules/json"
|
||||||
|
@ -222,6 +223,14 @@ func SelfCheck(ctx *context.Context) {
|
||||||
|
|
||||||
ctx.Data["DatabaseCheckHasProblems"] = hasProblem
|
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)
|
ctx.HTML(http.StatusOK, tplSelfCheck)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
|
|
||||||
system_model "code.gitea.io/gitea/models/system"
|
system_model "code.gitea.io/gitea/models/system"
|
||||||
"code.gitea.io/gitea/modules/base"
|
"code.gitea.io/gitea/modules/base"
|
||||||
|
"code.gitea.io/gitea/modules/cache"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/json"
|
"code.gitea.io/gitea/modules/json"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
@ -42,6 +43,22 @@ func SendTestMail(ctx *context.Context) {
|
||||||
ctx.Redirect(setting.AppSubURL + "/admin/config")
|
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 {
|
func shadowPasswordKV(cfgItem, splitter string) string {
|
||||||
fields := strings.Split(cfgItem, splitter)
|
fields := strings.Split(cfgItem, splitter)
|
||||||
for i := 0; i < len(fields); i++ {
|
for i := 0; i < len(fields); i++ {
|
||||||
|
|
|
@ -692,6 +692,7 @@ func registerRoutes(m *web.Route) {
|
||||||
m.Get("", admin.Config)
|
m.Get("", admin.Config)
|
||||||
m.Post("", admin.ChangeConfig)
|
m.Post("", admin.ChangeConfig)
|
||||||
m.Post("/test_mail", admin.SendTestMail)
|
m.Post("/test_mail", admin.SendTestMail)
|
||||||
|
m.Post("/test_cache", admin.TestCache)
|
||||||
m.Get("/settings", admin.ConfigSettings)
|
m.Get("/settings", admin.ConfigSettings)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -229,8 +229,8 @@
|
||||||
<dt>{{ctx.Locale.Tr "admin.config.mailer_user"}}</dt>
|
<dt>{{ctx.Locale.Tr "admin.config.mailer_user"}}</dt>
|
||||||
<dd>{{if .Mailer.User}}{{.Mailer.User}}{{else}}(empty){{end}}</dd>
|
<dd>{{if .Mailer.User}}{{.Mailer.User}}{{else}}(empty){{end}}</dd>
|
||||||
<div class="divider"></div>
|
<div class="divider"></div>
|
||||||
<dt class="tw-py-1">{{ctx.Locale.Tr "admin.config.send_test_mail"}}</dt>
|
<dt class="tw-py-1 tw-flex tw-items-center">{{ctx.Locale.Tr "admin.config.send_test_mail"}}</dt>
|
||||||
<dd>
|
<dd class="tw-py-0">
|
||||||
<form class="ui form ignore-dirty" action="{{AppSubUrl}}/admin/config/test_mail" method="post">
|
<form class="ui form ignore-dirty" action="{{AppSubUrl}}/admin/config/test_mail" method="post">
|
||||||
{{.CsrfTokenHtml}}
|
{{.CsrfTokenHtml}}
|
||||||
<div class="ui tiny input">
|
<div class="ui tiny input">
|
||||||
|
@ -260,6 +260,14 @@
|
||||||
<dt>{{ctx.Locale.Tr "admin.config.cache_item_ttl"}}</dt>
|
<dt>{{ctx.Locale.Tr "admin.config.cache_item_ttl"}}</dt>
|
||||||
<dd><code>{{.CacheItemTTL}}</code></dd>
|
<dd><code>{{.CacheItemTTL}}</code></dd>
|
||||||
{{end}}
|
{{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>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -17,32 +17,40 @@
|
||||||
<div class="ui attached segment tw-hidden self-check-problem" id="self-check-by-frontend"></div>
|
<div class="ui attached segment tw-hidden self-check-problem" id="self-check-by-frontend"></div>
|
||||||
|
|
||||||
{{if .DatabaseCheckHasProblems}}
|
{{if .DatabaseCheckHasProblems}}
|
||||||
<div class="ui attached segment self-check-problem">
|
<div class="ui attached segment self-check-problem">
|
||||||
{{if .DatabaseType.IsMySQL}}
|
{{if .DatabaseType.IsMySQL}}
|
||||||
<div class="tw-p-2">{{ctx.Locale.Tr "admin.self_check.database_fix_mysql"}}</div>
|
<div class="tw-p-2">{{ctx.Locale.Tr "admin.self_check.database_fix_mysql"}}</div>
|
||||||
{{else if .DatabaseType.IsMSSQL}}
|
{{else if .DatabaseType.IsMSSQL}}
|
||||||
<div class="tw-p-2">{{ctx.Locale.Tr "admin.self_check.database_fix_mssql"}}</div>
|
<div class="tw-p-2">{{ctx.Locale.Tr "admin.self_check.database_fix_mssql"}}</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .DatabaseCheckCollationMismatch}}
|
{{if .DatabaseCheckCollationMismatch}}
|
||||||
<div class="ui red message">{{ctx.Locale.Tr "admin.self_check.database_collation_mismatch" .DatabaseCheckResult.ExpectedCollation}}</div>
|
<div class="ui red message">{{ctx.Locale.Tr "admin.self_check.database_collation_mismatch" .DatabaseCheckResult.ExpectedCollation}}</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .DatabaseCheckCollationCaseInsensitive}}
|
{{if .DatabaseCheckCollationCaseInsensitive}}
|
||||||
<div class="ui warning message">{{ctx.Locale.Tr "admin.self_check.database_collation_case_insensitive" .DatabaseCheckResult.DatabaseCollation}}</div>
|
<div class="ui warning message">{{ctx.Locale.Tr "admin.self_check.database_collation_case_insensitive" .DatabaseCheckResult.DatabaseCollation}}</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{if .DatabaseCheckInconsistentCollationColumns}}
|
{{if .DatabaseCheckInconsistentCollationColumns}}
|
||||||
<div class="ui red message">
|
<div class="ui red message">
|
||||||
<details>
|
<details>
|
||||||
<summary>{{ctx.Locale.Tr "admin.self_check.database_inconsistent_collation_columns" .DatabaseCheckResult.DatabaseCollation}}</summary>
|
<summary>{{ctx.Locale.Tr "admin.self_check.database_inconsistent_collation_columns" .DatabaseCheckResult.DatabaseCollation}}</summary>
|
||||||
<ul class="tw-w-full">
|
<ul class="tw-w-full">
|
||||||
{{range .DatabaseCheckInconsistentCollationColumns}}
|
{{range .DatabaseCheckInconsistentCollationColumns}}
|
||||||
<li>{{.}}</li>
|
<li>{{.}}</li>
|
||||||
{{end}}
|
{{end}}
|
||||||
</ul>
|
</ul>
|
||||||
</details>
|
</details>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{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" */}}
|
{{/* only shown when there is no visible "self-check-problem" */}}
|
||||||
<div class="ui attached segment tw-hidden self-check-no-problem">
|
<div class="ui attached segment tw-hidden self-check-no-problem">
|
||||||
{{ctx.Locale.Tr "admin.self_check.no_problem_found"}}
|
{{ctx.Locale.Tr "admin.self_check.no_problem_found"}}
|
||||||
|
|
Loading…
Reference in New Issue