Skip to content

Commit 756c945

Browse files
authored
test:add unit test for service visible feature (polarismesh#1309)
1 parent dfa9741 commit 756c945

File tree

11 files changed

+359
-26
lines changed

11 files changed

+359
-26
lines changed

cache/api/funcs.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,11 @@ func ComputeRevisionBySlice(h hash.Hash, slice []string) (string, error) {
4848

4949
// CompositeComputeRevision 将多个 revision 合并计算为一个
5050
func CompositeComputeRevision(revisions []string) (string, error) {
51-
h := sha1.New()
51+
if len(revisions) == 1 {
52+
return revisions[0], nil
53+
}
5254

55+
h := sha1.New()
5356
sort.Strings(revisions)
5457

5558
for i := range revisions {

cache/service/instance.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ func fillInternalLabels(item *model.Instance) *model.Instance {
363363
func (ic *instanceCache) postProcessUpdatedServices(affect map[string]bool) {
364364
progress := 0
365365
for serviceID := range affect {
366-
ic.svcCache.GetRevisionWorker().Notify(serviceID, true)
366+
ic.svcCache.notifyRevisionWorker(serviceID, true)
367367
progress++
368368
if progress%10000 == 0 {
369369
log.Infof("[Cache][Instance] revision notify progress(%d / %d)", progress, len(affect))

cache/service/service.go

+27-6
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ type serviceCache struct {
7676
exportNamespace *utils.SyncMap[string, *utils.SyncSet[string]]
7777
// exportServices 某个服务对部分命名空间全部可见 exportNamespace -> svcName -> model.Service
7878
exportServices *utils.SyncMap[string, *utils.SyncMap[string, *model.Service]]
79+
80+
subCtx *eventhub.SubscribtionContext
7981
}
8082

8183
// NewServiceCache 返回一个serviceCache
@@ -98,14 +100,18 @@ func (sc *serviceCache) Initialize(opt map[string]interface{}) error {
98100
sc.cl5Names = utils.NewSyncMap[string, *model.Service]()
99101
sc.pendingServices = utils.NewSyncMap[string, struct{}]()
100102
sc.namespaceServiceCnt = utils.NewSyncMap[string, *model.NamespaceServiceCount]()
101-
sc.revisionWorker = newRevisionWorker(sc, sc.instCache.(*instanceCache), opt)
102103
sc.exportNamespace = utils.NewSyncMap[string, *utils.SyncSet[string]]()
103104
sc.exportServices = utils.NewSyncMap[string, *utils.SyncMap[string, *model.Service]]()
104-
105105
ctx, cancel := context.WithCancel(context.Background())
106106
sc.cancel = cancel
107+
sc.revisionWorker = newRevisionWorker(sc, sc.instCache.(*instanceCache), opt)
107108
// 先启动revision计算协程
108109
go sc.revisionWorker.revisionWorker(ctx)
110+
subCtx, err := eventhub.SubscribeWithFunc(eventhub.CacheNamespaceEventTopic, sc.handleNamespaceChange)
111+
if err != nil {
112+
return err
113+
}
114+
sc.subCtx = subCtx
109115
if opt == nil {
110116
return nil
111117
}
@@ -119,6 +125,9 @@ func (sc *serviceCache) Close() error {
119125
if err := sc.BaseCache.Close(); err != nil {
120126
return err
121127
}
128+
if sc.subCtx != nil {
129+
sc.subCtx.Cancel()
130+
}
122131
if sc.cancel != nil {
123132
sc.cancel()
124133
}
@@ -413,27 +422,30 @@ func (sc *serviceCache) setServices(services map[string]*model.Service) (map[str
413422
if service.IsAlias() {
414423
aliases = append(aliases, service)
415424
}
425+
oldVal, exist := sc.ids.Load(service.ID)
426+
if oldVal != nil {
427+
service.OldExportTo = oldVal.ExportTo
428+
}
416429

417430
spaceName := service.Namespace
418431
changeNs[spaceName] = struct{}{}
419432
// 发现有删除操作
420433
if !service.Valid {
421434
sc.removeServices(service)
422-
sc.revisionWorker.Notify(service.ID, false)
435+
sc.notifyRevisionWorker(service.ID, false)
423436
del++
424437
svcCount--
425438
continue
426439
}
427440

428441
update++
429-
_, exist := sc.ids.Load(service.ID)
430442
if !exist {
431443
svcCount++
432444
}
433445

434446
sc.ids.Store(service.ID, service)
435447
sc.serviceList.addService(service)
436-
sc.revisionWorker.Notify(service.ID, true)
448+
sc.notifyRevisionWorker(service.ID, true)
437449

438450
spaces, ok := sc.names.Load(spaceName)
439451
if !ok {
@@ -455,6 +467,7 @@ func (sc *serviceCache) setServices(services map[string]*model.Service) (map[str
455467

456468
sc.postProcessServiceAlias(aliases)
457469
sc.postProcessUpdatedServices(changeNs)
470+
sc.postProcessServiceExports(services)
458471
sc.serviceList.reloadRevision()
459472
return map[string]time.Time{
460473
sc.Name(): time.Unix(lastMtime, 0),
@@ -633,7 +646,7 @@ func (sc *serviceCache) GetVisibleServicesInOtherNamespace(svcName, namespace st
633646
return visibleServices
634647
}
635648

636-
func (sc *serviceCache) postProcessServiceExports(services []*model.Service) {
649+
func (sc *serviceCache) postProcessServiceExports(services map[string]*model.Service) {
637650

638651
for i := range services {
639652
svc := services[i]
@@ -680,6 +693,14 @@ func (sc *serviceCache) handleNamespaceChange(ctx context.Context, args interfac
680693
return nil
681694
}
682695

696+
func (sc *serviceCache) notifyRevisionWorker(serviceID string, valid bool) {
697+
revisionWorker := sc.revisionWorker
698+
if revisionWorker == nil {
699+
return
700+
}
701+
revisionWorker.Notify(serviceID, valid)
702+
}
703+
683704
// GetRevisionWorker
684705
func (sc *serviceCache) GetRevisionWorker() types.ServiceRevisionWorker {
685706
return sc.revisionWorker

cache/service/service_test.go

+120
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package service
1919

2020
import (
21+
"context"
2122
"fmt"
2223
"math/rand"
2324
"reflect"
@@ -30,6 +31,7 @@ import (
3031

3132
types "github.com/polarismesh/polaris/cache/api"
3233
cachemock "github.com/polarismesh/polaris/cache/mock"
34+
"github.com/polarismesh/polaris/common/eventhub"
3335
"github.com/polarismesh/polaris/common/model"
3436
"github.com/polarismesh/polaris/common/utils"
3537
"github.com/polarismesh/polaris/store"
@@ -593,3 +595,121 @@ func TestComputeRevision(t *testing.T) {
593595
assert.NotEqual(t, lhs, rhs)
594596
})
595597
}
598+
599+
func Test_serviceCache_GetVisibleServicesInOtherNamespace(t *testing.T) {
600+
ctl := gomock.NewController(t)
601+
storage := mock.NewMockStore(ctl)
602+
mockCacheMgr := cachemock.NewMockCacheManager(ctl)
603+
defer ctl.Finish()
604+
605+
t.Run("服务可见性查询判断", func(t *testing.T) {
606+
serviceList := map[string]*model.Service{
607+
"service-1": {
608+
ID: "service-1",
609+
Name: "service-1",
610+
Namespace: "ns-1",
611+
ExportTo: map[string]struct{}{
612+
"ns-2": {},
613+
},
614+
Valid: true,
615+
},
616+
"service-2": {
617+
ID: "service-2",
618+
Name: "service-2",
619+
Namespace: "ns-2",
620+
ExportTo: map[string]struct{}{},
621+
Valid: true,
622+
},
623+
"service-3": {
624+
ID: "service-3",
625+
Name: "service-3",
626+
Namespace: "ns-3",
627+
ExportTo: map[string]struct{}{
628+
"ns-2": {},
629+
},
630+
Valid: true,
631+
},
632+
}
633+
634+
svcCache := NewServiceCache(storage, mockCacheMgr).(*serviceCache)
635+
mockInstCache := NewInstanceCache(storage, mockCacheMgr)
636+
mockCacheMgr.EXPECT().GetCacher(types.CacheInstance).Return(mockInstCache).AnyTimes()
637+
mockCacheMgr.EXPECT().GetCacher(types.CacheService).Return(svcCache).AnyTimes()
638+
_ = svcCache.Initialize(map[string]interface{}{})
639+
_ = mockInstCache.Initialize(map[string]interface{}{})
640+
t.Cleanup(func() {
641+
_ = svcCache.Close()
642+
_ = mockInstCache.Close()
643+
})
644+
645+
_, _, _ = svcCache.setServices(serviceList)
646+
visibles := svcCache.GetVisibleServicesInOtherNamespace("service-1", "ns-2")
647+
assert.Equal(t, 1, len(visibles))
648+
assert.Equal(t, "ns-1", visibles[0].Namespace)
649+
})
650+
651+
t.Run("服务可见性查询判断", func(t *testing.T) {
652+
serviceList := map[string]*model.Service{
653+
"service-1": {
654+
ID: "service-1",
655+
Name: "service-1",
656+
Namespace: "ns-1",
657+
Valid: true,
658+
},
659+
"service-2": {
660+
ID: "service-2",
661+
Name: "service-2",
662+
Namespace: "ns-2",
663+
Valid: true,
664+
},
665+
"service-3": {
666+
ID: "service-3",
667+
Name: "service-3",
668+
Namespace: "ns-3",
669+
Valid: true,
670+
},
671+
"service-4": {
672+
ID: "service-4",
673+
Name: "service-4",
674+
Namespace: "ns-4",
675+
Valid: true,
676+
},
677+
}
678+
679+
svcCache := NewServiceCache(storage, mockCacheMgr).(*serviceCache)
680+
mockInstCache := NewInstanceCache(storage, mockCacheMgr)
681+
mockCacheMgr.EXPECT().GetCacher(types.CacheInstance).Return(mockInstCache).AnyTimes()
682+
mockCacheMgr.EXPECT().GetCacher(types.CacheService).Return(svcCache).AnyTimes()
683+
_ = svcCache.Initialize(map[string]interface{}{})
684+
_ = mockInstCache.Initialize(map[string]interface{}{})
685+
t.Cleanup(func() {
686+
_ = svcCache.Close()
687+
_ = mockInstCache.Close()
688+
})
689+
690+
_, _, _ = svcCache.setServices(serviceList)
691+
692+
svcCache.handleNamespaceChange(context.Background(), &eventhub.CacheNamespaceEvent{
693+
EventType: eventhub.EventCreated,
694+
Item: &model.Namespace{
695+
Name: "ns-1",
696+
ServiceExportTo: map[string]struct{}{
697+
"ns-2": {},
698+
"ns-3": {},
699+
},
700+
},
701+
})
702+
703+
visibles := svcCache.GetVisibleServicesInOtherNamespace("service-1", "ns-2")
704+
assert.Equal(t, 1, len(visibles))
705+
assert.Equal(t, "ns-1", visibles[0].Namespace)
706+
707+
visibles = svcCache.GetVisibleServicesInOtherNamespace("service-1", "ns-3")
708+
assert.Equal(t, 1, len(visibles))
709+
assert.Equal(t, "ns-1", visibles[0].Namespace)
710+
711+
visibles = svcCache.GetVisibleServicesInOtherNamespace("service-1", "ns-4")
712+
assert.Equal(t, 0, len(visibles))
713+
})
714+
715+
}

common/model/naming.go

+8
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ import (
3434
"github.com/polarismesh/polaris/common/utils"
3535
)
3636

37+
func ExportToMap(exportTo []*wrappers.StringValue) map[string]struct{} {
38+
ret := make(map[string]struct{})
39+
for _, v := range exportTo {
40+
ret[v.Value] = struct{}{}
41+
}
42+
return ret
43+
}
44+
3745
// Namespace 命名空间结构体
3846
type Namespace struct {
3947
Name string

namespace/namespace.go

+13-5
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,12 @@ func (s *Server) CreateNamespace(ctx context.Context, req *apimodel.Namespace) *
140140
*/
141141
func (s *Server) createNamespaceModel(req *apimodel.Namespace) *model.Namespace {
142142
namespace := &model.Namespace{
143-
Name: req.GetName().GetValue(),
144-
Comment: req.GetComment().GetValue(),
145-
Owner: req.GetOwners().GetValue(),
146-
Token: utils.NewUUID(),
143+
Name: req.GetName().GetValue(),
144+
Comment: req.GetComment().GetValue(),
145+
Owner: req.GetOwners().GetValue(),
146+
Token: utils.NewUUID(),
147+
ServiceExportTo: model.ExportToMap(req.GetServiceExportTo()),
147148
}
148-
149149
return namespace
150150
}
151151

@@ -298,6 +298,13 @@ func (s *Server) updateNamespaceAttribute(req *apimodel.Namespace, namespace *mo
298298
if req.GetOwners() != nil {
299299
namespace.Owner = req.GetOwners().GetValue()
300300
}
301+
302+
exportTo := map[string]struct{}{}
303+
for i := range req.GetServiceExportTo() {
304+
exportTo[req.GetServiceExportTo()[i].GetValue()] = struct{}{}
305+
}
306+
307+
namespace.ServiceExportTo = exportTo
301308
}
302309

303310
// UpdateNamespaceToken 更新命名空间token
@@ -360,6 +367,7 @@ func (s *Server) GetNamespaces(ctx context.Context, query map[string][]string) *
360367
TotalServiceCount: utils.NewUInt32Value(nsCntInfo.ServiceCount),
361368
TotalInstanceCount: utils.NewUInt32Value(nsCntInfo.InstanceCnt.TotalInstanceCount),
362369
TotalHealthInstanceCount: utils.NewUInt32Value(nsCntInfo.InstanceCnt.HealthyInstanceCount),
370+
ServiceExportTo: namespace.ListServiceExportTo(),
363371
})
364372
totalServiceCount += nsCntInfo.ServiceCount
365373
totalInstanceCount += nsCntInfo.InstanceCnt.TotalInstanceCount

service/client_v1.go

+23-4
Original file line numberDiff line numberDiff line change
@@ -205,14 +205,12 @@ func (s *Server) ServiceInstancesCache(ctx context.Context, filter *apiservice.D
205205
}
206206

207207
// 数据源都来自Cache,这里拿到的service,已经是源服务
208-
aliasFor := s.getServiceCache(serviceName, namespaceName)
209-
if aliasFor == nil {
208+
aliasFor, visibleServices := s.findVisibleServices(serviceName, namespaceName, req)
209+
if len(visibleServices) == 0 {
210210
log.Infof("[Server][Service][Instance] not found name(%s) namespace(%s) service",
211211
serviceName, namespaceName)
212212
return api.NewDiscoverInstanceResponse(apimodel.Code_NotFoundResource, req)
213213
}
214-
visibleServices := s.caches.Service().GetVisibleServicesInOtherNamespace(aliasFor.Name, aliasFor.Namespace)
215-
visibleServices = append(visibleServices, aliasFor)
216214

217215
revisions := make([]string, 0, len(visibleServices)+1)
218216
finalInstances := make(map[string]*apiservice.Instance, 128)
@@ -264,6 +262,27 @@ func (s *Server) ServiceInstancesCache(ctx context.Context, filter *apiservice.D
264262
return resp
265263
}
266264

265+
func (s *Server) findVisibleServices(serviceName, namespaceName string, req *apiservice.Service) (*model.Service, []*model.Service) {
266+
visibleServices := make([]*model.Service, 0, 4)
267+
// 数据源都来自Cache,这里拿到的service,已经是源服务
268+
aliasFor := s.getServiceCache(serviceName, namespaceName)
269+
if aliasFor == nil {
270+
aliasFor = &model.Service{
271+
Name: serviceName,
272+
Namespace: namespaceName,
273+
}
274+
ret := s.caches.Service().GetVisibleServicesInOtherNamespace(serviceName, namespaceName)
275+
if len(ret) == 0 {
276+
return nil, nil
277+
}
278+
visibleServices = append(visibleServices, ret...)
279+
} else {
280+
visibleServices = append(visibleServices, aliasFor)
281+
}
282+
283+
return aliasFor, visibleServices
284+
}
285+
267286
// GetRoutingConfigWithCache 获取缓存中的路由配置信息
268287
func (s *Server) GetRoutingConfigWithCache(ctx context.Context, req *apiservice.Service) *apiservice.DiscoverResponse {
269288
resp := createCommonDiscoverResponse(req, apiservice.DiscoverResponse_ROUTING)

0 commit comments

Comments
 (0)