mirror of
https://github.com/langgenius/dify-plugin-daemon.git
synced 2026-07-21 17:25:23 -04:00
feat(redis): implement CSV parsing utility and refactor Redis transaction handling
This commit is contained in:
@@ -2,7 +2,6 @@ package plugin_manager
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru/v2"
|
||||
"github.com/langgenius/dify-cloud-kit/oss"
|
||||
@@ -18,6 +17,7 @@ import (
|
||||
"github.com/langgenius/dify-plugin-daemon/pkg/plugin_packager/decoder"
|
||||
"github.com/langgenius/dify-plugin-daemon/pkg/utils/cache"
|
||||
"github.com/langgenius/dify-plugin-daemon/pkg/utils/log"
|
||||
"github.com/langgenius/dify-plugin-daemon/pkg/utils/parser"
|
||||
)
|
||||
|
||||
type PluginManager struct {
|
||||
@@ -126,8 +126,14 @@ func (p *PluginManager) Launch(configuration *app.Config) {
|
||||
cache.SetKeyPrefix(configuration.RedisKeyPrefix)
|
||||
|
||||
// init redis client
|
||||
if configuration.RedisUseClusters && configuration.RedisUseSentinel {
|
||||
log.Panic("REDIS_USE_CLUSTERS and REDIS_USE_SENTINEL cannot both be true")
|
||||
}
|
||||
if configuration.RedisUseClusters {
|
||||
addrs := splitAndTrimCSV(configuration.RedisClusters)
|
||||
if configuration.RedisDB != 0 {
|
||||
log.Panic("REDIS_DB must be 0 when REDIS_USE_CLUSTERS is true (Redis Cluster does not support SELECT DB)")
|
||||
}
|
||||
addrs := parser.SplitAndTrimCSV(configuration.RedisClusters)
|
||||
if len(addrs) == 0 {
|
||||
log.Panic("REDIS_USE_CLUSTERS is true but REDIS_CLUSTERS is empty")
|
||||
}
|
||||
@@ -146,7 +152,7 @@ func (p *PluginManager) Launch(configuration *app.Config) {
|
||||
}
|
||||
} else if configuration.RedisUseSentinel {
|
||||
// use Redis Sentinel
|
||||
sentinels := strings.Split(configuration.RedisSentinels, ",")
|
||||
sentinels := parser.SplitAndTrimCSV(configuration.RedisSentinels)
|
||||
if err := cache.InitRedisSentinelClient(
|
||||
sentinels,
|
||||
configuration.RedisSentinelServiceName,
|
||||
@@ -267,17 +273,3 @@ func (p *PluginManager) ExtractPluginAsset(
|
||||
p.pluginAssetCache.Add(key, assets[path])
|
||||
return assets[path], nil
|
||||
}
|
||||
|
||||
func splitAndTrimCSV(s string) []string {
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
parts := strings.Split(s, ",")
|
||||
out := make([]string, 0, len(parts))
|
||||
for _, p := range parts {
|
||||
if trimmed := strings.TrimSpace(p); trimmed != "" {
|
||||
out = append(out, trimmed)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
Vendored
+5
-5
@@ -616,14 +616,14 @@ func Expire(key string, time time.Duration, context ...redis.Cmdable) (bool, err
|
||||
return getCmdable(context...).Expire(ctx, serialKey(key), time).Result()
|
||||
}
|
||||
|
||||
func Transaction(fn func(redis.Pipeliner) error, keys ...string) error {
|
||||
func Transaction(fn func(redis.Pipeliner) error, watchKeys ...string) error {
|
||||
if client == nil {
|
||||
return ErrDBNotInit
|
||||
}
|
||||
|
||||
watchKeys := make([]string, len(keys))
|
||||
for i, k := range keys {
|
||||
watchKeys[i] = serialKey(k)
|
||||
serialized := make([]string, len(watchKeys))
|
||||
for i, k := range watchKeys {
|
||||
serialized[i] = serialKey(k)
|
||||
}
|
||||
|
||||
return client.Watch(ctx, func(tx *redis.Tx) error {
|
||||
@@ -634,7 +634,7 @@ func Transaction(fn func(redis.Pipeliner) error, keys ...string) error {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}, watchKeys...)
|
||||
}, serialized...)
|
||||
}
|
||||
|
||||
func Publish(channel string, message any, context ...redis.Cmdable) error {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package parser
|
||||
|
||||
import "strings"
|
||||
|
||||
func SplitAndTrimCSV(s string) []string {
|
||||
if s == "" {
|
||||
return nil
|
||||
}
|
||||
parts := strings.Split(s, ",")
|
||||
out := make([]string, 0, len(parts))
|
||||
for _, p := range parts {
|
||||
if trimmed := strings.TrimSpace(p); trimmed != "" {
|
||||
out = append(out, trimmed)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSplitAndTrimCSV(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
want []string
|
||||
}{
|
||||
{"empty string", "", nil},
|
||||
{"only separators", ",,,", []string{}},
|
||||
{"only whitespace between separators", " , , ,", []string{}},
|
||||
{"single value", "a", []string{"a"}},
|
||||
{"trims surrounding whitespace", " a , b ", []string{"a", "b"}},
|
||||
{"drops empty segments", "a, ,b", []string{"a", "b"}},
|
||||
{"preserves inner colons", "host1:6379, host2:6379", []string{"host1:6379", "host2:6379"}},
|
||||
{"trailing comma", "a,b,", []string{"a", "b"}},
|
||||
{"leading comma", ",a,b", []string{"a", "b"}},
|
||||
{"tabs and mixed whitespace", "\ta\t,\nb\n", []string{"a", "b"}},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := SplitAndTrimCSV(tt.input)
|
||||
if len(got) == 0 && len(tt.want) == 0 {
|
||||
return
|
||||
}
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("SplitAndTrimCSV(%q) = %#v, want %#v", tt.input, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user