datasource/mongo/sd/dep_cache.go (130 lines of code) (raw):
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package sd
import (
"reflect"
"strings"
cmap "github.com/orcaman/concurrent-map"
"go.mongodb.org/mongo-driver/bson"
"github.com/apache/servicecomb-service-center/datasource/mongo/model"
"github.com/apache/servicecomb-service-center/datasource/sdcommon"
)
type depStore struct {
dirty bool
// the key is documentID, is value is mongo document.
concurrentMap cmap.ConcurrentMap
// the key is generated by indexFuncs,the value is a set of documentID.
indexSets IndexCache
}
func init() {
RegisterCacher(dep, newDepStore)
DepIndexCols = NewIndexCols()
DepIndexCols.AddIndexFunc(depIndex)
DepIndexCols.AddIndexFunc(depVersionIndex)
}
func newDepStore() *MongoCacher {
options := DefaultOptions().SetTable(dep)
cache := &depStore{
dirty: false,
concurrentMap: cmap.New(),
indexSets: NewIndexCache(),
}
depUnmarshal := func(doc bson.Raw) (resource sdcommon.Resource) {
docID := MongoDocument{}
err := bson.Unmarshal(doc, &docID)
if err != nil {
return
}
dep := model.DependencyRule{}
err = bson.Unmarshal(doc, &dep)
if err != nil {
return
}
resource.Value = dep
resource.Key = docID.ID.Hex()
return
}
return NewMongoCacher(options, cache, depUnmarshal)
}
func (s *depStore) Name() string {
return dep
}
func (s *depStore) Size() int {
return s.concurrentMap.Count()
}
func (s *depStore) Get(key string) interface{} {
if v, exist := s.concurrentMap.Get(key); exist {
return v
}
return nil
}
func (s *depStore) ForEach(iter func(k string, v interface{}) (next bool)) {
for k, v := range s.concurrentMap.Items() {
if !iter(k, v) {
break
}
}
}
func (s *depStore) GetValue(index string) []interface{} {
docs := s.indexSets.Get(index)
res := make([]interface{}, 0, len(docs))
for _, id := range docs {
if doc, exist := s.concurrentMap.Get(id); exist {
res = append(res, doc)
}
}
return res
}
func (s *depStore) Dirty() bool {
return s.dirty
}
func (s *depStore) MarkDirty() {
s.dirty = true
}
func (s *depStore) Clear() {
s.dirty = false
s.concurrentMap.Clear()
s.indexSets.Clear()
}
func (s *depStore) ProcessUpdate(event MongoEvent) {
dep, ok := event.Value.(model.DependencyRule)
if !ok {
return
}
if dep.ServiceKey == nil {
return
}
// set the document data.
s.concurrentMap.Set(event.DocumentID, event.Value)
for _, index := range DepIndexCols.GetIndexes(dep) {
// set the index sets.
s.indexSets.Put(index, event.DocumentID)
}
}
func (s *depStore) ProcessDelete(event MongoEvent) {
depData, ok := s.concurrentMap.Get(event.DocumentID)
if !ok {
return
}
dep := depData.(model.DependencyRule)
if dep.ServiceKey == nil {
return
}
s.concurrentMap.Remove(event.DocumentID)
for _, index := range DepIndexCols.GetIndexes(dep) {
s.indexSets.Delete(index, event.DocumentID)
}
}
func (s *depStore) isValueNotUpdated(value interface{}, newValue interface{}) bool {
newDep, ok := newValue.(model.DependencyRule)
if !ok {
return true
}
oldDep, ok := value.(model.DependencyRule)
if !ok {
return true
}
return reflect.DeepEqual(newDep, oldDep)
}
func depIndex(data interface{}) string {
dep := data.(model.DependencyRule)
return strings.Join([]string{dep.Type, dep.ServiceKey.AppId, dep.ServiceKey.ServiceName, dep.ServiceKey.Version}, "/")
}
func depVersionIndex(data interface{}) string {
dep := data.(model.DependencyRule)
return strings.Join([]string{dep.Type, dep.ServiceKey.AppId, dep.ServiceKey.ServiceName}, "/")
}