feat: run.sh四模式(dev/docker/build/binary) + CLI flags + Redka内嵌Redis + Agent复制修复 + 服务器编辑IP字段 + 安装Agent按钮
This commit is contained in:
1 parent
d0b94d39c0
commit
2354959811
14 files changed
+1355
-575
No files matched your search
@@ -0,0 +1,66 @@
|
||||
// go-redis 外部 Redis 服务器实现
|
||||
// 用于 Docker Compose / 生产环境部署 // Logan.Li
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
goredis "github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
// goRedisCache 基于 go-redis 的缓存实现 // Logan.Li
|
||||
type goRedisCache struct {
|
||||
client *goredis.Client
|
||||
}
|
||||
|
||||
func newGoRedis(cfg Config) (Cache, error) {
|
||||
client := goredis.NewClient(&goredis.Options{
|
||||
Addr: fmt.Sprintf("%s:%d", cfg.Host, cfg.Port),
|
||||
Password: cfg.Password,
|
||||
DB: cfg.DB,
|
||||
})
|
||||
|
||||
// 连接测试
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := client.Ping(ctx).Err(); err != nil {
|
||||
return nil, fmt.Errorf("redis: 连接失败 %s:%d: %w", cfg.Host, cfg.Port, err)
|
||||
}
|
||||
|
||||
return &goRedisCache{client: client}, nil
|
||||
}
|
||||
|
||||
func (r *goRedisCache) Get(ctx context.Context, key string) (string, error) {
|
||||
val, err := r.client.Get(ctx, key).Result()
|
||||
if err == goredis.Nil {
|
||||
return "", nil
|
||||
}
|
||||
return val, err
|
||||
}
|
||||
|
||||
func (r *goRedisCache) Set(ctx context.Context, key string, value string, expiration time.Duration) error {
|
||||
return r.client.Set(ctx, key, value, expiration).Err()
|
||||
}
|
||||
|
||||
func (r *goRedisCache) Del(ctx context.Context, keys ...string) error {
|
||||
return r.client.Del(ctx, keys...).Err()
|
||||
}
|
||||
|
||||
func (r *goRedisCache) Exists(ctx context.Context, keys ...string) (int64, error) {
|
||||
return r.client.Exists(ctx, keys...).Result()
|
||||
}
|
||||
|
||||
func (r *goRedisCache) Expire(ctx context.Context, key string, expiration time.Duration) error {
|
||||
return r.client.Expire(ctx, key, expiration).Err()
|
||||
}
|
||||
|
||||
func (r *goRedisCache) Ping(ctx context.Context) error {
|
||||
return r.client.Ping(ctx).Err()
|
||||
}
|
||||
|
||||
func (r *goRedisCache) Close() error {
|
||||
return r.client.Close()
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Package redis 提供统一的 Redis 缓存抽象层
|
||||
// 支持两种后端:
|
||||
// - redka: 内嵌 Redis 兼容存储(零依赖,独立二进制模式)// Logan.Li
|
||||
// - redis: 外部 Redis 服务器(Docker / 生产环境)
|
||||
//
|
||||
// 使用方式:
|
||||
//
|
||||
// cache, err := redis.New(redis.Config{
|
||||
// Driver: "redka", // 或 "redis"
|
||||
// Host: "localhost",
|
||||
// Port: 6379,
|
||||
// Password: "",
|
||||
// DB: 0,
|
||||
// DataDir: "data/redka", // redka 数据目录(仅 redka 驱动使用)
|
||||
// })
|
||||
//
|
||||
// cache.Set(ctx, "key", "value", 0)
|
||||
// val, _ := cache.Get(ctx, "key")
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Config Redis 配置 // Logan.Li
|
||||
type Config struct {
|
||||
Driver string // "redka" 或 "redis"
|
||||
Host string
|
||||
Port int
|
||||
Password string
|
||||
DB int
|
||||
DataDir string // redka 数据目录
|
||||
}
|
||||
|
||||
// Cache Redis 缓存接口 // Logan.Li
|
||||
type Cache interface {
|
||||
Get(ctx context.Context, key string) (string, error)
|
||||
Set(ctx context.Context, key string, value string, expiration time.Duration) error
|
||||
Del(ctx context.Context, keys ...string) error
|
||||
Exists(ctx context.Context, keys ...string) (int64, error)
|
||||
Expire(ctx context.Context, key string, expiration time.Duration) error
|
||||
Ping(ctx context.Context) error
|
||||
Close() error
|
||||
}
|
||||
|
||||
// New 创建缓存实例(根据驱动自动选择后端)// Logan.Li
|
||||
func New(cfg Config) (Cache, error) {
|
||||
switch cfg.Driver {
|
||||
case "redka", "":
|
||||
return newRedka(cfg)
|
||||
case "redis":
|
||||
return newGoRedis(cfg)
|
||||
default:
|
||||
return nil, fmt.Errorf("redis: 不支持的驱动: %s (支持: redka, redis)", cfg.Driver)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
// redka 内嵌 Redis 兼容存储实现(v0.2.x API)
|
||||
// 使用 github.com/nalgeon/redka — 基于 SQLite 的 Redis 替代方案 // Logan.Li
|
||||
// 零外部依赖,数据存在本地文件中,非常适合独立二进制部署
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/nalgeon/redka"
|
||||
)
|
||||
|
||||
// redkaCache 基于 Redka v0.2.x 的缓存实现 // Logan.Li
|
||||
type redkaCache struct {
|
||||
db *redka.DB
|
||||
}
|
||||
|
||||
func newRedka(cfg Config) (Cache, error) {
|
||||
dataDir := cfg.DataDir
|
||||
if dataDir == "" {
|
||||
dataDir = "data/redka"
|
||||
}
|
||||
|
||||
// Redka v0.2.x: Open(path, opts) // Logan.Li
|
||||
db, err := redka.Open(dataDir+"/redka.db", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &redkaCache{db: db}, nil
|
||||
}
|
||||
|
||||
func (r *redkaCache) Get(ctx context.Context, key string) (string, error) {
|
||||
// Redka v0.2.x: Str().Get() 返回 core.Value // Logan.Li
|
||||
val, err := r.db.Str().Get(key)
|
||||
if err == redka.ErrNotFound {
|
||||
return "", nil
|
||||
}
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return val.String(), nil
|
||||
}
|
||||
|
||||
func (r *redkaCache) Set(ctx context.Context, key string, value string, expiration time.Duration) error {
|
||||
// Redka v0.2.x: Str().Set() 返回 error // Logan.Li
|
||||
if err := r.db.Str().Set(key, value); err != nil {
|
||||
return err
|
||||
}
|
||||
if expiration > 0 {
|
||||
_, err := r.db.Key().Expire(key, expiration)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *redkaCache) Del(ctx context.Context, keys ...string) error {
|
||||
for _, key := range keys {
|
||||
if _, err := r.db.Key().Delete(key); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *redkaCache) Exists(ctx context.Context, keys ...string) (int64, error) {
|
||||
var count int64
|
||||
for _, key := range keys {
|
||||
ok, err := r.db.Key().Exists(key)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if ok {
|
||||
count++
|
||||
}
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (r *redkaCache) Expire(ctx context.Context, key string, expiration time.Duration) error {
|
||||
ok, err := r.db.Key().Expire(key, expiration)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return redka.ErrNotFound
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *redkaCache) Ping(ctx context.Context) error {
|
||||
// Redka 始终可用(内嵌数据库)// Logan.Li
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *redkaCache) Close() error {
|
||||
return r.db.Close()
|
||||
}
|
||||
Reference in new issue
Block a user