From 239711cea7b2fd7e15b5edec972009a857192765 Mon Sep 17 00:00:00 2001 From: ryan Date: Mon, 15 Jun 2026 16:45:26 +0800 Subject: [PATCH] refactor(service): adopt feature-based architecture and rename pkg/diskcache - Moved GORM/Redis CAPTCHA manager from internal/service/cap directly into the cohesive CAPTCHA app folder at internal/apps/cap/. - Moved background system cleanup handler from internal/service/cleanup.go into internal/apps/upload/cleanup.go. - Completely removed the global internal/service directory to keep module logic self-contained. - Renamed the core utility engine pkg/diskcache to pkg/cache/disk to separate underlying utility code from db/config integrations. - Renamed DiskCache struct in pkg/cache/disk to Cache to resolve revive package-name stuttering warning. - Regenerated Swagger API documentation and confirmed all tests compile and pass with 0 linter issues. --- docs/docs.go | 14 ++++---- docs/swagger.json | 14 ++++---- docs/swagger.yaml | 14 ++++---- internal/apps/admin/task/routers_test.go | 7 ++-- internal/{service => apps}/cap/manager.go | 0 .../{service => apps}/cap/manager_test.go | 0 internal/apps/cap/middleware.go | 9 ++--- internal/apps/cap/routers.go | 21 ++++++----- internal/apps/cap/routers_test.go | 7 ++-- internal/{service => apps/upload}/cleanup.go | 4 +-- internal/apps/upload/tasks_test.go | 7 ++-- internal/diskcache/cache.go | 4 +-- internal/router/router.go | 7 ++-- internal/service/.gitkeep | 0 internal/task/handlers/register.go | 5 ++- pkg/{diskcache => cache/disk}/cache.go | 36 +++++++++---------- pkg/{diskcache => cache/disk}/cache_test.go | 2 +- 17 files changed, 73 insertions(+), 78 deletions(-) rename internal/{service => apps}/cap/manager.go (100%) rename internal/{service => apps}/cap/manager_test.go (100%) rename internal/{service => apps/upload}/cleanup.go (98%) delete mode 100644 internal/service/.gitkeep rename pkg/{diskcache => cache/disk}/cache.go (89%) rename pkg/{diskcache => cache/disk}/cache_test.go (99%) diff --git a/docs/docs.go b/docs/docs.go index bcd47595..465f9c53 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -55,7 +55,7 @@ const docTemplate = `{ "500": { "description": "内部服务错误", "schema": { - "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_service_cap.RedeemResponse" + "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse" } } } @@ -89,19 +89,19 @@ const docTemplate = `{ "200": { "description": "核销成功,返回 X-Cap-Token", "schema": { - "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_service_cap.RedeemResponse" + "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse" } }, "400": { "description": "参数错误或核销失败", "schema": { - "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_service_cap.RedeemResponse" + "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse" } }, "500": { "description": "内部服务错误", "schema": { - "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_service_cap.RedeemResponse" + "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse" } } } @@ -620,7 +620,7 @@ const docTemplate = `{ "type": "object", "properties": { "data": { - "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_diskcache.Status" + "$ref": "#/definitions/diskcache.Status" } } } @@ -5648,7 +5648,7 @@ const docTemplate = `{ } } }, - "github_com_Rain-kl_Wavelet_internal_diskcache.Status": { + "diskcache.Status": { "type": "object", "properties": { "base_path": { @@ -5671,7 +5671,7 @@ const docTemplate = `{ } } }, - "github_com_Rain-kl_Wavelet_internal_service_cap.RedeemResponse": { + "github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse": { "type": "object", "properties": { "error": { diff --git a/docs/swagger.json b/docs/swagger.json index 03f4a46d..b8c4f605 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -48,7 +48,7 @@ "500": { "description": "内部服务错误", "schema": { - "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_service_cap.RedeemResponse" + "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse" } } } @@ -82,19 +82,19 @@ "200": { "description": "核销成功,返回 X-Cap-Token", "schema": { - "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_service_cap.RedeemResponse" + "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse" } }, "400": { "description": "参数错误或核销失败", "schema": { - "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_service_cap.RedeemResponse" + "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse" } }, "500": { "description": "内部服务错误", "schema": { - "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_service_cap.RedeemResponse" + "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse" } } } @@ -613,7 +613,7 @@ "type": "object", "properties": { "data": { - "$ref": "#/definitions/github_com_Rain-kl_Wavelet_internal_diskcache.Status" + "$ref": "#/definitions/diskcache.Status" } } } @@ -5641,7 +5641,7 @@ } } }, - "github_com_Rain-kl_Wavelet_internal_diskcache.Status": { + "diskcache.Status": { "type": "object", "properties": { "base_path": { @@ -5664,7 +5664,7 @@ } } }, - "github_com_Rain-kl_Wavelet_internal_service_cap.RedeemResponse": { + "github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse": { "type": "object", "properties": { "error": { diff --git a/docs/swagger.yaml b/docs/swagger.yaml index 97678072..a589f999 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -117,7 +117,7 @@ definitions: description: '"select" 或 "exec"' type: string type: object - github_com_Rain-kl_Wavelet_internal_diskcache.Status: + diskcache.Status: properties: base_path: type: string @@ -132,7 +132,7 @@ definitions: ttl_minutes: type: integer type: object - github_com_Rain-kl_Wavelet_internal_service_cap.RedeemResponse: + github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse: properties: error: type: string @@ -1431,7 +1431,7 @@ paths: "500": description: 内部服务错误 schema: - $ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_service_cap.RedeemResponse' + $ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse' summary: 生成人机验证难题 tags: - cap @@ -1453,15 +1453,15 @@ paths: "200": description: 核销成功,返回 X-Cap-Token schema: - $ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_service_cap.RedeemResponse' + $ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse' "400": description: 参数错误或核销失败 schema: - $ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_service_cap.RedeemResponse' + $ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse' "500": description: 内部服务错误 schema: - $ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_service_cap.RedeemResponse' + $ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_apps_cap.RedeemResponse' summary: 校验人机验证解答 tags: - cap @@ -1773,7 +1773,7 @@ paths: - $ref: '#/definitions/response.Any' - properties: data: - $ref: '#/definitions/github_com_Rain-kl_Wavelet_internal_diskcache.Status' + $ref: '#/definitions/diskcache.Status' type: object "401": description: 未登录 diff --git a/internal/apps/admin/task/routers_test.go b/internal/apps/admin/task/routers_test.go index a3f8a268..9260e68c 100644 --- a/internal/apps/admin/task/routers_test.go +++ b/internal/apps/admin/task/routers_test.go @@ -17,7 +17,6 @@ import ("bytes" "github.com/Rain-kl/Wavelet/internal/apps/upload" "github.com/Rain-kl/Wavelet/internal/apps/user" "github.com/Rain-kl/Wavelet/internal/model" - "github.com/Rain-kl/Wavelet/internal/service" "github.com/Rain-kl/Wavelet/internal/task" "github.com/Rain-kl/Wavelet/internal/testhelper" "github.com/Rain-kl/Wavelet/internal/util" @@ -92,7 +91,7 @@ func TestListTaskTypes(t *testing.T) { foundCleanup := false foundWarmImageCache := false for _, m := range taskMetas { - if m.Type == service.TaskTypeSystemCleanup { + if m.Type == upload.TaskTypeSystemCleanup { foundCleanup = true } if m.Type == upload.TaskTypeWarmImageCache { @@ -100,7 +99,7 @@ func TestListTaskTypes(t *testing.T) { } } if !foundCleanup { - t.Errorf("expected task type %s to be listed", service.TaskTypeSystemCleanup) + t.Errorf("expected task type %s to be listed", upload.TaskTypeSystemCleanup) } if !foundWarmImageCache { t.Errorf("expected task type %s to be listed", upload.TaskTypeWarmImageCache) @@ -116,7 +115,7 @@ func TestDispatchTask(t *testing.T) { t.Run("dispatch valid task successfully", func(t *testing.T) { payload := DispatchTaskRequest{ - TaskType: service.TaskTypeSystemCleanup, + TaskType: upload.TaskTypeSystemCleanup, } body, _ := json.Marshal(payload) req, _ := http.NewRequest("POST", "/api/v1/admin/tasks/dispatch", bytes.NewBuffer(body)) diff --git a/internal/service/cap/manager.go b/internal/apps/cap/manager.go similarity index 100% rename from internal/service/cap/manager.go rename to internal/apps/cap/manager.go diff --git a/internal/service/cap/manager_test.go b/internal/apps/cap/manager_test.go similarity index 100% rename from internal/service/cap/manager_test.go rename to internal/apps/cap/manager_test.go diff --git a/internal/apps/cap/middleware.go b/internal/apps/cap/middleware.go index b3893b65..6260b67c 100644 --- a/internal/apps/cap/middleware.go +++ b/internal/apps/cap/middleware.go @@ -3,16 +3,17 @@ package cap -import ("net/http" +import ( + "net/http" - caputil "github.com/Rain-kl/Wavelet/internal/service/cap" "github.com/gin-gonic/gin" - "github.com/Rain-kl/Wavelet/internal/common/response") + "github.com/Rain-kl/Wavelet/internal/common/response" +) // VerifyMiddleware returns a Gin middleware that checks and consumes the X-Cap-Token header. // enabledFunc is an optional callback allowing dynamic check of whether captcha protection is turned on. -func VerifyMiddleware(mgr *caputil.Manager, scope string, enabledFunc func() bool) gin.HandlerFunc { +func VerifyMiddleware(mgr *Manager, scope string, enabledFunc func() bool) gin.HandlerFunc { return func(c *gin.Context) { if enabledFunc != nil && !enabledFunc() { c.Next() diff --git a/internal/apps/cap/routers.go b/internal/apps/cap/routers.go index fddc8511..1cc2eef9 100644 --- a/internal/apps/cap/routers.go +++ b/internal/apps/cap/routers.go @@ -6,8 +6,7 @@ package cap import ( "net/http" - capService "github.com/Rain-kl/Wavelet/internal/service/cap" - "github.com/gin-gonic/gin" + "github.com/gin-gonic/gin" ) type challengeRequest struct { @@ -28,7 +27,7 @@ type redeemRequest struct { // @Produce json // @Param request body challengeRequest false "可选范围限制参数" // @Success 200 {object} cap.ChallengeResponse "成功返回 PoW 难题" -// @Failure 500 {object} capService.RedeemResponse "内部服务错误" +// @Failure 500 {object} RedeemResponse "内部服务错误" // @Router /api/cap/challenge [post] func Challenge(c *gin.Context) { var req challengeRequest @@ -38,10 +37,10 @@ func Challenge(c *gin.Context) { req.Scope = "login" } - mgr := capService.GetDefaultManager() + mgr := GetDefaultManager() resp, err := mgr.Generate(c.Request.Context(), req.Scope) if err != nil { - c.JSON(http.StatusInternalServerError, capService.RedeemResponse{ + c.JSON(http.StatusInternalServerError, RedeemResponse{ Success: false, Error: err.Error(), }) @@ -58,14 +57,14 @@ func Challenge(c *gin.Context) { // @Accept json // @Produce json // @Param request body redeemRequest true "难题 Token 与解答 solutions 数组" -// @Success 200 {object} capService.RedeemResponse "核销成功,返回 X-Cap-Token" -// @Failure 400 {object} capService.RedeemResponse "参数错误或核销失败" -// @Failure 500 {object} capService.RedeemResponse "内部服务错误" +// @Success 200 {object} RedeemResponse "核销成功,返回 X-Cap-Token" +// @Failure 400 {object} RedeemResponse "参数错误或核销失败" +// @Failure 500 {object} RedeemResponse "内部服务错误" // @Router /api/cap/redeem [post] func Redeem(c *gin.Context) { var req redeemRequest if err := c.ShouldBindJSON(&req); err != nil { - c.JSON(http.StatusBadRequest, capService.RedeemResponse{ + c.JSON(http.StatusBadRequest, RedeemResponse{ Success: false, Error: "无效的参数", }) @@ -76,10 +75,10 @@ func Redeem(c *gin.Context) { req.Scope = "login" } - mgr := capService.GetDefaultManager() + mgr := GetDefaultManager() resp, err := mgr.Redeem(c.Request.Context(), req.Token, req.Solutions, req.Scope) if err != nil { - c.JSON(http.StatusInternalServerError, capService.RedeemResponse{ + c.JSON(http.StatusInternalServerError, RedeemResponse{ Success: false, Error: err.Error(), }) diff --git a/internal/apps/cap/routers_test.go b/internal/apps/cap/routers_test.go index e3531077..956059ec 100644 --- a/internal/apps/cap/routers_test.go +++ b/internal/apps/cap/routers_test.go @@ -13,8 +13,7 @@ import ("bytes" "github.com/Rain-kl/Wavelet/internal/db" "github.com/Rain-kl/Wavelet/internal/model" "github.com/Rain-kl/Wavelet/internal/testhelper" - capUtil "github.com/Rain-kl/Wavelet/internal/service/cap" - pkgcap "github.com/Rain-kl/Wavelet/pkg/cap" + pkgcap "github.com/Rain-kl/Wavelet/pkg/cap" "github.com/gin-gonic/gin" "github.com/Rain-kl/Wavelet/internal/common/response") @@ -34,7 +33,7 @@ func TestCapEndpointsAndMiddleware(t *testing.T) { } // Login endpoint with CAPTCHA middleware - r.POST("/api/v1/user/login", VerifyMiddleware(capUtil.GetDefaultManager(), "login", func() bool { + r.POST("/api/v1/user/login", VerifyMiddleware(GetDefaultManager(), "login", func() bool { enabled, err := model.GetBoolByKey(context.Background(), model.ConfigKeyCapLoginEnabled) if err != nil { return false @@ -106,7 +105,7 @@ func TestCapEndpointsAndMiddleware(t *testing.T) { t.Fatalf("expected 200 OK for redeem, got %d. Body: %s", w.Code, w.Body.String()) } - var redeemResp capUtil.RedeemResponse + var redeemResp RedeemResponse if err := json.Unmarshal(w.Body.Bytes(), &redeemResp); err != nil { t.Fatalf("failed to unmarshal redeem response: %v", err) } diff --git a/internal/service/cleanup.go b/internal/apps/upload/cleanup.go similarity index 98% rename from internal/service/cleanup.go rename to internal/apps/upload/cleanup.go index 11a5129c..3d4977d8 100644 --- a/internal/service/cleanup.go +++ b/internal/apps/upload/cleanup.go @@ -1,8 +1,8 @@ // Copyright 2026 Arctel.net // SPDX-License-Identifier: Apache-2.0 -// Package service implements Wavelet's core background service processes. -package service +// Package upload implements upload tasks and file cleanup services. +package upload import ( "context" diff --git a/internal/apps/upload/tasks_test.go b/internal/apps/upload/tasks_test.go index 5a5031c9..83476cbb 100644 --- a/internal/apps/upload/tasks_test.go +++ b/internal/apps/upload/tasks_test.go @@ -20,7 +20,6 @@ import ( "github.com/Rain-kl/Wavelet/internal/db" "github.com/Rain-kl/Wavelet/internal/diskcache" "github.com/Rain-kl/Wavelet/internal/model" - "github.com/Rain-kl/Wavelet/internal/service" "github.com/Rain-kl/Wavelet/internal/storage" "github.com/Rain-kl/Wavelet/internal/task" "github.com/Rain-kl/Wavelet/internal/testhelper" @@ -111,7 +110,7 @@ func TestSystemCleanupHandler_Execute(t *testing.T) { require.NoError(t, err) // 执行 handler - handler := &service.SystemCleanupHandler{} + handler := &SystemCleanupHandler{} result, err := handler.Execute(ctx, nil) // 验证结果 @@ -162,7 +161,7 @@ func TestSystemCleanupHandler_ExecuteNoFiles(t *testing.T) { require.NoError(t, err) // 没有任何上传记录 - handler := &service.SystemCleanupHandler{} + handler := &SystemCleanupHandler{} result, err := handler.Execute(ctx, nil) require.NoError(t, err) @@ -172,7 +171,7 @@ func TestSystemCleanupHandler_ExecuteNoFiles(t *testing.T) { func TestSystemCleanupHandler_ImplementsTaskHandler(t *testing.T) { // 编译期验证 SystemCleanupHandler 实现了 TaskHandler 接口 - var _ task.TaskHandler = (*service.SystemCleanupHandler)(nil) + var _ task.TaskHandler = (*SystemCleanupHandler)(nil) } func TestWarmImageCacheHandlerValidatePayload(t *testing.T) { diff --git a/internal/diskcache/cache.go b/internal/diskcache/cache.go index 1ad50ac6..d2525b9f 100644 --- a/internal/diskcache/cache.go +++ b/internal/diskcache/cache.go @@ -12,7 +12,7 @@ import ( "github.com/Rain-kl/Wavelet/internal/db" "github.com/Rain-kl/Wavelet/internal/model" - pkgcache "github.com/Rain-kl/Wavelet/pkg/diskcache" + pkgcache "github.com/Rain-kl/Wavelet/pkg/cache/disk" ) // Status represents the runtime cache statistics. @@ -35,7 +35,7 @@ var ErrCacheMiss = pkgcache.ErrCacheMiss // DiskCache is a wrapper around the generic pkg/diskcache that integrates with the DB for configs. type DiskCache struct { - *pkgcache.DiskCache + *pkgcache.Cache } var ( diff --git a/internal/router/router.go b/internal/router/router.go index 42d8a1f9..612193c3 100644 --- a/internal/router/router.go +++ b/internal/router/router.go @@ -33,7 +33,6 @@ import ( "github.com/Rain-kl/Wavelet/internal/apps/upload" "github.com/Rain-kl/Wavelet/internal/apps/user" "github.com/Rain-kl/Wavelet/internal/model" - capUtil "github.com/Rain-kl/Wavelet/internal/service/cap" // Swagger 文档生成 _ "github.com/Rain-kl/Wavelet/docs" @@ -208,21 +207,21 @@ func registerOAuthRoutes(apiV1Router *gin.RouterGroup) { func registerUserRoutes(apiV1Router *gin.RouterGroup) { userRouter := apiV1Router.Group("/user") { - userRouter.POST("/login", capApp.VerifyMiddleware(capUtil.GetDefaultManager(), "login", func() bool { + userRouter.POST("/login", capApp.VerifyMiddleware(capApp.GetDefaultManager(), "login", func() bool { enabled, err := model.GetBoolByKey(context.Background(), model.ConfigKeyCapLoginEnabled) if err != nil { return false } return enabled }), user.Login) - userRouter.POST("/register", capApp.VerifyMiddleware(capUtil.GetDefaultManager(), "register", func() bool { + userRouter.POST("/register", capApp.VerifyMiddleware(capApp.GetDefaultManager(), "register", func() bool { enabled, err := model.GetBoolByKey(context.Background(), model.ConfigKeyCapLoginEnabled) if err != nil { return false } return enabled }), user.Register) - userRouter.POST("/send-email-code", capApp.VerifyMiddleware(capUtil.GetDefaultManager(), "send_email_code", func() bool { + userRouter.POST("/send-email-code", capApp.VerifyMiddleware(capApp.GetDefaultManager(), "send_email_code", func() bool { enabled, err := model.GetBoolByKey(context.Background(), model.ConfigKeyCapLoginEnabled) if err != nil { return false diff --git a/internal/service/.gitkeep b/internal/service/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/internal/task/handlers/register.go b/internal/task/handlers/register.go index 37866bcc..b9ef86b5 100644 --- a/internal/task/handlers/register.go +++ b/internal/task/handlers/register.go @@ -9,7 +9,6 @@ import ( "github.com/Rain-kl/Wavelet/internal/apps/admin/push" "github.com/Rain-kl/Wavelet/internal/apps/upload" "github.com/Rain-kl/Wavelet/internal/apps/user" - "github.com/Rain-kl/Wavelet/internal/service" "github.com/Rain-kl/Wavelet/internal/task" ) @@ -19,8 +18,8 @@ func Register() { task.RegisterTaskMeta(upload.StorageMigrationMeta) // system cleanup - task.RegisterHandler(service.SystemCleanupTask, &service.SystemCleanupHandler{}) - task.RegisterTaskMeta(service.SystemCleanupMeta) + task.RegisterHandler(upload.SystemCleanupTask, &upload.SystemCleanupHandler{}) + task.RegisterTaskMeta(upload.SystemCleanupMeta) // upload task.RegisterHandler(upload.WarmImageCacheTask, &upload.WarmImageCacheHandler{}) diff --git a/pkg/diskcache/cache.go b/pkg/cache/disk/cache.go similarity index 89% rename from pkg/diskcache/cache.go rename to pkg/cache/disk/cache.go index e273f41c..236b1700 100644 --- a/pkg/diskcache/cache.go +++ b/pkg/cache/disk/cache.go @@ -1,8 +1,8 @@ // Copyright 2026 Arctel.net // SPDX-License-Identifier: Apache-2.0 -// Package diskcache implements a platform-level disk-backed cache with size limit, TTL, and LRU eviction. -package diskcache +// Package disk implements a platform-level disk-backed cache with size limit, TTL, and LRU eviction. +package disk import ( "container/list" @@ -44,8 +44,8 @@ type Status struct { BasePath string `json:"base_path"` } -// DiskCache implements the disk-backed cache with size limits, TTL, and LRU eviction. -type DiskCache struct { +// Cache implements the disk-backed cache with size limits, TTL, and LRU eviction. +type Cache struct { mu sync.RWMutex d *diskv.Diskv basePath string @@ -65,15 +65,15 @@ type cacheItem struct { expiredAt time.Time } -// New creates a new DiskCache instance. -func New(basePath string) *DiskCache { +// New creates a new Cache instance. +func New(basePath string) *Cache { d := diskv.New(diskv.Options{ BasePath: basePath, Transform: func(_ string) []string { return []string{} }, // flat structure for easy walk CacheSizeMax: 1024 * 1024, // 1MB in-memory cache size for diskv itself }) - c := &DiskCache{ + c := &Cache{ d: d, basePath: basePath, maxSize: defaultMaxSizeMB * 1024 * 1024, // 100MB default @@ -91,7 +91,7 @@ func New(basePath string) *DiskCache { // Set stores a key-value pair in the cache. // Use DefaultExpiration for the configured default TTL, NoExpiration for no // TTL, or a positive duration for a business-specific TTL. -func (c *DiskCache) Set(key string, value []byte, ttl time.Duration) error { +func (c *Cache) Set(key string, value []byte, ttl time.Duration) error { c.mu.Lock() defer c.mu.Unlock() @@ -146,7 +146,7 @@ func (c *DiskCache) Set(key string, value []byte, ttl time.Duration) error { } // Get retrieves a key's value from the cache. -func (c *DiskCache) Get(key string) ([]byte, error) { +func (c *Cache) Get(key string) ([]byte, error) { c.mu.Lock() defer c.mu.Unlock() @@ -185,13 +185,13 @@ func (c *DiskCache) Get(key string) ([]byte, error) { } // Delete removes a key-value pair from the cache. -func (c *DiskCache) Delete(key string) error { +func (c *Cache) Delete(key string) error { c.mu.Lock() defer c.mu.Unlock() return c.deleteUnlocked(key) } -func (c *DiskCache) deleteUnlocked(key string) error { +func (c *Cache) deleteUnlocked(key string) error { if elem, ok := c.items[key]; ok { item := elem.Value.(*cacheItem) c.currentSize -= item.size @@ -202,7 +202,7 @@ func (c *DiskCache) deleteUnlocked(key string) error { } // Clear flushes all cached elements. -func (c *DiskCache) Clear() error { +func (c *Cache) Clear() error { c.mu.Lock() defer c.mu.Unlock() @@ -214,7 +214,7 @@ func (c *DiskCache) Clear() error { } // Status returns the cache status. -func (c *DiskCache) Status() Status { +func (c *Cache) Status() Status { c.mu.RLock() defer c.mu.RUnlock() @@ -229,7 +229,7 @@ func (c *DiskCache) Status() Status { } // UpdatePolicy dynamically updates policies. -func (c *DiskCache) UpdatePolicy(maxSizeMB int64, ttlMinutes int64, lruEnabled bool) { +func (c *Cache) UpdatePolicy(maxSizeMB int64, ttlMinutes int64, lruEnabled bool) { c.mu.Lock() defer c.mu.Unlock() @@ -240,7 +240,7 @@ func (c *DiskCache) UpdatePolicy(maxSizeMB int64, ttlMinutes int64, lruEnabled b } // evict evicts oldest items if current size exceeds maxSize and LRU is enabled. -func (c *DiskCache) evict() { +func (c *Cache) evict() { if !c.lruEnabled { return } @@ -256,7 +256,7 @@ func (c *DiskCache) evict() { } // loadTracker scans the cache directory on startup to rebuild memory state. -func (c *DiskCache) loadTracker() error { +func (c *Cache) loadTracker() error { c.mu.Lock() defer c.mu.Unlock() @@ -325,7 +325,7 @@ func (c *DiskCache) loadTracker() error { } // StartCleanupWorker periodically cleans up expired cache items. -func (c *DiskCache) StartCleanupWorker(interval time.Duration) { +func (c *Cache) StartCleanupWorker(interval time.Duration) { ticker := time.NewTicker(interval) for range ticker.C { c.cleanExpired() @@ -333,7 +333,7 @@ func (c *DiskCache) StartCleanupWorker(interval time.Duration) { } // cleanExpired scans memory for expired items and removes them. -func (c *DiskCache) cleanExpired() { +func (c *Cache) cleanExpired() { c.mu.Lock() defer c.mu.Unlock() diff --git a/pkg/diskcache/cache_test.go b/pkg/cache/disk/cache_test.go similarity index 99% rename from pkg/diskcache/cache_test.go rename to pkg/cache/disk/cache_test.go index 78e1eed1..107d3c44 100644 --- a/pkg/diskcache/cache_test.go +++ b/pkg/cache/disk/cache_test.go @@ -1,7 +1,7 @@ // Copyright 2026 Arctel.net // SPDX-License-Identifier: Apache-2.0 -package diskcache +package disk import ( "bytes"