Skip to content

Commit

Permalink
apache#87 view create and get content
Browse files Browse the repository at this point in the history
  • Loading branch information
tianxiaoliang committed Feb 5, 2020
1 parent 014e259 commit 906df8f
Show file tree
Hide file tree
Showing 9 changed files with 406 additions and 7 deletions.
23 changes: 22 additions & 1 deletion deployments/db.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,11 +67,32 @@ db.createCollection( "label", {
}
} }
} );

db.createCollection( "view", {
validator: { $jsonSchema: {
bsonType: "object",
required: [ "id","domain","project","display","criteria" ],
properties: {
id: {
bsonType: "string",
},
domain: {
bsonType: "string"
},
project: {
bsonType: "string"
},
criteria: {
bsonType: "string"
}
}
} }
} );
//index
db.kv.createIndex({"id": 1}, { unique: true } );
db.kv.createIndex({key: 1, label_id: 1,domain:1,project:1},{ unique: true });
db.label.createIndex({"id": 1}, { unique: true } );
db.label.createIndex({format: 1,domain:1,project:1},{ unique: true });
db.view.createIndex({"id": 1}, { unique: true } );
db.view.createIndex({display:1,domain:1,project:1},{ unique: true });
//db config
db.setProfilingLevel(1, {slowms: 80, sampleRate: 1} );
9 changes: 9 additions & 0 deletions pkg/model/db_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,12 @@ type KVDoc struct {
Domain string `json:"domain,omitempty" yaml:"domain,omitempty"` //redundant

}

//ViewDoc is db struct
type ViewDoc struct {
ID string `json:"id,omitempty" bson:"id,omitempty" yaml:"id,omitempty" swag:"string"`
Display string `json:"display,omitempty" yaml:"display,omitempty"`
Project string `json:"project,omitempty" yaml:"project,omitempty"`
Domain string `json:"domain,omitempty" yaml:"domain,omitempty"`
Criteria string `json:"criteria,omitempty" yaml:"criteria,omitempty"`
}
6 changes: 6 additions & 0 deletions pkg/model/kv.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,9 @@ type LabelHistoryResponse struct {
KVs []*KVDoc `json:"data,omitempty"`
Revision int `json:"revision"`
}

//ViewResponse represents the view list
type ViewResponse struct {
Total int `json:"total,omitempty"`
Data []*ViewDoc `json:"data,omitempty"`
}
2 changes: 1 addition & 1 deletion server/handler/noop_auth_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func newDomainResolver() handler.Handler {
return &NoopAuthHandler{}
}

//Name is handler name
//Display is handler name
func (bk *NoopAuthHandler) Name() string {
return "auth-handler"
}
Expand Down
27 changes: 23 additions & 4 deletions server/service/mongo/session/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ const (
CollectionKV = "kv"
CollectionKVRevision = "kv_revision"
CollectionCounter = "counter"

DefaultTimeout = 5 * time.Second
DefaultValueType = "text"
CollectionView = "view"
DefaultTimeout = 5 * time.Second
DefaultValueType = "text"
)

//db errors
Expand All @@ -59,9 +59,14 @@ var (
ErrTooMany = errors.New("key with labels should be only one")
ErrKeyMustNotEmpty = errors.New("must supply key if you want to get exact one result")

ErrKVIDIsNil = errors.New("kvID id is nil")
ErrIDIsNil = errors.New("id is empty")
ErrKvIDAndLabelIDNotMatch = errors.New("kvID and labelID do not match")
ErrRootCAMissing = errors.New("rootCAFile is empty in config file")

ErrViewCreation = errors.New("can not create view")
ErrViewUpdate = errors.New("can not update view")
ErrViewNotExist = errors.New("view not exists")
ErrViewFinding = errors.New("view search error")
)

var client *mongo.Client
Expand Down Expand Up @@ -132,3 +137,17 @@ func Init() error {
func GetDB() *mongo.Database {
return db
}

func CreateView(ctx context.Context, view, source string, pipeline mongo.Pipeline) error {
sr := GetDB().RunCommand(ctx,
bson.D{
{"create", view},
{"viewOn", source},
{"pipeline", pipeline},
})
if sr.Err() != nil {
openlogging.Error("can not create view: " + sr.Err().Error())
return ErrViewCreation
}
return nil
}
58 changes: 58 additions & 0 deletions server/service/mongo/view/view_dao.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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 view

import (
"context"
"github.com/apache/servicecomb-kie/pkg/model"
"github.com/apache/servicecomb-kie/server/service/mongo/session"
"github.com/go-mesh/openlogging"
uuid "github.com/satori/go.uuid"
"go.mongodb.org/mongo-driver/bson"
)

func create(ctx context.Context, viewDoc *model.ViewDoc) error {
viewDoc.ID = uuid.NewV4().String()
viewDoc.Criteria = "" //TODO parse pipe line to sql-like lang
_, err := session.GetDB().Collection(session.CollectionView).InsertOne(ctx, viewDoc)
if err != nil {
openlogging.Error("can not insert view collection: " + err.Error())
return session.ErrViewCreation
}
return nil
}
func findOne(ctx context.Context, viewID, domain, project string) (*model.ViewDoc, error) {
filter := bson.M{"domain": domain,
"project": project,
"id": viewID}
sr := session.GetDB().Collection(session.CollectionView).FindOne(ctx, filter)
if sr.Err() != nil {
openlogging.Error("can not insert view collection: " + sr.Err().Error())
return nil, sr.Err()
}
result := &model.ViewDoc{}
err := sr.Decode(result)
if err != nil {
openlogging.Error("decode error: " + err.Error())
return nil, err
}
if result.ID == viewID {
return result, nil
}
return nil, session.ErrViewNotExist
}
171 changes: 171 additions & 0 deletions server/service/mongo/view/view_service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
/*
* 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 view

import (
"context"
"github.com/apache/servicecomb-kie/pkg/model"
"github.com/apache/servicecomb-kie/server/service"
"github.com/apache/servicecomb-kie/server/service/mongo/session"
"github.com/go-mesh/openlogging"
uuid "github.com/satori/go.uuid"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"time"
)

//Service operate data in mongodb
type Service struct {
timeout time.Duration
}

//Create insert a view data and create a mongo db view
func (s *Service) Create(ctx context.Context, viewDoc *model.ViewDoc, options ...service.FindOption) (*model.ViewDoc, error) {
if viewDoc.Domain == "" {
return nil, session.ErrMissingDomain
}
var pipeline mongo.Pipeline = []bson.D{
{{"$match", bson.D{{"domain", viewDoc.Domain}}}},
{{"$match", bson.D{{"project", viewDoc.Project}}}},
}
opts := service.FindOptions{}
for _, o := range options {
o(&opts)
}
if opts.Key != "" {
pipeline = append(pipeline, bson.D{{"$match", bson.D{{"key", opts.Key}}}})
}
if len(opts.Labels) != 0 {
for k, v := range opts.Labels {
pipeline = append(pipeline, bson.D{{"$match", bson.D{{"labels." + k, v}}}})
}
}
viewDoc.ID = uuid.NewV4().String()
viewDoc.Criteria = "" //TODO parse pipe line to sql-like lang
err := create(ctx, viewDoc)
if err != nil {
openlogging.Error("can not insert view collection: " + err.Error())
return nil, session.ErrViewCreation
}
err = session.CreateView(ctx, generateViewName(viewDoc.ID, viewDoc.Domain, viewDoc.Project), session.CollectionKV, pipeline)
if err != nil {
openlogging.Error("can not create view: " + err.Error())
return nil, session.ErrViewCreation
}
return viewDoc, nil
}

func (s *Service) Update(ctx context.Context, viewDoc *model.ViewDoc) error {
if viewDoc.Domain == "" {
return session.ErrMissingDomain
}
if viewDoc.Project == "" {
return session.ErrMissingProject
}
if viewDoc.ID == "" {
return session.ErrIDIsNil
}
oldView, err := findOne(ctx, viewDoc.ID, viewDoc.Domain, viewDoc.Project)
if err != nil {
return err
}
if viewDoc.Display != "" {
oldView.Display = viewDoc.Display
}
if viewDoc.Criteria != "" {
oldView.Criteria = viewDoc.Criteria
}
_, err = session.GetDB().Collection(session.CollectionView).UpdateOne(ctx, bson.M{"domain": oldView.Domain,
"project": oldView.Project,
"id": oldView.ID},
bson.D{
{"$set", bson.D{
{"name", oldView.Display},
{"criteria", oldView.Criteria},
}},
})
if err != nil {
openlogging.Error("can not update view: " + err.Error())
return session.ErrViewUpdate
}
return nil
}
func (s *Service) List(ctx context.Context, domain, project string, opts ...service.FindOption) (*model.ViewResponse, error) {
option := service.FindOptions{}
for _, o := range opts {
o(&option)
}
collection := session.GetDB().Collection(session.CollectionView)
filter := bson.M{"domain": domain, "project": project}
mOpt := options.Find()
if option.Limit != 0 {
mOpt = mOpt.SetLimit(option.Limit)
}
if option.Offset != 0 {
mOpt = mOpt.SetSkip(option.Offset)
}
cur, err := collection.Find(ctx, filter, mOpt)
if err != nil {
openlogging.Error("can not find view: " + err.Error())
return nil, session.ErrViewFinding
}
result := &model.ViewResponse{}
for cur.Next(ctx) {
v := &model.ViewDoc{}
if err := cur.Decode(v); err != nil {
openlogging.Error("decode error: " + err.Error())
return nil, err
}
result.Data = append(result.Data, v)
}
return result, nil
}
func (s *Service) GetContent(ctx context.Context, id, domain, project string, opts ...service.FindOption) (*model.ViewResponse, error) {
option := service.FindOptions{}
for _, o := range opts {
o(&option)
}
mOpt := options.Find()
if option.Limit != 0 {
mOpt = mOpt.SetLimit(option.Limit)
}
if option.Offset != 0 {
mOpt = mOpt.SetSkip(option.Offset)
}
collection := session.GetDB().Collection(generateViewName(id, domain, project))
cur, err := collection.Find(ctx, bson.D{}, mOpt)
if err != nil {
openlogging.Error("can not find view content: " + err.Error())
return nil, session.ErrViewFinding
}
result := &model.ViewResponse{}
for cur.Next(ctx) {
v := &model.ViewDoc{}
if err := cur.Decode(v); err != nil {
openlogging.Error("decode error: " + err.Error())
return nil, err
}
result.Data = append(result.Data, v)
}
return result, nil
}

func generateViewName(id, domain, project string) string {
return domain + "::" + project + "::" + id
}
Loading

0 comments on commit 906df8f

Please sign in to comment.