2024-08-23 11:32:24 +00:00
|
|
|
package services
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"git.solsynth.dev/hydrogen/dealer/pkg/hyper"
|
|
|
|
"git.solsynth.dev/hydrogen/dealer/pkg/proto"
|
2024-09-22 06:20:04 +00:00
|
|
|
localCache "git.solsynth.dev/hydrogen/messaging/pkg/internal/cache"
|
2024-08-23 11:32:24 +00:00
|
|
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/database"
|
|
|
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/gap"
|
|
|
|
"git.solsynth.dev/hydrogen/messaging/pkg/internal/models"
|
2024-09-22 06:20:04 +00:00
|
|
|
"github.com/eko/gocache/lib/v4/cache"
|
|
|
|
"github.com/eko/gocache/lib/v4/marshaler"
|
|
|
|
"github.com/eko/gocache/lib/v4/store"
|
2024-08-23 11:32:24 +00:00
|
|
|
)
|
|
|
|
|
2024-08-23 13:58:40 +00:00
|
|
|
type statusQueryCacheEntry struct {
|
2024-08-23 14:26:54 +00:00
|
|
|
Target []uint64
|
|
|
|
Data any
|
2024-08-23 13:58:40 +00:00
|
|
|
}
|
|
|
|
|
2024-09-22 06:20:04 +00:00
|
|
|
func GetTypingStatusQueryCacheKey(channelId uint, userId uint) string {
|
|
|
|
return fmt.Sprintf("typing-status-query#%d;%d", channelId, userId)
|
|
|
|
}
|
2024-08-23 13:58:40 +00:00
|
|
|
|
2024-08-23 11:32:24 +00:00
|
|
|
func SetTypingStatus(channelId uint, userId uint) error {
|
2024-08-23 14:26:54 +00:00
|
|
|
var broadcastTarget []uint64
|
|
|
|
var data any
|
2024-08-23 13:58:40 +00:00
|
|
|
|
2024-09-22 06:20:04 +00:00
|
|
|
cacheManager := cache.New[any](localCache.S)
|
|
|
|
marshal := marshaler.New(cacheManager)
|
|
|
|
contx := context.Background()
|
|
|
|
|
2024-08-23 14:26:54 +00:00
|
|
|
hitCache := false
|
2024-09-22 06:20:04 +00:00
|
|
|
if val, err := marshal.Get(contx, GetTypingStatusQueryCacheKey(channelId, userId), new(statusQueryCacheEntry)); err == nil {
|
2024-10-09 15:56:24 +00:00
|
|
|
entry := val.(*statusQueryCacheEntry)
|
2024-09-22 06:20:04 +00:00
|
|
|
broadcastTarget = entry.Target
|
|
|
|
data = entry.Data
|
|
|
|
hitCache = true
|
2024-08-23 14:26:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if !hitCache {
|
|
|
|
var account models.Account
|
2024-08-23 13:58:40 +00:00
|
|
|
if err := database.C.Where("external_id = ?", userId).First(&account).Error; err != nil {
|
|
|
|
return fmt.Errorf("account not found: %v", err)
|
|
|
|
}
|
2024-08-23 11:32:24 +00:00
|
|
|
|
2024-08-23 14:26:54 +00:00
|
|
|
var member models.ChannelMember
|
2024-08-23 13:58:40 +00:00
|
|
|
if err := database.C.
|
|
|
|
Where("account_id = ? AND channel_id = ?", account.ID, channelId).
|
|
|
|
First(&member).Error; err != nil {
|
|
|
|
return fmt.Errorf("channel member not found: %v", err)
|
|
|
|
} else {
|
|
|
|
member.Account = account
|
|
|
|
}
|
|
|
|
|
2024-08-23 14:26:54 +00:00
|
|
|
var channel models.Channel
|
2024-08-23 13:58:40 +00:00
|
|
|
if err := database.C.
|
|
|
|
Preload("Members").
|
2024-08-23 15:00:49 +00:00
|
|
|
Preload("Members.Account").
|
2024-08-23 13:58:40 +00:00
|
|
|
Where("id = ?", channelId).
|
|
|
|
First(&channel).Error; err != nil {
|
|
|
|
return fmt.Errorf("channel not found: %v", err)
|
|
|
|
}
|
|
|
|
|
2024-08-23 14:26:54 +00:00
|
|
|
for _, item := range channel.Members {
|
2024-09-11 15:54:18 +00:00
|
|
|
broadcastTarget = append(broadcastTarget, uint64(item.Account.ID))
|
2024-08-23 14:26:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
data = map[string]any{
|
|
|
|
"user_id": userId,
|
|
|
|
"member_id": member.ID,
|
|
|
|
"channel_id": channelId,
|
|
|
|
"member": member,
|
|
|
|
"channel": channel,
|
|
|
|
}
|
|
|
|
|
2024-08-23 13:58:40 +00:00
|
|
|
// Cache queries
|
2024-09-22 06:20:04 +00:00
|
|
|
cacheManager := cache.New[any](localCache.S)
|
|
|
|
marshal := marshaler.New(cacheManager)
|
|
|
|
contx := context.Background()
|
|
|
|
|
|
|
|
marshal.Set(
|
|
|
|
contx,
|
|
|
|
GetTypingStatusQueryCacheKey(channelId, userId),
|
|
|
|
statusQueryCacheEntry{broadcastTarget, data},
|
|
|
|
store.WithTags([]string{"typing-status-query", fmt.Sprintf("channel#%d", channelId), fmt.Sprintf("user#%d", userId)}),
|
|
|
|
)
|
2024-08-23 11:32:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sc := proto.NewStreamControllerClient(gap.H.GetDealerGrpcConn())
|
|
|
|
_, err := sc.PushStreamBatch(context.Background(), &proto.PushStreamBatchRequest{
|
2024-08-23 13:01:47 +00:00
|
|
|
UserId: broadcastTarget,
|
2024-08-23 11:32:24 +00:00
|
|
|
Body: hyper.NetworkPackage{
|
2024-08-23 14:26:54 +00:00
|
|
|
Action: "status.typing",
|
|
|
|
Payload: data,
|
2024-08-23 11:32:24 +00:00
|
|
|
}.Marshal(),
|
|
|
|
})
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|