Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions notification-dingtalk/dingtalk_notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,7 @@ func (n *Notification) Info() plugin.Info {

// GetNewQuestionSubscribers returns the subscribers of the new question notification
func (n *Notification) GetNewQuestionSubscribers() (userIDs []string) {
for userID, conf := range n.UserConfigCache.userConfigMapping {
if conf.AllNewQuestions {
userIDs = append(userIDs, userID)
}
}
return userIDs
return n.UserConfigCache.NewQuestionSubscriberIDs()
}

// Notify sends a notification to the user
Expand Down
15 changes: 14 additions & 1 deletion notification-dingtalk/user_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type UserConfig struct {
type UserConfigCache struct {
// key: userID value: user config
userConfigMapping map[string]*UserConfig
sync.Mutex
sync.RWMutex
}

func NewUserConfigCache() *UserConfigCache {
Expand All @@ -55,6 +55,19 @@ func (ucc *UserConfigCache) SetUserConfig(userID string, config *UserConfig) {
ucc.userConfigMapping[userID] = config
}

func (ucc *UserConfigCache) NewQuestionSubscriberIDs() []string {
ucc.RLock()
defer ucc.RUnlock()

userIDs := make([]string, 0)
for userID, conf := range ucc.userConfigMapping {
if conf.AllNewQuestions {
userIDs = append(userIDs, userID)
}
}
return userIDs
}

func (n *Notification) UserConfigFields() []plugin.ConfigField {
fields := make([]plugin.ConfigField, 0)
// Show tip for user, if the notification service is disabled
Expand Down
51 changes: 51 additions & 0 deletions notification-dingtalk/user_config_concurrency_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0.
*/

package dingtalk

import (
"fmt"
"sync"
"testing"
)

func TestUserConfigCacheConcurrentNewQuestionSubscribers(t *testing.T) {
cache := NewUserConfigCache()
const workers, iterations = 8, 500
start := make(chan struct{})
var wg sync.WaitGroup
for worker := range workers {
wg.Add(1)
go func() {
defer wg.Done()
<-start
for i := range iterations {
cache.SetUserConfig(fmt.Sprintf("writer-%d-user-%d", worker, i%32), &UserConfig{AllNewQuestions: i%2 == 0})
}
}()
}
for range workers {
wg.Add(1)
go func() {
defer wg.Done()
<-start
for range iterations {
_ = cache.NewQuestionSubscriberIDs()
}
}()
}
close(start)
wg.Wait()

cache.SetUserConfig("subscriber", &UserConfig{AllNewQuestions: true})
for _, userID := range cache.NewQuestionSubscriberIDs() {
if userID == "subscriber" {
return
}
}
t.Fatal("subscriber missing from snapshot")
}
7 changes: 1 addition & 6 deletions notification-lark/notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,12 +211,7 @@ func makeCardMsg(args plugin.NotificationMessage) Card {

// GetNewQuestionSubscribers returns the subscribers of the new question notification
func (n *Notification) GetNewQuestionSubscribers() (userIDs []string) {
for userID, conf := range n.userConfigCache.userConfigMapping {
if conf.AllNewQuestions {
userIDs = append(userIDs, userID)
}
}
return userIDs
return n.userConfigCache.NewQuestionSubscriberIDs()
}

// Notify sends a notification to the user
Expand Down
15 changes: 14 additions & 1 deletion notification-lark/user_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type UserConfig struct {

type UserConfigCache struct {
userConfigMapping map[string]*UserConfig
sync.Mutex
sync.RWMutex
}

func NewUserConfigCache() *UserConfigCache {
Expand All @@ -55,6 +55,19 @@ func (ucc *UserConfigCache) SetUserConfig(userID string, config *UserConfig) {
ucc.userConfigMapping[userID] = config
}

func (ucc *UserConfigCache) NewQuestionSubscriberIDs() []string {
ucc.RLock()
defer ucc.RUnlock()

userIDs := make([]string, 0)
for userID, conf := range ucc.userConfigMapping {
if conf.AllNewQuestions {
userIDs = append(userIDs, userID)
}
}
return userIDs
}

func (n *Notification) UserConfigFields() []plugin.ConfigField {
return []plugin.ConfigField{
{
Expand Down
51 changes: 51 additions & 0 deletions notification-lark/user_config_concurrency_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0.
*/

package lark

import (
"fmt"
"sync"
"testing"
)

func TestUserConfigCacheConcurrentNewQuestionSubscribers(t *testing.T) {
cache := NewUserConfigCache()
const workers, iterations = 8, 500
start := make(chan struct{})
var wg sync.WaitGroup
for worker := range workers {
wg.Add(1)
go func() {
defer wg.Done()
<-start
for i := range iterations {
cache.SetUserConfig(fmt.Sprintf("writer-%d-user-%d", worker, i%32), &UserConfig{AllNewQuestions: i%2 == 0})
}
}()
}
for range workers {
wg.Add(1)
go func() {
defer wg.Done()
<-start
for range iterations {
_ = cache.NewQuestionSubscriberIDs()
}
}()
}
close(start)
wg.Wait()

cache.SetUserConfig("subscriber", &UserConfig{AllNewQuestions: true})
for _, userID := range cache.NewQuestionSubscriberIDs() {
if userID == "subscriber" {
return
}
}
t.Fatal("subscriber missing from snapshot")
}
7 changes: 1 addition & 6 deletions notification-slack/slack_notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,7 @@ func (n *Notification) Info() plugin.Info {

// GetNewQuestionSubscribers returns the subscribers of the new question notification
func (n *Notification) GetNewQuestionSubscribers() (userIDs []string) {
for userID, conf := range n.UserConfigCache.userConfigMapping {
if conf.AllNewQuestions {
userIDs = append(userIDs, userID)
}
}
return userIDs
return n.UserConfigCache.NewQuestionSubscriberIDs()
}

// Notify sends a notification to the user
Expand Down
15 changes: 14 additions & 1 deletion notification-slack/user_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type UserConfig struct {
type UserConfigCache struct {
// key: userID value: user config
userConfigMapping map[string]*UserConfig
sync.Mutex
sync.RWMutex
}

func NewUserConfigCache() *UserConfigCache {
Expand All @@ -59,6 +59,19 @@ func (ucc *UserConfigCache) SetUserConfig(userID string, config *UserConfig) {
ucc.userConfigMapping[userID] = config
}

func (ucc *UserConfigCache) NewQuestionSubscriberIDs() []string {
ucc.RLock()
defer ucc.RUnlock()

userIDs := make([]string, 0)
for userID, conf := range ucc.userConfigMapping {
if conf.AllNewQuestions {
userIDs = append(userIDs, userID)
}
}
return userIDs
}

func (n *Notification) UserConfigFields() []plugin.ConfigField {
fields := make([]plugin.ConfigField, 0)
// Show tip for user, if the notification service is disabled
Expand Down
51 changes: 51 additions & 0 deletions notification-slack/user_config_concurrency_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0.
*/

package slack_notification

import (
"fmt"
"sync"
"testing"
)

func TestUserConfigCacheConcurrentNewQuestionSubscribers(t *testing.T) {
cache := NewUserConfigCache()
const workers, iterations = 8, 500
start := make(chan struct{})
var wg sync.WaitGroup
for worker := range workers {
wg.Add(1)
go func() {
defer wg.Done()
<-start
for i := range iterations {
cache.SetUserConfig(fmt.Sprintf("writer-%d-user-%d", worker, i%32), &UserConfig{AllNewQuestions: i%2 == 0})
}
}()
}
for range workers {
wg.Add(1)
go func() {
defer wg.Done()
<-start
for range iterations {
_ = cache.NewQuestionSubscriberIDs()
}
}()
}
close(start)
wg.Wait()

cache.SetUserConfig("subscriber", &UserConfig{AllNewQuestions: true})
for _, userID := range cache.NewQuestionSubscriberIDs() {
if userID == "subscriber" {
return
}
}
t.Fatal("subscriber missing from snapshot")
}
7 changes: 1 addition & 6 deletions notification-wecom/notification_wecom.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,7 @@ func (*Notification) Info() plugin.Info {

// GetNewQuestionSubscribers returns the subscribers of the new question notification
func (n *Notification) GetNewQuestionSubscribers() (userIDs []string) {
for userID, conf := range n.UserConfigCache.userConfigMapping {
if conf.AllNewQuestions {
userIDs = append(userIDs, userID)
}
}
return userIDs
return n.UserConfigCache.NewQuestionSubscriberIDs()
}

// Notify sends a notification to the user
Expand Down
15 changes: 14 additions & 1 deletion notification-wecom/user_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ type UserConfig struct {
type UserConfigCache struct {
// key: userID value: user config
userConfigMapping map[string]*UserConfig
sync.Mutex
sync.RWMutex
}

func NewUserConfigCache() *UserConfigCache {
Expand All @@ -55,6 +55,19 @@ func (ucc *UserConfigCache) SetUserConfig(userID string, config *UserConfig) {
ucc.userConfigMapping[userID] = config
}

func (ucc *UserConfigCache) NewQuestionSubscriberIDs() []string {
ucc.RLock()
defer ucc.RUnlock()

userIDs := make([]string, 0)
for userID, conf := range ucc.userConfigMapping {
if conf.AllNewQuestions {
userIDs = append(userIDs, userID)
}
}
return userIDs
}

func (n *Notification) UserConfigFields() []plugin.ConfigField {
fields := make([]plugin.ConfigField, 0)
// Show tip for user, if the notification service is disabled
Expand Down
51 changes: 51 additions & 0 deletions notification-wecom/user_config_concurrency_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0.
*/

package wecom

import (
"fmt"
"sync"
"testing"
)

func TestUserConfigCacheConcurrentNewQuestionSubscribers(t *testing.T) {
cache := NewUserConfigCache()
const workers, iterations = 8, 500
start := make(chan struct{})
var wg sync.WaitGroup
for worker := range workers {
wg.Add(1)
go func() {
defer wg.Done()
<-start
for i := range iterations {
cache.SetUserConfig(fmt.Sprintf("writer-%d-user-%d", worker, i%32), &UserConfig{AllNewQuestions: i%2 == 0})
}
}()
}
for range workers {
wg.Add(1)
go func() {
defer wg.Done()
<-start
for range iterations {
_ = cache.NewQuestionSubscriberIDs()
}
}()
}
close(start)
wg.Wait()

cache.SetUserConfig("subscriber", &UserConfig{AllNewQuestions: true})
for _, userID := range cache.NewQuestionSubscriberIDs() {
if userID == "subscriber" {
return
}
}
t.Fatal("subscriber missing from snapshot")
}
7 changes: 1 addition & 6 deletions user-center-slack/notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,7 @@ import (

// GetNewQuestionSubscribers returns the subscribers of the new question notification
func (uc *UserCenter) GetNewQuestionSubscribers() (userIDs []string) {
for userID, conf := range uc.UserConfigCache.userConfigMapping {
if conf.AllNewQuestions {
userIDs = append(userIDs, userID)
}
}
return userIDs
return uc.UserConfigCache.NewQuestionSubscriberIDs()
}

// Notify sends a notification to the user
Expand Down
Loading
Loading