⚡ Optimize for passive users
✨ Subscribe to channel focused
This commit is contained in:
@ -117,10 +117,6 @@ func NewCall(channel models.Channel, founder models.ChannelMember) (models.Call,
|
||||
if member.ID != call.Founder.ID {
|
||||
pendingUsers = append(pendingUsers, uint64(member.AccountID))
|
||||
}
|
||||
PushCommand(member.AccountID, nex.WebSocketPackage{
|
||||
Action: "calls.new",
|
||||
Payload: call,
|
||||
})
|
||||
}
|
||||
|
||||
channel, _ = GetChannel(channel.ID)
|
||||
@ -131,6 +127,13 @@ func NewCall(channel models.Channel, founder models.ChannelMember) (models.Call,
|
||||
}
|
||||
}
|
||||
|
||||
// The call notification is not happen very often
|
||||
// So we don't need to optimize the performance for passive users
|
||||
PushCommandBatch(pendingUsers, nex.WebSocketPackage{
|
||||
Action: "calls.new",
|
||||
Payload: call,
|
||||
})
|
||||
|
||||
err = authkit.NotifyUserBatch(
|
||||
gap.Nx,
|
||||
pendingUsers,
|
||||
@ -172,12 +175,17 @@ func EndCall(call models.Call) (models.Call, error) {
|
||||
ChannelID: call.ChannelID,
|
||||
}).Find(&members).Error; err == nil {
|
||||
call, _ = GetCall(call.Channel, call.ID)
|
||||
var pendingUsers []uint64
|
||||
for _, member := range members {
|
||||
PushCommand(member.AccountID, nex.WebSocketPackage{
|
||||
Action: "calls.end",
|
||||
Payload: call,
|
||||
})
|
||||
if member.ID != call.Founder.ID {
|
||||
pendingUsers = append(pendingUsers, uint64(member.AccountID))
|
||||
}
|
||||
}
|
||||
|
||||
PushCommandBatch(pendingUsers, nex.WebSocketPackage{
|
||||
Action: "calls.end",
|
||||
Payload: call,
|
||||
})
|
||||
}
|
||||
|
||||
return call, nil
|
||||
|
@ -297,6 +297,8 @@ func EditChannel(channel models.Channel) (models.Channel, error) {
|
||||
|
||||
func DeleteChannel(channel models.Channel) error {
|
||||
if err := database.C.Delete(&channel).Error; err == nil {
|
||||
UnsubscribeAllWithChannels(channel.ID)
|
||||
|
||||
database.C.Where("channel_id = ?", channel.ID).Delete(&models.Event{})
|
||||
|
||||
cacheManager := cache.New[any](localCache.S)
|
||||
|
@ -15,6 +15,7 @@ import (
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/rs/zerolog/log"
|
||||
"github.com/samber/lo"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func CountEvent(channel models.Channel) int64 {
|
||||
@ -89,7 +90,13 @@ func NewEvent(event models.Event) (models.Event, error) {
|
||||
log.Error().Err(err).Msg("Failed to fetch event, the notifying of new event was terminated...")
|
||||
return event, err
|
||||
}
|
||||
idxList := lo.Map(members, func(item models.ChannelMember, index int) uint64 {
|
||||
idxList := lo.Map(lo.Filter(members, func(item models.ChannelMember, index int) bool {
|
||||
if !viper.GetBool("performance.passive_user_optimize") {
|
||||
// Leave this for backward compatibility
|
||||
return true
|
||||
}
|
||||
return CheckSubscribed(item.AccountID, event.ChannelID)
|
||||
}), func(item models.ChannelMember, index int) uint64 {
|
||||
return uint64(item.AccountID)
|
||||
})
|
||||
_ = PushCommandBatch(idxList, nex.WebSocketPackage{
|
||||
@ -120,6 +127,9 @@ func NotifyMessageEvent(members []models.ChannelMember, event models.Event) {
|
||||
var mentionedUsers []uint64
|
||||
|
||||
for _, member := range members {
|
||||
if CheckSubscribed(member.AccountID, event.ChannelID) {
|
||||
continue
|
||||
}
|
||||
if member.ID != event.SenderID {
|
||||
switch member.Notify {
|
||||
case models.NotifyLevelNone:
|
||||
|
@ -3,15 +3,16 @@ package services
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
localCache "git.solsynth.dev/hypernet/messaging/pkg/internal/cache"
|
||||
"git.solsynth.dev/hypernet/messaging/pkg/internal/database"
|
||||
"git.solsynth.dev/hypernet/messaging/pkg/internal/gap"
|
||||
"git.solsynth.dev/hypernet/messaging/pkg/internal/models"
|
||||
"git.solsynth.dev/hypernet/nexus/pkg/nex"
|
||||
"git.solsynth.dev/hypernet/nexus/pkg/proto"
|
||||
"github.com/eko/gocache/lib/v4/cache"
|
||||
"github.com/eko/gocache/lib/v4/marshaler"
|
||||
"github.com/eko/gocache/lib/v4/store"
|
||||
"github.com/samber/lo"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type statusQueryCacheEntry struct {
|
||||
@ -76,14 +77,18 @@ func SetTypingStatus(channelId uint, userId uint) error {
|
||||
)
|
||||
}
|
||||
|
||||
sc := proto.NewStreamServiceClient(gap.Nx.GetNexusGrpcConn())
|
||||
_, err := sc.PushStreamBatch(context.Background(), &proto.PushStreamBatchRequest{
|
||||
UserId: broadcastTarget,
|
||||
Body: nex.WebSocketPackage{
|
||||
Action: "status.typing",
|
||||
Payload: data,
|
||||
}.Marshal(),
|
||||
broadcastTarget = lo.Filter(broadcastTarget, func(item uint64, index int) bool {
|
||||
if !viper.GetBool("performance.passive_user_optimize") {
|
||||
// Leave this for backward compatibility
|
||||
return true
|
||||
}
|
||||
return CheckSubscribed(uint(item), channelId)
|
||||
})
|
||||
|
||||
return err
|
||||
PushCommandBatch(broadcastTarget, nex.WebSocketPackage{
|
||||
Action: "status.typing",
|
||||
Payload: data,
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
51
pkg/internal/services/subscribe.go
Normal file
51
pkg/internal/services/subscribe.go
Normal file
@ -0,0 +1,51 @@
|
||||
package services
|
||||
|
||||
import "sync"
|
||||
|
||||
// ChannelID -> UserID
|
||||
var subscribeInfo = make(map[uint]map[uint]bool)
|
||||
var subscribeLock sync.Mutex
|
||||
|
||||
// If user subscribed to a channel
|
||||
// Push the new message to them via websocket
|
||||
// And skip the notification
|
||||
|
||||
func CheckSubscribed(UserID uint, ChannelID uint) bool {
|
||||
if _, ok := subscribeInfo[ChannelID]; ok {
|
||||
if _, ok := subscribeInfo[ChannelID][UserID]; ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func SubscribeChannel(userId uint, channelId uint) {
|
||||
subscribeLock.Lock()
|
||||
defer subscribeLock.Unlock()
|
||||
if _, ok := subscribeInfo[channelId]; !ok {
|
||||
subscribeInfo[channelId] = make(map[uint]bool)
|
||||
}
|
||||
subscribeInfo[channelId][userId] = true
|
||||
}
|
||||
|
||||
func UnsubscribeChannel(userId uint, channelId uint) {
|
||||
subscribeLock.Lock()
|
||||
defer subscribeLock.Unlock()
|
||||
if _, ok := subscribeInfo[channelId]; ok {
|
||||
delete(subscribeInfo[channelId], userId)
|
||||
}
|
||||
}
|
||||
|
||||
func UnsubscribeAll(userId uint) {
|
||||
subscribeLock.Lock()
|
||||
defer subscribeLock.Unlock()
|
||||
for _, v := range subscribeInfo {
|
||||
delete(v, userId)
|
||||
}
|
||||
}
|
||||
|
||||
func UnsubscribeAllWithChannels(channelId uint) {
|
||||
subscribeLock.Lock()
|
||||
defer subscribeLock.Unlock()
|
||||
delete(subscribeInfo, channelId)
|
||||
}
|
Reference in New Issue
Block a user