优化结构
This commit is contained in:
@@ -68,6 +68,13 @@ func (s *Store) Set(config Config) {
|
||||
config = cloneConfig(config)
|
||||
key := configKey(config.Kind, config.Provider)
|
||||
s.mu.Lock()
|
||||
if s.values == nil {
|
||||
s.values = make(map[string]Config)
|
||||
}
|
||||
if previous, exists := s.values[key]; exists && sameConfig(previous, config) {
|
||||
s.mu.Unlock()
|
||||
return
|
||||
}
|
||||
s.values[key] = config
|
||||
callbacks := s.matchingListenersLocked(config.Kind, config.Provider)
|
||||
s.mu.Unlock()
|
||||
@@ -83,7 +90,12 @@ func (s *Store) Delete(kind, provider string) {
|
||||
kind = strings.ToLower(strings.TrimSpace(kind))
|
||||
provider = strings.ToLower(strings.TrimSpace(provider))
|
||||
s.mu.Lock()
|
||||
delete(s.values, configKey(kind, provider))
|
||||
key := configKey(kind, provider)
|
||||
if _, exists := s.values[key]; !exists {
|
||||
s.mu.Unlock()
|
||||
return
|
||||
}
|
||||
delete(s.values, key)
|
||||
callbacks := s.matchingListenersLocked(kind, provider)
|
||||
s.mu.Unlock()
|
||||
config := Config{Kind: kind, Provider: provider}
|
||||
@@ -142,6 +154,9 @@ func (s *Store) Subscribe(kind, provider string, callback func(Config)) func() {
|
||||
s.mu.Lock()
|
||||
s.nextID++
|
||||
id := s.nextID
|
||||
if s.listeners == nil {
|
||||
s.listeners = make(map[uint64]listener)
|
||||
}
|
||||
s.listeners[id] = listener{kind: strings.ToLower(strings.TrimSpace(kind)), provider: strings.ToLower(strings.TrimSpace(provider)), callback: callback}
|
||||
s.mu.Unlock()
|
||||
return func() {
|
||||
|
||||
@@ -63,3 +63,23 @@ func TestStoreReplaceSkipsUnchangedValues(t *testing.T) {
|
||||
t.Fatal("changed replace notification was not delivered")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStoreSetSkipsUnchangedValues(t *testing.T) {
|
||||
var store Store
|
||||
updates := make(chan Config, 1)
|
||||
stop := store.Subscribe("mq", "rabbitmq", func(config Config) { updates <- config })
|
||||
defer stop()
|
||||
config := Config{Kind: "mq", Provider: "rabbitmq", Enabled: true, Values: json.RawMessage(`{"host":"localhost"}`)}
|
||||
store.Set(config)
|
||||
select {
|
||||
case <-updates:
|
||||
case <-time.After(time.Second):
|
||||
t.Fatal("initial set notification was not delivered")
|
||||
}
|
||||
store.Set(config)
|
||||
select {
|
||||
case update := <-updates:
|
||||
t.Fatalf("unchanged set emitted notification: %#v", update)
|
||||
case <-time.After(20 * time.Millisecond):
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ func (s *aliyunStorage) DeletePrefix(ctx context.Context, prefix string) error {
|
||||
}
|
||||
cursor := ""
|
||||
for {
|
||||
items, next, more, err := s.List(ctx, prefix, cursor, 1000)
|
||||
items, next, more, err := s.List(ctx, prefix+"/", cursor, 1000)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -97,7 +97,7 @@ func (s *aliyunStorage) List(_ context.Context, prefix, cursor string, limit int
|
||||
if limit <= 0 {
|
||||
limit = 100
|
||||
}
|
||||
result, err := s.bucket.ListObjects(oss.Prefix(s.key(prefix)), oss.Marker(cursor), oss.MaxKeys(limit))
|
||||
result, err := s.bucket.ListObjects(oss.Prefix(boundedPrefix(s.key(prefix), prefix)), oss.Marker(cursor), oss.MaxKeys(limit))
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ func (s *awsStorage) DeletePrefix(ctx context.Context, prefix string) error {
|
||||
}
|
||||
cursor := ""
|
||||
for {
|
||||
items, next, more, err := s.List(ctx, prefix, cursor, 1000)
|
||||
items, next, more, err := s.List(ctx, prefix+"/", cursor, 1000)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -134,7 +134,7 @@ func (s *awsStorage) List(ctx context.Context, prefix, cursor string, limit int)
|
||||
if limit <= 0 {
|
||||
limit = 100
|
||||
}
|
||||
input := &s3.ListObjectsV2Input{Bucket: aws.String(s.bucket), Prefix: aws.String(s.key(prefix)), MaxKeys: aws.Int32(int32(limit))}
|
||||
input := &s3.ListObjectsV2Input{Bucket: aws.String(s.bucket), Prefix: aws.String(boundedPrefix(s.key(prefix), prefix)), MaxKeys: aws.Int32(int32(limit))}
|
||||
if cursor != "" {
|
||||
input.ContinuationToken = aws.String(cursor)
|
||||
}
|
||||
|
||||
@@ -100,6 +100,15 @@ func TestNormalizeDeletePrefix(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoundedPrefixKeepsDirectoryBoundary(t *testing.T) {
|
||||
if got := boundedPrefix("uploads/chunks/1", "uploads/chunks/1/"); got != "uploads/chunks/1/" {
|
||||
t.Fatalf("boundedPrefix() = %q", got)
|
||||
}
|
||||
if got := boundedPrefix("uploads/chunks/1", "uploads/chunks/1"); got != "uploads/chunks/1" {
|
||||
t.Fatalf("boundedPrefix() changed ordinary prefix to %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAdvanceDeletePrefixCursor(t *testing.T) {
|
||||
if _, err := advanceDeletePrefixCursor("cursor", "cursor", true); err == nil {
|
||||
t.Fatal("same cursor should fail")
|
||||
|
||||
@@ -74,7 +74,7 @@ func (s *huaweiStorage) DeletePrefix(ctx context.Context, prefix string) error {
|
||||
}
|
||||
cursor := ""
|
||||
for {
|
||||
items, next, more, err := s.List(ctx, prefix, cursor, 1000)
|
||||
items, next, more, err := s.List(ctx, prefix+"/", cursor, 1000)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -96,7 +96,7 @@ func (s *huaweiStorage) List(_ context.Context, prefix, cursor string, limit int
|
||||
if limit <= 0 {
|
||||
limit = 100
|
||||
}
|
||||
result, err := s.client.ListObjects(&obs.ListObjectsInput{ListObjsInput: obs.ListObjsInput{Prefix: s.key(prefix), MaxKeys: limit}, Bucket: s.bucket, Marker: cursor})
|
||||
result, err := s.client.ListObjects(&obs.ListObjectsInput{ListObjsInput: obs.ListObjsInput{Prefix: boundedPrefix(s.key(prefix), prefix), MaxKeys: limit}, Bucket: s.bucket, Marker: cursor})
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
|
||||
@@ -39,3 +39,10 @@ func advanceDeletePrefixCursor(current, next string, more bool) (string, error)
|
||||
}
|
||||
return next, nil
|
||||
}
|
||||
|
||||
func boundedPrefix(key, prefix string) string {
|
||||
if strings.HasSuffix(strings.ReplaceAll(prefix, "\\", "/"), "/") && !strings.HasSuffix(key, "/") {
|
||||
return key + "/"
|
||||
}
|
||||
return key
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ func (s *qiniuStorage) DeletePrefix(ctx context.Context, prefix string) error {
|
||||
}
|
||||
cursor := ""
|
||||
for {
|
||||
items, next, more, err := s.List(ctx, prefix, cursor, 1000)
|
||||
items, next, more, err := s.List(ctx, prefix+"/", cursor, 1000)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -124,7 +124,7 @@ func (s *qiniuStorage) List(ctx context.Context, prefix, cursor string, limit in
|
||||
if limit <= 0 {
|
||||
limit = 100
|
||||
}
|
||||
entries, _, marker, more, err := s.manager.ListFiles(s.config.Bucket, prefix, "", cursor, limit)
|
||||
entries, _, marker, more, err := s.manager.ListFiles(s.config.Bucket, boundedPrefix(strings.TrimPrefix(prefix, "/"), prefix), "", cursor, limit)
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ func (s *s3Storage) DeletePrefix(ctx context.Context, prefix string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
items := s.client.ListObjects(ctx, s.bucket, minio.ListObjectsOptions{Prefix: s.key(prefix), Recursive: true})
|
||||
items := s.client.ListObjects(ctx, s.bucket, minio.ListObjectsOptions{Prefix: boundedPrefix(s.key(prefix), prefix), Recursive: true})
|
||||
for item := range items {
|
||||
if item.Err != nil {
|
||||
return item.Err
|
||||
|
||||
@@ -88,7 +88,7 @@ func (s *tencentStorage) DeletePrefix(ctx context.Context, prefix string) error
|
||||
}
|
||||
cursor := ""
|
||||
for {
|
||||
items, next, more, err := s.List(ctx, prefix, cursor, 1000)
|
||||
items, next, more, err := s.List(ctx, prefix+"/", cursor, 1000)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -110,7 +110,7 @@ func (s *tencentStorage) List(ctx context.Context, prefix, cursor string, limit
|
||||
if limit <= 0 {
|
||||
limit = 100
|
||||
}
|
||||
result, _, err := s.client.Bucket.Get(ctx, &cos.BucketGetOptions{Prefix: s.key(prefix), Marker: cursor, MaxKeys: limit})
|
||||
result, _, err := s.client.Bucket.Get(ctx, &cos.BucketGetOptions{Prefix: boundedPrefix(s.key(prefix), prefix), Marker: cursor, MaxKeys: limit})
|
||||
if err != nil {
|
||||
return nil, "", false, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user