| /* |
| * 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 main |
| |
| import ( |
| "context" |
| "errors" |
| "fmt" |
| "sync" |
| "time" |
| ) |
| |
| import ( |
| hessian "github.com/apache/dubbo-go-hessian2" |
| "github.com/apache/dubbo-go/config" |
| ) |
| |
| func init() { |
| config.SetProviderService(new(StudentProvider)) |
| // ------for hessian2------ |
| hessian.RegisterPOJO(&Student{}) |
| |
| studentCache = &StudentDB{ |
| nameIndex: make(map[string]*Student, 16), |
| codeIndex: make(map[int64]*Student, 16), |
| lock: sync.Mutex{}, |
| } |
| |
| studentCache.Add(&Student{ID: "0001", Code: 1, Name: "tc-student", Age: 18, Time: time.Now()}) |
| studentCache.Add(&Student{ID: "0002", Code: 2, Name: "ic-student", Age: 88, Time: time.Now()}) |
| } |
| |
| var studentCache *StudentDB |
| |
| // StudentDB cache student. |
| type StudentDB struct { |
| // key is name, value is student obj |
| nameIndex map[string]*Student |
| // key is code, value is student obj |
| codeIndex map[int64]*Student |
| lock sync.Mutex |
| } |
| |
| // nolint |
| func (db *StudentDB) Add(u *Student) bool { |
| db.lock.Lock() |
| defer db.lock.Unlock() |
| |
| if u.Name == "" || u.Code <= 0 { |
| return false |
| } |
| |
| if !db.existName(u.Name) && !db.existCode(u.Code) { |
| return db.AddForName(u) && db.AddForCode(u) |
| } |
| |
| return false |
| } |
| |
| // nolint |
| func (db *StudentDB) AddForName(u *Student) bool { |
| if len(u.Name) == 0 { |
| return false |
| } |
| |
| if _, ok := db.nameIndex[u.Name]; ok { |
| return false |
| } |
| |
| db.nameIndex[u.Name] = u |
| return true |
| } |
| |
| // nolint |
| func (db *StudentDB) AddForCode(u *Student) bool { |
| if u.Code <= 0 { |
| return false |
| } |
| |
| if _, ok := db.codeIndex[u.Code]; ok { |
| return false |
| } |
| |
| db.codeIndex[u.Code] = u |
| return true |
| } |
| |
| // nolint |
| func (db *StudentDB) GetByName(n string) (*Student, bool) { |
| db.lock.Lock() |
| defer db.lock.Unlock() |
| |
| r, ok := db.nameIndex[n] |
| return r, ok |
| } |
| |
| // nolint |
| func (db *StudentDB) GetByCode(n int64) (*Student, bool) { |
| db.lock.Lock() |
| defer db.lock.Unlock() |
| |
| r, ok := db.codeIndex[n] |
| return r, ok |
| } |
| |
| func (db *StudentDB) existName(name string) bool { |
| if len(name) <= 0 { |
| return false |
| } |
| |
| _, ok := db.nameIndex[name] |
| if ok { |
| return true |
| } |
| |
| return false |
| } |
| |
| func (db *StudentDB) existCode(code int64) bool { |
| if code <= 0 { |
| return false |
| } |
| |
| _, ok := db.codeIndex[code] |
| if ok { |
| return true |
| } |
| |
| return false |
| } |
| |
| // Student student obj. |
| type Student struct { |
| ID string `json:"id,omitempty"` |
| Code int64 `json:"code,omitempty"` |
| Name string `json:"name,omitempty"` |
| Age int32 `json:"age,omitempty"` |
| Time time.Time `json:"time,omitempty"` |
| } |
| |
| // StudentProvider the dubbo provider. |
| // like: version: 1.0.0 group: test |
| type StudentProvider struct{} |
| |
| // CreateStudent new Student, PX config POST. |
| func (s *StudentProvider) CreateStudent(ctx context.Context, student *Student) (*Student, error) { |
| outLn("Req CreateStudent data:%#v", student) |
| if student == nil { |
| return nil, errors.New("not found") |
| } |
| _, ok := studentCache.GetByName(student.Name) |
| if ok { |
| return nil, errors.New("data is exist") |
| } |
| |
| b := studentCache.Add(student) |
| if b { |
| return student, nil |
| } |
| |
| return nil, errors.New("add error") |
| } |
| |
| // GetStudentByName query by name, single param, PX config GET. |
| func (s *StudentProvider) GetStudentByName(ctx context.Context, name string) (*Student, error) { |
| outLn("Req GetStudentByName name:%#v", name) |
| r, ok := studentCache.GetByName(name) |
| if !ok { |
| return nil, nil |
| } |
| outLn("Req GetStudentByName result:%#v", r) |
| return r, nil |
| } |
| |
| // GetStudentByCode query by code, single param, PX config GET. |
| func (s *StudentProvider) GetStudentByCode(ctx context.Context, code int64) (*Student, error) { |
| outLn("Req GetStudentByCode name:%#v", code) |
| r, ok := studentCache.GetByCode(code) |
| if !ok { |
| return nil, nil |
| } |
| outLn("Req GetStudentByCode result:%#v", r) |
| return r, nil |
| } |
| |
| // GetStudentTimeout query by name, will timeout for pixiu. |
| func (s *StudentProvider) GetStudentTimeout(ctx context.Context, name string) (*Student, error) { |
| outLn("Req GetStudentByName name:%#v", name) |
| // sleep 10s, pixiu config less than 10s. |
| time.Sleep(10 * time.Second) |
| r, ok := studentCache.GetByName(name) |
| if !ok { |
| return nil, nil |
| } |
| outLn("Req GetStudentByName result:%#v", r) |
| return r, nil |
| } |
| |
| // GetStudentByNameAndAge query by name and age, two params, PX config GET. |
| func (s *StudentProvider) GetStudentByNameAndAge(ctx context.Context, name string, age int32) (*Student, error) { |
| outLn("Req GetStudentByNameAndAge name:%s, age:%d", name, age) |
| r, ok := studentCache.GetByName(name) |
| if ok && r.Age == age { |
| outLn("Req GetStudentByNameAndAge result:%#v", r) |
| return r, nil |
| } |
| return r, nil |
| } |
| |
| // UpdateStudent update by Student struct, my be another struct, PX config POST or PUT. |
| func (s *StudentProvider) UpdateStudent(ctx context.Context, student *Student) (bool, error) { |
| outLn("Req UpdateStudent data:%#v", student) |
| r, ok := studentCache.GetByName(student.Name) |
| if !ok { |
| return false, errors.New("not found") |
| } |
| if len(student.ID) != 0 { |
| r.ID = student.ID |
| } |
| if student.Age >= 0 { |
| r.Age = student.Age |
| } |
| return true, nil |
| } |
| |
| // UpdateStudentByName update by Student struct, my be another struct, PX config POST or PUT. |
| func (s *StudentProvider) UpdateStudentByName(ctx context.Context, name string, student *Student) (bool, error) { |
| outLn("Req UpdateStudentByName data:%#v", student) |
| r, ok := studentCache.GetByName(name) |
| if !ok { |
| return false, errors.New("not found") |
| } |
| if len(student.ID) != 0 { |
| r.ID = student.ID |
| } |
| if student.Age >= 0 { |
| r.Age = student.Age |
| } |
| return true, nil |
| } |
| |
| // nolint |
| func (s *StudentProvider) Reference() string { |
| return "StudentProvider" |
| } |
| |
| // nolint |
| func (s Student) JavaClassName() string { |
| return "com.dubbogo.pixiu.StudentService" |
| } |
| |
| // nolint |
| func outLn(format string, args ...interface{}) { |
| fmt.Printf("\033[32;40m"+format+"\033[0m\n", args...) |
| } |