fix: resolve im backend issue list regressions

This commit is contained in:
richjohnrambo
2026-09-17 14:59:16 +08:00
parent 760de35e10
commit 50f8581667
13 changed files with 750 additions and 181 deletions
+66 -5
View File
@@ -2,6 +2,9 @@ package store
import (
"context"
"encoding/json"
"strconv"
"strings"
"testing"
"time"
@@ -12,6 +15,7 @@ type testGroupMessageRuntime struct {
claims map[string]*groupMessageUniqueRecord
seqs map[string]int64
shortStates map[string]bool
objects map[string][]byte
deletedPrefixes []string
deletedObjects []string
}
@@ -21,6 +25,7 @@ func newTestGroupMessageRuntime() *testGroupMessageRuntime {
claims: make(map[string]*groupMessageUniqueRecord),
seqs: make(map[string]int64),
shortStates: make(map[string]bool),
objects: make(map[string][]byte),
}
}
@@ -145,21 +150,37 @@ func (r *testGroupMessageRuntime) StartRealtimeFanoutSubscriber(context.Context,
return nil
}
func (r *testGroupMessageRuntime) CacheObject(types.TenantID, string, string, any) error {
func (r *testGroupMessageRuntime) CacheObject(tenantID types.TenantID, namespace, id string, value any) error {
payload, err := json.Marshal(value)
if err != nil {
return err
}
r.objects[strconv.FormatInt(int64(tenantID), 10)+":"+namespace+":"+id] = payload
return nil
}
func (r *testGroupMessageRuntime) GetCachedObject(types.TenantID, string, string, any) (bool, error) {
return false, nil
func (r *testGroupMessageRuntime) GetCachedObject(tenantID types.TenantID, namespace, id string, value any) (bool, error) {
payload, ok := r.objects[strconv.FormatInt(int64(tenantID), 10)+":"+namespace+":"+id]
if !ok {
return false, nil
}
return true, json.Unmarshal(payload, value)
}
func (r *testGroupMessageRuntime) DeleteCachedObject(_ types.TenantID, namespace, id string) error {
func (r *testGroupMessageRuntime) DeleteCachedObject(tenantID types.TenantID, namespace, id string) error {
r.deletedObjects = append(r.deletedObjects, namespace+":"+id)
delete(r.objects, strconv.FormatInt(int64(tenantID), 10)+":"+namespace+":"+id)
return nil
}
func (r *testGroupMessageRuntime) DeleteCachedObjectsByPrefix(_ types.TenantID, _ string, prefix string) error {
func (r *testGroupMessageRuntime) DeleteCachedObjectsByPrefix(tenantID types.TenantID, namespace, prefix string) error {
r.deletedPrefixes = append(r.deletedPrefixes, prefix)
cachePrefix := strconv.FormatInt(int64(tenantID), 10) + ":" + namespace + ":" + prefix
for key := range r.objects {
if strings.HasPrefix(key, cachePrefix) {
delete(r.objects, key)
}
}
return nil
}
@@ -220,6 +241,46 @@ func TestLoginTokenRevocation(t *testing.T) {
}
}
func TestGroupMemberPageCacheRoundTripAndInvalidate(t *testing.T) {
oldRuntime := groupMsgRuntime
runtime := newTestGroupMessageRuntime()
groupMsgRuntime = runtime
t.Cleanup(func() { groupMsgRuntime = oldRuntime })
opts := types.GroupMemberListOptions{
Role: "member",
Query: " alice ",
Cursor: "42",
Limit: 20,
Mentionable: true,
}
key := groupMemberPageCacheID("grpAlpha", opts)
if !strings.HasPrefix(key, "grpAlpha|") {
t.Fatalf("cache key must be topic-prefixed for invalidation: %q", key)
}
CacheGroupMemberPage(7, key, groupMemberPageCache{
Items: []types.GroupMember{{
ID: 43,
Topic: "grpAlpha",
UserID: types.Uid(100),
Role: types.GroupMemberRoleMember,
}},
NextCursor: "43",
})
cached, ok := GetCachedGroupMemberPage(7, key)
if !ok || cached.NextCursor != "43" || len(cached.Items) != 1 || cached.Items[0].UserID != types.Uid(100) {
t.Fatalf("unexpected cached page: ok=%v page=%#v", ok, cached)
}
invalidateGroupMemberPages(7, "grpAlpha")
if _, ok := GetCachedGroupMemberPage(7, key); ok {
t.Fatalf("group member page cache survived invalidation")
}
if len(runtime.deletedPrefixes) != 1 || runtime.deletedPrefixes[0] != "grpAlpha|" {
t.Fatalf("unexpected invalidation prefixes: %#v", runtime.deletedPrefixes)
}
}
func TestRealtimeFanoutDedupClaimIDIsNodeScoped(t *testing.T) {
tenantID := types.TenantID(7)
dedupKey := "data:p2pABC:42"