fix: sync contact phone privacy disclosure
This commit is contained in:
parent
0e2fcdf9c8
commit
e1a95c7318
19 changed files with 789 additions and 50 deletions
|
|
@ -81,6 +81,31 @@ func (c *CachedPrivacyStore) SetPrivacyRules(ctx context.Context, rules domain.P
|
|||
return err
|
||||
}
|
||||
c.InvalidateOwners(rules.OwnerUserID)
|
||||
// 数据写入已提交,预热失败不能伪装成写失败;LISTEN/NOTIFY 也会在每个
|
||||
// 实例上再次失效并预热,覆盖本实例通知晚于这里到达的时序。
|
||||
_ = c.WarmOwners(ctx, rules.OwnerUserID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// WarmOwners 在低频写/变更通知路径一次性装入 owner 的完整规则集。调用方必须先
|
||||
// InvalidateOwners;epoch 保证预热期间若又发生失效,不会把旧快照写回。
|
||||
func (c *CachedPrivacyStore) WarmOwners(ctx context.Context, ownerUserIDs ...int64) error {
|
||||
owners := dedupPrivacyOwnerIDs(ownerUserIDs)
|
||||
if len(owners) == 0 || c == nil || c.cache == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 隐私规则变更很少、读取极热。必须重建全部 key,
|
||||
// 不能只塞本次 key,否则会把 owner 的其它持久规则误当成默认规则。
|
||||
loadEpoch := c.cache.LoadEpoch()
|
||||
list, err := c.inner.ListPrivacyRules(ctx, owners, allPrivacyRuleKeys)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
snapshots := buildPrivacyRulesByOwner(list, owners)
|
||||
for _, ownerUserID := range owners {
|
||||
c.cache.StoreIfEpoch(ownerUserID, snapshots[ownerUserID], loadEpoch)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ func TestCachedPrivacyStoreUsesOwnerSnapshot(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestCachedPrivacyStoreInvalidatesOnSet(t *testing.T) {
|
||||
func TestCachedPrivacyStoreWarmsCompleteOwnerSnapshotOnSet(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
base := memory.NewPrivacyStore()
|
||||
counting := &countingPrivacyStore{PrivacyStore: base}
|
||||
|
|
@ -121,24 +121,34 @@ func TestCachedPrivacyStoreInvalidatesOnSet(t *testing.T) {
|
|||
t.Fatalf("set first: %v", err)
|
||||
}
|
||||
if _, ok, err := cached.GetPrivacyRules(ctx, 1001, domain.PrivacyKeyPhoneNumber); err != nil || !ok {
|
||||
t.Fatalf("prime get ok=%v err=%v", ok, err)
|
||||
t.Fatalf("first memory get ok=%v err=%v", ok, err)
|
||||
}
|
||||
if err := cached.SetPrivacyRules(ctx, domain.PrivacyRules{
|
||||
OwnerUserID: 1001,
|
||||
Key: domain.PrivacyKeyPhoneNumber,
|
||||
Rules: []domain.PrivacyRule{{Kind: domain.PrivacyRuleAllowAll}},
|
||||
Key: domain.PrivacyKeyProfilePhoto,
|
||||
Rules: []domain.PrivacyRule{{Kind: domain.PrivacyRuleDisallowAll}},
|
||||
}); err != nil {
|
||||
t.Fatalf("set second: %v", err)
|
||||
}
|
||||
got, ok, err := cached.GetPrivacyRules(ctx, 1001, domain.PrivacyKeyPhoneNumber)
|
||||
if err != nil || !ok {
|
||||
t.Fatalf("after invalidation get ok=%v err=%v", ok, err)
|
||||
t.Fatalf("phone after second set ok=%v err=%v", ok, err)
|
||||
}
|
||||
if got.Rules[0].Kind != domain.PrivacyRuleAllowAll {
|
||||
t.Fatalf("rules after invalidation = %+v, want allow all", got.Rules)
|
||||
if got.Rules[0].Kind != domain.PrivacyRuleDisallowAll {
|
||||
t.Fatalf("phone rules after second set = %+v, want disallow all", got.Rules)
|
||||
}
|
||||
photo, ok, err := cached.GetPrivacyRules(ctx, 1001, domain.PrivacyKeyProfilePhoto)
|
||||
if err != nil || !ok {
|
||||
t.Fatalf("photo after second set ok=%v err=%v", ok, err)
|
||||
}
|
||||
if photo.Rules[0].Kind != domain.PrivacyRuleDisallowAll {
|
||||
t.Fatalf("photo rules after second set = %+v, want disallow all", photo.Rules)
|
||||
}
|
||||
if counting.setCalls != 2 {
|
||||
t.Fatalf("SetPrivacyRules calls = %d, want 2", counting.setCalls)
|
||||
}
|
||||
if counting.listCalls != 2 {
|
||||
t.Fatalf("ListPrivacyRules calls = %d, want 2 after invalidation", counting.listCalls)
|
||||
t.Fatalf("ListPrivacyRules calls = %d, want exactly one write-path warm per set and no read-path query", counting.listCalls)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue