code quality inspection for pkg direcory

This commit is contained in:
zhuyasen
2023-08-06 17:41:28 +08:00
parent a7d0a67f01
commit 95a3ed7461
97 changed files with 375 additions and 269 deletions

5
.github/RELEASE.md vendored
View File

@@ -1,4 +1,5 @@
## New ## New
- Add automatic code merge function to solve the problem that you need to copy code manually after executing the command `make proto`. - Add automated code merge functionality in the command `make proto`, no more copying code manually.
- Improve documentation - Add code quality inspection.
- Improve documentation.

View File

@@ -12,10 +12,8 @@ run:
# default value is empty list, but default dirs are skipped independently # default value is empty list, but default dirs are skipped independently
# from this option's value (see skip-dirs-use-default). # from this option's value (see skip-dirs-use-default).
skip-dirs: skip-dirs:
- pkg
- docs - docs
- api - api
- configs
# which files to skip: they will be analyzed, but issues from them # which files to skip: they will be analyzed, but issues from them
# won't be reported. Default value is empty list, but there is # won't be reported. Default value is empty list, but there is
# no need to include all autogenerated files, we confidently recognize # no need to include all autogenerated files, we confidently recognize

View File

@@ -97,6 +97,8 @@ Visit `http://localhost:24631` in your browser, generate code by manipulating it
### Examples of use ### Examples of use
The following sample code , in addition to the core business logic code , the other code is generated by the tool sponge .
#### Basic Services examples #### Basic Services examples
- [1_web-gin-CRUD](https://github.com/zhufuyi/sponge_examples/tree/main/1_web-gin-CRUD) - [1_web-gin-CRUD](https://github.com/zhufuyi/sponge_examples/tree/main/1_web-gin-CRUD)

View File

@@ -138,6 +138,8 @@ sponge run
### 使用示例 ### 使用示例
下面的示例代码除了核心业务逻辑代码其他代码都是由工具sponge生成。
#### 基础服务示例 #### 基础服务示例
- [1_web-gin-CRUD](https://github.com/zhufuyi/sponge_examples/tree/main/1_web-gin-CRUD) - [1_web-gin-CRUD](https://github.com/zhufuyi/sponge_examples/tree/main/1_web-gin-CRUD)

View File

@@ -101,7 +101,9 @@ func buildHTTPRule(m *protogen.Method, rule *annotations.HttpRule) *RPCMethod {
} }
func buildMethodDesc(m *protogen.Method, httpMethod, path string) *RPCMethod { func buildMethodDesc(m *protogen.Method, httpMethod, path string) *RPCMethod {
defer func() { methodSets[m.GoName]++ }() defer func() {
methodSets[m.GoName]++
}()
md := &RPCMethod{ md := &RPCMethod{
Name: m.GoName, Name: m.GoName,
Num: methodSets[m.GoName], Num: methodSets[m.GoName],

View File

@@ -1,3 +1,4 @@
// Package configs used to locate config file.
package configs package configs
import ( import (
@@ -5,12 +6,10 @@ import (
"runtime" "runtime"
) )
// used to locate a directory
var basePath string var basePath string
func init() { func init() {
_, currentFile, _, _ := runtime.Caller(0) _, currentFile, _, _ := runtime.Caller(0) //nolint
basePath = filepath.Dir(currentFile) basePath = filepath.Dir(currentFile)
} }

View File

@@ -51,7 +51,7 @@ grpcClient:
host: "127.0.0.1" # rpc service address, used for direct connection host: "127.0.0.1" # rpc service address, used for direct connection
port: 8282 # rpc service port port: 8282 # rpc service port
registryDiscoveryType: "" # registration and discovery types: consul, etcd, nacos, if empty, connecting to server using host and port registryDiscoveryType: "" # registration and discovery types: consul, etcd, nacos, if empty, connecting to server using host and port
enableLoadBalance: false # whether to turn on the load balancer enableLoadBalance: true # whether to turn on the load balancer
# clientSecure parameter setting # clientSecure parameter setting
# if type="", it means no secure connection, no need to fill in any parameters # if type="", it means no secure connection, no need to fill in any parameters
# if type="one-way", it means server-side certification, only the fields 'serverName' and 'certFile' should be filled in # if type="one-way", it means server-side certification, only the fields 'serverName' and 'certFile' should be filled in

View File

@@ -1,3 +1,4 @@
// Package app is starting and stopping services gracefully, using golang.org/x/sync/errgroup to ensure that multiple services are started properly at the same time.
package app package app
import ( import (
@@ -46,10 +47,7 @@ func (a *App) Run() {
s := server s := server
eg.Go(func() error { eg.Go(func() error {
fmt.Println(s.String()) fmt.Println(s.String())
if err := s.Start(); err != nil { return s.Start()
return err
}
return nil
}) })
} }

1
pkg/cache/cache.go vendored
View File

@@ -1,3 +1,4 @@
// Package cache is memory and redis cache libraries.
package cache package cache
import ( import (

12
pkg/cache/memory.go vendored
View File

@@ -21,7 +21,7 @@ type memoryCache struct {
} }
// NewMemoryCache create a memory cache // NewMemoryCache create a memory cache
func NewMemoryCache(keyPrefix string, encoding encoding.Encoding, newObject func() interface{}) Cache { func NewMemoryCache(keyPrefix string, encode encoding.Encoding, newObject func() interface{}) Cache {
// see: https://dgraph.io/blog/post/introducing-ristretto-high-perf-go-cache/ // see: https://dgraph.io/blog/post/introducing-ristretto-high-perf-go-cache/
// https://www.start.io/blog/we-chose-ristretto-cache-for-go-heres-why/ // https://www.start.io/blog/we-chose-ristretto-cache-for-go-heres-why/
config := &ristretto.Config{ config := &ristretto.Config{
@@ -33,13 +33,13 @@ func NewMemoryCache(keyPrefix string, encoding encoding.Encoding, newObject func
return &memoryCache{ return &memoryCache{
client: store, client: store,
KeyPrefix: keyPrefix, KeyPrefix: keyPrefix,
encoding: encoding, encoding: encode,
newObject: newObject, newObject: newObject,
} }
} }
// Set data // Set data
func (m *memoryCache) Set(ctx context.Context, key string, val interface{}, expiration time.Duration) error { func (m *memoryCache) Set(_ context.Context, key string, val interface{}, expiration time.Duration) error {
buf, err := encoding.Marshal(m.encoding, val) buf, err := encoding.Marshal(m.encoding, val)
if err != nil { if err != nil {
return fmt.Errorf("encoding.Marshal error: %v, key=%s, val=%+v ", err, key, val) return fmt.Errorf("encoding.Marshal error: %v, key=%s, val=%+v ", err, key, val)
@@ -57,7 +57,7 @@ func (m *memoryCache) Set(ctx context.Context, key string, val interface{}, expi
} }
// Get data // Get data
func (m *memoryCache) Get(ctx context.Context, key string, val interface{}) error { func (m *memoryCache) Get(_ context.Context, key string, val interface{}) error {
cacheKey, err := BuildCacheKey(m.KeyPrefix, key) cacheKey, err := BuildCacheKey(m.KeyPrefix, key)
if err != nil { if err != nil {
return fmt.Errorf("BuildCacheKey error: %v, key=%s", err, key) return fmt.Errorf("BuildCacheKey error: %v, key=%s", err, key)
@@ -81,7 +81,7 @@ func (m *memoryCache) Get(ctx context.Context, key string, val interface{}) erro
} }
// Del delete data // Del delete data
func (m *memoryCache) Del(ctx context.Context, keys ...string) error { func (m *memoryCache) Del(_ context.Context, keys ...string) error {
if len(keys) == 0 { if len(keys) == 0 {
return nil return nil
} }
@@ -124,7 +124,7 @@ func (m *memoryCache) MultiGet(ctx context.Context, keys []string, value interfa
} }
// SetCacheWithNotFound set not found // SetCacheWithNotFound set not found
func (m *memoryCache) SetCacheWithNotFound(ctx context.Context, key string) error { func (m *memoryCache) SetCacheWithNotFound(_ context.Context, key string) error {
cacheKey, err := BuildCacheKey(m.KeyPrefix, key) cacheKey, err := BuildCacheKey(m.KeyPrefix, key)
if err != nil { if err != nil {
return fmt.Errorf("BuildCacheKey error: %v, key=%s", err, key) return fmt.Errorf("BuildCacheKey error: %v, key=%s", err, key)

4
pkg/cache/redis.go vendored
View File

@@ -26,11 +26,11 @@ type redisCache struct {
} }
// NewRedisCache new a cache, client parameter can be passed in for unit testing // NewRedisCache new a cache, client parameter can be passed in for unit testing
func NewRedisCache(client *redis.Client, keyPrefix string, encoding encoding.Encoding, newObject func() interface{}) Cache { func NewRedisCache(client *redis.Client, keyPrefix string, encode encoding.Encoding, newObject func() interface{}) Cache {
return &redisCache{ return &redisCache{
client: client, client: client,
KeyPrefix: keyPrefix, KeyPrefix: keyPrefix,
encoding: encoding, encoding: encode,
newObject: newObject, newObject: newObject,
} }
} }

View File

@@ -1,3 +1,4 @@
// Package conf is parsing yaml, json, toml configuration files to go struct.
package conf package conf
import ( import (

View File

@@ -1,3 +1,4 @@
// Package consulcli is connecting to the consul service client.
package consulcli package consulcli
import ( import (

View File

@@ -1,3 +1,4 @@
// Package encoding Provides encoding and decoding of json, protobuf and gob.
package encoding package encoding
import ( import (
@@ -74,19 +75,18 @@ func Marshal(e Encoding, v interface{}) (data []byte, err error) {
} }
bm, ok := v.(encoding.BinaryMarshaler) bm, ok := v.(encoding.BinaryMarshaler)
if ok && e == nil { if ok && e == nil {
data, err = bm.MarshalBinary() return bm.MarshalBinary()
return
} }
data, err = e.Marshal(v) data, err = e.Marshal(v)
if err == nil { if err == nil {
return return data, err
} }
if ok { if ok {
data, err = bm.MarshalBinary() data, err = bm.MarshalBinary()
} }
return return data, err
} }
// Unmarshal decode data // Unmarshal decode data
@@ -101,12 +101,12 @@ func Unmarshal(e Encoding, data []byte, v interface{}) (err error) {
} }
err = e.Unmarshal(data, v) err = e.Unmarshal(data, v)
if err == nil { if err == nil {
return return err
} }
if ok { if ok {
return bm.UnmarshalBinary(data) return bm.UnmarshalBinary(data)
} }
return return err
} }
func isPointer(data interface{}) bool { func isPointer(data interface{}) bool {

View File

@@ -1,3 +1,4 @@
// Package json is a JSON encoding and decoding.
package json package json
import ( import (

View File

@@ -106,7 +106,7 @@ func GzipDecode(in []byte) ([]byte, error) {
// JSONSnappyEncoding json format and snappy compression // JSONSnappyEncoding json format and snappy compression
type JSONSnappyEncoding struct{} type JSONSnappyEncoding struct{}
// Marshal serialisation // Marshal serialization
func (s JSONSnappyEncoding) Marshal(v interface{}) (data []byte, err error) { func (s JSONSnappyEncoding) Marshal(v interface{}) (data []byte, err error) {
b, err := json.Marshal(v) b, err := json.Marshal(v)
if err != nil { if err != nil {

View File

@@ -1,3 +1,4 @@
// Package proto is a protobuf encoding and decoding.
package proto package proto
import ( import (

View File

@@ -1,3 +1,4 @@
// Package errcode is used for http and grpc error codes, include system-level error codes and service-level error codes
package errcode package errcode
import ( import (

View File

@@ -10,9 +10,9 @@ package errcode
// ErrUserUpdate = NewError(HCode(1)+3, "failed to update user") // 200103 // ErrUserUpdate = NewError(HCode(1)+3, "failed to update user") // 200103
// ErrUserGet = NewError(HCode(1)+4, "failed to get user details") // 200104 // ErrUserGet = NewError(HCode(1)+4, "failed to get user details") // 200104
// ) // )
func HCode(NO int) int { func HCode(num int) int {
if NO > 99 || NO < 1 { if num > 99 || num < 1 {
panic("NO range must be between 0 to 100") panic("num range must be between 0 to 100")
} }
return 200000 + NO*100 return 200000 + num*100
} }

View File

@@ -1,6 +1,5 @@
package errcode package errcode
// nolint
// http system level error code, error code range 10000~20000 // http system level error code, error code range 10000~20000
var ( var (
Success = NewError(0, "ok") Success = NewError(0, "ok")

View File

@@ -54,8 +54,8 @@ type defaultResponse struct {
rpcStatus map[int]*RPCStatus rpcStatus map[int]*RPCStatus
} }
func (resp *defaultResponse) response(c *gin.Context, status, code int, msg string, data interface{}) { func (resp *defaultResponse) response(c *gin.Context, respStatus, code int, msg string, data interface{}) {
c.JSON(status, map[string]interface{}{ c.JSON(respStatus, map[string]interface{}{
"code": code, "code": code,
"msg": msg, "msg": msg,
"data": data, "data": data,
@@ -67,8 +67,8 @@ func (resp *defaultResponse) Success(c *gin.Context, data interface{}) {
resp.response(c, http.StatusOK, 0, "ok", data) resp.response(c, http.StatusOK, 0, "ok", data)
} }
// ParamError response parameter error information // ParamError response parameter error information, does not return an error message
func (resp *defaultResponse) ParamError(c *gin.Context, err error) { func (resp *defaultResponse) ParamError(c *gin.Context, _ error) {
resp.response(c, http.StatusOK, InvalidParams.Code(), InvalidParams.Msg(), struct{}{}) resp.response(c, http.StatusOK, InvalidParams.Code(), InvalidParams.Msg(), struct{}{})
} }
@@ -173,24 +173,37 @@ func (resp *defaultResponse) isUserDefinedHTTPErrorCode(c *gin.Context, errCode
} }
// ToHTTPErr converted to http error // ToHTTPErr converted to http error
func ToHTTPErr(st *status.Status) *Error { func ToHTTPErr(st *status.Status) *Error { //nolint
switch st.Code() { switch st.Code() {
case StatusSuccess.status.Code(), codes.OK: case StatusSuccess.status.Code(), codes.OK:
return Success return Success
case StatusInvalidParams.status.Code(), codes.InvalidArgument:
return InvalidParams
case StatusInternalServerError.status.Code(), codes.Internal:
return InternalServerError
case StatusUnimplemented.status.Code(), codes.Unimplemented:
return Unimplemented
case StatusPermissionDenied.status.Code(), codes.PermissionDenied:
return PermissionDenied
}
switch st.Code() {
//case StatusSuccess.status.Code(), codes.OK:
// return Success
case StatusCanceled.status.Code(), codes.Canceled: case StatusCanceled.status.Code(), codes.Canceled:
return Canceled return Canceled
case StatusUnknown.status.Code(), codes.Unknown: case StatusUnknown.status.Code(), codes.Unknown:
return Unknown return Unknown
case StatusInvalidParams.status.Code(), codes.InvalidArgument: //case StatusInvalidParams.status.Code(), codes.InvalidArgument:
return InvalidParams // return InvalidParams
case StatusDeadlineExceeded.status.Code(), codes.DeadlineExceeded: case StatusDeadlineExceeded.status.Code(), codes.DeadlineExceeded:
return DeadlineExceeded return DeadlineExceeded
case StatusNotFound.status.Code(), codes.NotFound: case StatusNotFound.status.Code(), codes.NotFound:
return NotFound return NotFound
case StatusAlreadyExists.status.Code(), codes.AlreadyExists: case StatusAlreadyExists.status.Code(), codes.AlreadyExists:
return AlreadyExists return AlreadyExists
case StatusPermissionDenied.status.Code(), codes.PermissionDenied: //case StatusPermissionDenied.status.Code(), codes.PermissionDenied:
return PermissionDenied // return PermissionDenied
case StatusResourceExhausted.status.Code(), codes.ResourceExhausted: case StatusResourceExhausted.status.Code(), codes.ResourceExhausted:
return ResourceExhausted return ResourceExhausted
case StatusFailedPrecondition.status.Code(), codes.FailedPrecondition: case StatusFailedPrecondition.status.Code(), codes.FailedPrecondition:
@@ -199,10 +212,10 @@ func ToHTTPErr(st *status.Status) *Error {
return Aborted return Aborted
case StatusOutOfRange.status.Code(), codes.OutOfRange: case StatusOutOfRange.status.Code(), codes.OutOfRange:
return OutOfRange return OutOfRange
case StatusUnimplemented.status.Code(), codes.Unimplemented: //case StatusUnimplemented.status.Code(), codes.Unimplemented:
return Unimplemented // return Unimplemented
case StatusInternalServerError.status.Code(), codes.Internal: //case StatusInternalServerError.status.Code(), codes.Internal:
return InternalServerError // return InternalServerError
case StatusServiceUnavailable.status.Code(), codes.Unavailable: case StatusServiceUnavailable.status.Code(), codes.Unavailable:
return ServiceUnavailable return ServiceUnavailable
case StatusDataLoss.status.Code(), codes.DataLoss: case StatusDataLoss.status.Code(), codes.DataLoss:

View File

@@ -128,21 +128,32 @@ func toRPCErr(code codes.Code, descs ...string) error {
// ToRPCCode converted to standard RPC error code // ToRPCCode converted to standard RPC error code
func (g *RPCStatus) ToRPCCode() codes.Code { func (g *RPCStatus) ToRPCCode() codes.Code {
switch g.status.Code() {
case StatusInvalidParams.status.Code():
return codes.InvalidArgument
case StatusInternalServerError.status.Code():
return codes.Internal
case StatusUnimplemented.status.Code():
return codes.Unimplemented
case StatusPermissionDenied.status.Code():
return codes.PermissionDenied
}
switch g.status.Code() { switch g.status.Code() {
case StatusCanceled.status.Code(): case StatusCanceled.status.Code():
return codes.Canceled return codes.Canceled
case StatusUnknown.status.Code(): case StatusUnknown.status.Code():
return codes.Unknown return codes.Unknown
case StatusInvalidParams.status.Code(): //case StatusInvalidParams.status.Code():
return codes.InvalidArgument // return codes.InvalidArgument
case StatusDeadlineExceeded.status.Code(): case StatusDeadlineExceeded.status.Code():
return codes.DeadlineExceeded return codes.DeadlineExceeded
case StatusNotFound.status.Code(): case StatusNotFound.status.Code():
return codes.NotFound return codes.NotFound
case StatusAlreadyExists.status.Code(): case StatusAlreadyExists.status.Code():
return codes.AlreadyExists return codes.AlreadyExists
case StatusPermissionDenied.status.Code(): //case StatusPermissionDenied.status.Code():
return codes.PermissionDenied // return codes.PermissionDenied
case StatusResourceExhausted.status.Code(): case StatusResourceExhausted.status.Code():
return codes.ResourceExhausted return codes.ResourceExhausted
case StatusFailedPrecondition.status.Code(): case StatusFailedPrecondition.status.Code():
@@ -151,10 +162,10 @@ func (g *RPCStatus) ToRPCCode() codes.Code {
return codes.Aborted return codes.Aborted
case StatusOutOfRange.status.Code(): case StatusOutOfRange.status.Code():
return codes.OutOfRange return codes.OutOfRange
case StatusUnimplemented.status.Code(): //case StatusUnimplemented.status.Code():
return codes.Unimplemented // return codes.Unimplemented
case StatusInternalServerError.status.Code(): //case StatusInternalServerError.status.Code():
return codes.Internal // return codes.Internal
case StatusServiceUnavailable.status.Code(): case StatusServiceUnavailable.status.Code():
return codes.Unavailable return codes.Unavailable
case StatusDataLoss.status.Code(): case StatusDataLoss.status.Code():

View File

@@ -12,9 +12,9 @@ import "google.golang.org/grpc/codes"
// StatusUserUpdate = NewRPCStatus(RCode(1)+3, "failed to update user") // 40103 // StatusUserUpdate = NewRPCStatus(RCode(1)+3, "failed to update user") // 40103
// StatusUserGet = NewRPCStatus(RCode(1)+4, "failed to get user details") // 40104 // StatusUserGet = NewRPCStatus(RCode(1)+4, "failed to get user details") // 40104
// ) // )
func RCode(NO int) codes.Code { func RCode(num int) codes.Code {
if NO > 99 || NO < 1 { if num > 99 || num < 1 {
panic("NO range must be between 0 to 100") panic("NO range must be between 0 to 100")
} }
return codes.Code(40000 + NO*100) return codes.Code(40000 + num*100)
} }

View File

@@ -1,6 +1,5 @@
package errcode package errcode
// nolint
// rpc system level error code with status prefix, error code range 30000~40000 // rpc system level error code with status prefix, error code range 30000~40000
var ( var (
StatusSuccess = NewRPCStatus(0, "ok") StatusSuccess = NewRPCStatus(0, "ok")

View File

@@ -1,3 +1,4 @@
// Package etcdcli is use for connecting to the etcd service
package etcdcli package etcdcli
import ( import (

View File

@@ -19,7 +19,7 @@ type options struct {
serverNameOverride string // etcd domain serverNameOverride string // etcd domain
certFile string // path to certificate file certFile string // path to certificate file
autoSyncInterval time.Duration // automatic synchronisation of member list intervals autoSyncInterval time.Duration // automatic synchronization of member list intervals
logger *zap.Logger logger *zap.Logger
} }

View File

@@ -1,3 +1,4 @@
// Package handlerfunc is used for public http request handler.
package handlerfunc package handlerfunc
import ( import (

View File

@@ -1,3 +1,4 @@
// Package middleware is gin middleware plugin.
package middleware package middleware
import ( import (

View File

@@ -67,8 +67,7 @@ func CircuitBreaker(opts ...CircuitBreakerOption) gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
breaker := o.group.Get(c.FullPath()).(circuitbreaker.CircuitBreaker) breaker := o.group.Get(c.FullPath()).(circuitbreaker.CircuitBreaker)
if err := breaker.Allow(); err != nil { if err := breaker.Allow(); err != nil {
// NOTE: when client reject request locally, // NOTE: when client reject request locally, keep adding counter let the drop ratio higher.
// continue to add counter let the drop ratio higher.
breaker.MarkFailed() breaker.MarkFailed()
response.Output(c, http.StatusServiceUnavailable, err.Error()) response.Output(c, http.StatusServiceUnavailable, err.Error())
c.Abort() c.Abort()

View File

@@ -1,3 +1,5 @@
// Package metrics is gin metrics library, collect five metrics, "uptime", "http_request_count_total",
// "http_request_duration_seconds", "http_request_size_bytes", "http_response_size_bytes".
package metrics package metrics
import ( import (

View File

@@ -4,9 +4,10 @@ import (
"net/http" "net/http"
"time" "time"
"github.com/gin-gonic/gin"
"github.com/zhufuyi/sponge/pkg/gin/response" "github.com/zhufuyi/sponge/pkg/gin/response"
rl "github.com/zhufuyi/sponge/pkg/shield/ratelimit" rl "github.com/zhufuyi/sponge/pkg/shield/ratelimit"
"github.com/gin-gonic/gin"
) )
// ErrLimitExceed is returned when the rate limiter is // ErrLimitExceed is returned when the rate limiter is

View File

@@ -1,3 +1,4 @@
// Package prof is used for gin profiling.
package prof package prof
import ( import (

View File

@@ -1,3 +1,4 @@
// Package response provides wrapper gin returns json data in the same format.
package response package response
import ( import (
@@ -52,11 +53,11 @@ func writeJSON(c *gin.Context, code int, res interface{}) {
} }
func respJSONWithStatusCode(c *gin.Context, code int, msg string, data ...interface{}) { func respJSONWithStatusCode(c *gin.Context, code int, msg string, data ...interface{}) {
var FirstData interface{} var firstData interface{}
if len(data) > 0 { if len(data) > 0 {
FirstData = data[0] firstData = data[0]
} }
resp := newResp(code, msg, FirstData) resp := newResp(code, msg, firstData)
writeJSON(c, code, resp) writeJSON(c, code, resp)
} }
@@ -122,11 +123,11 @@ func Out(c *gin.Context, err *errcode.Error, data ...interface{}) {
// status code flat 200, custom error codes in data.code // status code flat 200, custom error codes in data.code
func respJSONWith200(c *gin.Context, code int, msg string, data ...interface{}) { func respJSONWith200(c *gin.Context, code int, msg string, data ...interface{}) {
var FirstData interface{} var firstData interface{}
if len(data) > 0 { if len(data) > 0 {
FirstData = data[0] firstData = data[0]
} }
resp := newResp(code, msg, FirstData) resp := newResp(code, msg, firstData)
writeJSON(c, http.StatusOK, resp) writeJSON(c, http.StatusOK, resp)
} }

View File

@@ -1,3 +1,4 @@
// Package swagger is gin swagger library.
package swagger package swagger
import ( import (

View File

@@ -1,3 +1,4 @@
// Package validator is gin request parameter check library.
package validator package validator
import ( import (
@@ -9,9 +10,9 @@ import (
// Init request body file valid // Init request body file valid
func Init() *CustomValidator { func Init() *CustomValidator {
valid := NewCustomValidator() validator := NewCustomValidator()
valid.Engine() validator.Engine()
return valid return validator
} }
// CustomValidator Custom valid objects // CustomValidator Custom valid objects

View File

@@ -1,3 +1,4 @@
// Package gobash provides the ability to execute commands, scripts, executables in the go environment with live log output.
package gobash package gobash
import ( import (

View File

@@ -1,6 +1,6 @@
## gofile ## gofile
For file and directory management libraries. File and directory management libraries.
<br> <br>

View File

@@ -1,3 +1,4 @@
// Package gofile is file and directory management libraries.
package gofile package gofile
import ( import (

View File

@@ -9,8 +9,8 @@ import (
) )
// IsExists determine if a file or folder exists // IsExists determine if a file or folder exists
func IsExists(path string) bool { func IsExists(f string) bool {
_, err := os.Stat(path) _, err := os.Stat(f)
if err != nil { if err != nil {
return !os.IsNotExist(err) return !os.IsNotExist(err)
} }
@@ -56,13 +56,13 @@ func GetFilenameWithoutSuffix(filePath string) string {
// Join joins any number of path elements into a single path // Join joins any number of path elements into a single path
func Join(elem ...string) string { func Join(elem ...string) string {
path := strings.Join(elem, "/") dir := strings.Join(elem, "/")
if IsWindows() { if IsWindows() {
return strings.ReplaceAll(path, "/", "\\") return strings.ReplaceAll(dir, "/", "\\")
} }
return path return dir
} }
// IsWindows determining whether a window environment // IsWindows determining whether a window environment

View File

@@ -1,3 +1,4 @@
// Package gohttp is http request client, which only supports returning json format.
package gohttp package gohttp
import ( import (
@@ -166,7 +167,7 @@ func (req *Request) Do(method string, data interface{}) (*Response, error) {
switch method { switch method {
case http.MethodGet, http.MethodDelete: case http.MethodGet, http.MethodDelete:
if data != nil { if data != nil {
if params, ok := data.(map[string]interface{}); ok { if params, ok := data.(map[string]interface{}); ok { //nolint
req.SetParams(params) req.SetParams(params)
} else { } else {
req.err = errors.New("params is not a map[string]interface{}") req.err = errors.New("params is not a map[string]interface{}")
@@ -321,36 +322,36 @@ func (resp *Response) BindJSON(v interface{}) error {
// Simple crud function, no support for setting header, timeout, etc. // Simple crud function, no support for setting header, timeout, etc.
// Get request, return custom json format // Get request, return custom json format
func Get(result interface{}, url string, params ...KV) error { func Get(result interface{}, urlStr string, params ...KV) error {
var pms KV var pms KV
if len(params) > 0 { if len(params) > 0 {
pms = params[0] pms = params[0]
} }
return gDo("GET", result, url, pms) return gDo("GET", result, urlStr, pms)
} }
// Delete request, return custom json format // Delete request, return custom json format
func Delete(result interface{}, url string, params ...KV) error { func Delete(result interface{}, urlStr string, params ...KV) error {
var pms KV var pms KV
if len(params) > 0 { if len(params) > 0 {
pms = params[0] pms = params[0]
} }
return gDo("DELETE", result, url, pms) return gDo("DELETE", result, urlStr, pms)
} }
// Post request, return custom json format // Post request, return custom json format
func Post(result interface{}, url string, body interface{}) error { func Post(result interface{}, urlStr string, body interface{}) error {
return do("POST", result, url, body) return do("POST", result, urlStr, body)
} }
// Put request, return custom json format // Put request, return custom json format
func Put(result interface{}, url string, body interface{}) error { func Put(result interface{}, urlStr string, body interface{}) error {
return do("PUT", result, url, body) return do("PUT", result, urlStr, body)
} }
// Patch request, return custom json format // Patch request, return custom json format
func Patch(result interface{}, url string, body interface{}) error { func Patch(result interface{}, urlStr string, body interface{}) error {
return do("PATCH", result, url, body) return do("PATCH", result, urlStr, body)
} }
var requestErr = func(err error) error { return fmt.Errorf("request error, err=%v", err) } var requestErr = func(err error) error { return fmt.Errorf("request error, err=%v", err) }
@@ -366,13 +367,13 @@ var notOKErr = func(resp *Response) error {
return fmt.Errorf("statusCode=%d, body=%s", resp.StatusCode, body) return fmt.Errorf("statusCode=%d, body=%s", resp.StatusCode, body)
} }
func do(method string, result interface{}, url string, body interface{}, params ...KV) error { func do(method string, result interface{}, urlStr string, body interface{}, params ...KV) error {
if result == nil { if result == nil {
return fmt.Errorf("params 'result' is nil") return fmt.Errorf("params 'result' is nil")
} }
req := &Request{} req := &Request{}
req.SetURL(url) req.SetURL(urlStr)
req.SetContentType("application/json") req.SetContentType("application/json")
if len(params) > 0 { if len(params) > 0 {
req.SetParams(params[0]) req.SetParams(params[0])
@@ -406,9 +407,9 @@ func do(method string, result interface{}, url string, body interface{}, params
return nil return nil
} }
func gDo(method string, result interface{}, url string, params KV) error { func gDo(method string, result interface{}, urlStr string, params KV) error {
req := &Request{} req := &Request{}
req.SetURL(url) req.SetURL(urlStr)
req.SetParams(params) req.SetParams(params)
var resp *Response var resp *Response

View File

@@ -1,3 +1,4 @@
// Package goredis is a library wrapped on top of github.com/go-redis/redis.
package goredis package goredis
import ( import (

View File

@@ -1,3 +1,4 @@
// Package gotest is a library that simulates the testing of cache, dao and handler.
package gotest package gotest
import ( import (

View File

@@ -1,3 +1,4 @@
// Package benchmark is compression testing of rpc methods and generation of reported results.
package benchmark package benchmark
import ( import (

View File

@@ -1,3 +1,4 @@
// Package grpccli is grpc client with support for service discovery, logging, load balancing, trace, metrics, retries, circuit breaker.
package grpccli package grpccli
import ( import (

View File

@@ -1,5 +1,7 @@
## gtls ## gtls
gtls provides grpc secure connectivity, supporting both server-only authentication and client-server authentication.
#### Example of use #### Example of use
#### grpc server #### grpc server

View File

@@ -1,3 +1,4 @@
// Package certfile is used to locate the certificate file.
package certfile package certfile
import ( import (

View File

@@ -1,3 +1,4 @@
// Package gtls provides grpc secure connectivity, supporting both server-only authentication and client-server authentication.
package gtls package gtls
import ( import (

View File

@@ -1,6 +1,6 @@
## interceptor ## interceptor
Commonly used grpc client and server-side interceptors. Commonly used grpc client-side and server-side interceptors.
<br> <br>
@@ -60,10 +60,9 @@ var logger *zap.Logger
func getServerOptions() []grpc.ServerOption { func getServerOptions() []grpc.ServerOption {
var options []grpc.ServerOption var options []grpc.ServerOption
// log setting, which prints client disconnection information by default, example https://pkg.go.dev/github.com/grpc-ecosystem/go-grpc-middleware/logging/zap
options = append(options, grpc_middleware.WithUnaryServerChain( options = append(options, grpc_middleware.WithUnaryServerChain(
interceptor.UnaryServerZapLogging( interceptor.UnaryClientLog(
logger.Get(), // zap logger.Get(), // zap
// middleware.WithLogFields(map[string]interface{}{"serverName": "userExample"}), // additional print fields // middleware.WithLogFields(map[string]interface{}{"serverName": "userExample"}), // additional print fields
middleware.WithLogIgnoreMethods("/proto.userExampleService/GetByID"), // ignore the specified method print, you can specify more than one middleware.WithLogIgnoreMethods("/proto.userExampleService/GetByID"), // ignore the specified method print, you can specify more than one

View File

@@ -1,7 +1,9 @@
// Package interceptor provides commonly used grpc client-side and server-side interceptors.
package interceptor package interceptor
import ( import (
"context" "context"
"github.com/zhufuyi/sponge/pkg/container/group" "github.com/zhufuyi/sponge/pkg/container/group"
"github.com/zhufuyi/sponge/pkg/errcode" "github.com/zhufuyi/sponge/pkg/errcode"
"github.com/zhufuyi/sponge/pkg/shield/circuitbreaker" "github.com/zhufuyi/sponge/pkg/shield/circuitbreaker"
@@ -68,8 +70,7 @@ func UnaryClientCircuitBreaker(opts ...CircuitBreakerOption) grpc.UnaryClientInt
return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
breaker := o.group.Get(method).(circuitbreaker.CircuitBreaker) breaker := o.group.Get(method).(circuitbreaker.CircuitBreaker)
if err := breaker.Allow(); err != nil { if err := breaker.Allow(); err != nil {
// NOTE: when client reject request locally, // NOTE: when client reject request locally, keep adding counter let the drop ratio higher.
// continue to add counter let the drop ratio higher.
breaker.MarkFailed() breaker.MarkFailed()
return errcode.StatusServiceUnavailable.ToRPCErr(err.Error()) return errcode.StatusServiceUnavailable.ToRPCErr(err.Error())
} }
@@ -98,8 +99,7 @@ func StreamClientCircuitBreaker(opts ...CircuitBreakerOption) grpc.StreamClientI
return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) { return func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
breaker := o.group.Get(method).(circuitbreaker.CircuitBreaker) breaker := o.group.Get(method).(circuitbreaker.CircuitBreaker)
if err := breaker.Allow(); err != nil { if err := breaker.Allow(); err != nil {
// NOTE: when client reject request locally, // NOTE: when client reject request locally, keep adding counter let the drop ratio higher.
// continue to add counter let the drop ratio higher.
breaker.MarkFailed() breaker.MarkFailed()
return nil, errcode.StatusServiceUnavailable.ToRPCErr(err.Error()) return nil, errcode.StatusServiceUnavailable.ToRPCErr(err.Error())
} }
@@ -128,8 +128,7 @@ func UnaryServerCircuitBreaker(opts ...CircuitBreakerOption) grpc.UnaryServerInt
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
breaker := o.group.Get(info.FullMethod).(circuitbreaker.CircuitBreaker) breaker := o.group.Get(info.FullMethod).(circuitbreaker.CircuitBreaker)
if err := breaker.Allow(); err != nil { if err := breaker.Allow(); err != nil {
// NOTE: when client reject request locally, // NOTE: when client reject request locally, keep adding let the drop ratio higher.
// continue to add counter let the drop ratio higher.
breaker.MarkFailed() breaker.MarkFailed()
return nil, errcode.StatusServiceUnavailable.ToRPCErr(err.Error()) return nil, errcode.StatusServiceUnavailable.ToRPCErr(err.Error())
} }
@@ -158,8 +157,7 @@ func StreamServerCircuitBreaker(opts ...CircuitBreakerOption) grpc.StreamServerI
return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { return func(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
breaker := o.group.Get(info.FullMethod).(circuitbreaker.CircuitBreaker) breaker := o.group.Get(info.FullMethod).(circuitbreaker.CircuitBreaker)
if err := breaker.Allow(); err != nil { if err := breaker.Allow(); err != nil {
// NOTE: when client reject request locally, // NOTE: when client reject request locally, keep adding counter let the drop ratio higher.
// continue to add counter let the drop ratio higher.
breaker.MarkFailed() breaker.MarkFailed()
return errcode.StatusServiceUnavailable.ToRPCErr(err.Error()) return errcode.StatusServiceUnavailable.ToRPCErr(err.Error())
} }

View File

@@ -116,7 +116,8 @@ func JwtVerify(ctx context.Context) (context.Context, error) {
return nil, status.Errorf(codes.Unauthenticated, "%v", err) return nil, status.Errorf(codes.Unauthenticated, "%v", err)
} }
newCtx := context.WithValue(ctx, authCtxClaimsName, cc) // get value by ctx.Value(interceptor.GetAuthCtxKey()).(*jwt.CustomClaims) newCtx := context.WithValue(ctx, authCtxClaimsName, cc) //nolint
// get value by ctx.Value(interceptor.GetAuthCtxKey()).(*jwt.CustomClaims)
return newCtx, nil return newCtx, nil
} }

View File

@@ -2,6 +2,7 @@ package interceptor
import ( import (
"context" "context"
grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery" grpc_recovery "github.com/grpc-ecosystem/go-grpc-middleware/recovery"
"google.golang.org/grpc" "google.golang.org/grpc"
"google.golang.org/grpc/codes" "google.golang.org/grpc/codes"

View File

@@ -81,14 +81,14 @@ func UnaryServerRequestID() grpc.UnaryServerInterceptor {
// StreamServerRequestID server-side request id stream interceptor // StreamServerRequestID server-side request id stream interceptor
func StreamServerRequestID() grpc.StreamServerInterceptor { func StreamServerRequestID() grpc.StreamServerInterceptor {
// todo
return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
ctx := stream.Context() //ctx := stream.Context()
requestID := ServerCtxRequestID(ctx) //requestID := ServerCtxRequestID(ctx)
if requestID == "" { //if requestID == "" {
requestID = krand.String(krand.R_All, 10) // requestID = krand.String(krand.R_All, 10)
ctx = metautils.ExtractIncoming(ctx).Add(ContextRequestIDKey, requestID).ToIncoming(ctx) // ctx = metautils.ExtractIncoming(ctx).Add(ContextRequestIDKey, requestID).ToIncoming(ctx)
} //}
return handler(srv, stream) return handler(srv, stream)
} }
} }

View File

@@ -2,6 +2,7 @@ package interceptor
import ( import (
"context" "context"
"github.com/grpc-ecosystem/go-grpc-middleware/util/metautils" "github.com/grpc-ecosystem/go-grpc-middleware/util/metautils"
"google.golang.org/grpc" "google.golang.org/grpc"
) )
@@ -15,7 +16,7 @@ type authToken struct {
} }
// GetRequestMetadata get metadata // GetRequestMetadata get metadata
func (t *authToken) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { func (t *authToken) GetRequestMetadata(ctx context.Context, uri ...string) (map[string]string, error) { //nolint
return map[string]string{ return map[string]string{
"app_id": t.AppID, "app_id": t.AppID,
"app_key": t.AppKey, "app_key": t.AppKey,

View File

@@ -1,3 +1,4 @@
// Package keepalive is setting grpc keepalive parameters.
package keepalive package keepalive
import ( import (

View File

@@ -1,6 +1,6 @@
## metrics ## metrics
The grpc's server and client-side metrics can continue to be captured using prometheus. The grpc's server-side and client-side metrics can continue to be captured using prometheus.
### Example of use ### Example of use

View File

@@ -19,7 +19,7 @@ var (
// create a Registry // create a Registry
cliReg = prometheus.NewRegistry() cliReg = prometheus.NewRegistry()
// initialise the client's default metrics // initialize the client's default metrics
grpcClientMetrics = grpc_prometheus.NewClientMetrics() grpcClientMetrics = grpc_prometheus.NewClientMetrics()
cliOnce sync.Once cliOnce sync.Once

View File

@@ -1,3 +1,4 @@
// Package metrics is grpc's server-side and client-side metrics can continue to be captured using prometheus.
package metrics package metrics
import ( import (
@@ -135,7 +136,7 @@ func ServerHTTPService(addr string, grpcServer *grpc.Server) *http.Server {
} }
}() }()
// initialising gRPC methods Metrics // initialize gRPC methods Metrics
grpcServerMetrics.InitializeMetrics(grpcServer) grpcServerMetrics.InitializeMetrics(grpcServer)
return httpServer return httpServer

View File

@@ -1,3 +1,4 @@
// Package resolve is setting grpc client-side load balancing policy.
package resolve package resolve
import ( import (
@@ -37,7 +38,7 @@ type ResolverBuilder struct {
} }
// Build resolver // Build resolver
func (r *ResolverBuilder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) { func (r *ResolverBuilder) Build(target resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (resolver.Resolver, error) {
blr := &blResolver{ blr := &blResolver{
target: target, target: target,
cc: cc, cc: cc,
@@ -70,7 +71,7 @@ func (b *blResolver) start() {
} }
// ResolveNow Resolve now // ResolveNow Resolve now
func (*blResolver) ResolveNow(o resolver.ResolveNowOptions) {} func (*blResolver) ResolveNow(_ resolver.ResolveNowOptions) {}
// Close resolver // Close resolver
func (*blResolver) Close() {} func (*blResolver) Close() {}

View File

@@ -1,3 +1,4 @@
// Package jwt is token generation and validation.
package jwt package jwt
import ( import (

View File

@@ -1,3 +1,4 @@
// Package jy2struct is a library for generating go struct code, supporting json and yaml.
package jy2struct package jy2struct
import ( import (
@@ -16,7 +17,7 @@ type Args struct {
SubStruct bool // are sub-structures separated SubStruct bool // are sub-structures separated
Tags string // add additional tags, multiple tags separated by commas Tags string // add additional tags, multiple tags separated by commas
tags []string tags []string //nolint
convertFloats bool convertFloats bool
parser Parser parser Parser
} }

View File

@@ -107,7 +107,8 @@ func readFile(input io.Reader) ([]byte, error) {
// json or yaml parse // json or yaml parse
func jyParse(input io.Reader, parser Parser, structName, pkgName string, tags []string, subStruct bool, convertFloats bool) ([]byte, error) { func jyParse(input io.Reader, parser Parser, structName, pkgName string, tags []string, subStruct bool, convertFloats bool) ([]byte, error) {
var subStructMap map[string]string = nil _ = pkgName
var subStructMap map[string]string
if subStruct { if subStruct {
subStructMap = make(map[string]string) subStructMap = make(map[string]string)
} }
@@ -125,7 +126,6 @@ func jyParse(input io.Reader, parser Parser, structName, pkgName string, tags []
case map[string]interface{}: case map[string]interface{}:
result = iresult result = iresult
case []interface{}: case []interface{}:
//src := fmt.Sprintf("package %s\n\ntype %s %s\n", pkgName, structName, typeForValue(iresult, structName, tags, subStructMap, convertFloats))
src := fmt.Sprintf("\ntype %s %s\n", structName, typeForValue(iresult, structName, tags, subStructMap, convertFloats)) src := fmt.Sprintf("\ntype %s %s\n", structName, typeForValue(iresult, structName, tags, subStructMap, convertFloats))
// supplementary sub-structures // supplementary sub-structures
for k, v := range subStructMap { for k, v := range subStructMap {
@@ -141,7 +141,6 @@ func jyParse(input io.Reader, parser Parser, structName, pkgName string, tags []
return nil, fmt.Errorf("unexpected type: %T", iresult) return nil, fmt.Errorf("unexpected type: %T", iresult)
} }
//src := fmt.Sprintf("package %s\ntype %s %s}", pkgName, structName, generateTypes(result, structName, tags, 0, subStructMap, convertFloats))
src := fmt.Sprintf("\ntype %s %s}", structName, generateTypes(result, structName, tags, 0, subStructMap, convertFloats)) src := fmt.Sprintf("\ntype %s %s}", structName, generateTypes(result, structName, tags, 0, subStructMap, convertFloats))
keys := make([]string, 0, len(subStructMap)) keys := make([]string, 0, len(subStructMap))

View File

@@ -1,3 +1,4 @@
// Package krand is a library for generating random strings, integers, floating point numbers.
package krand package krand
import ( import (

View File

@@ -21,8 +21,8 @@ func Create(ctx context.Context, db *gorm.DB, table interface{}) error {
// Delete record // Delete record
// the param of 'table' must be pointer, eg: &StructName // the param of 'table' must be pointer, eg: &StructName
func Delete(ctx context.Context, db *gorm.DB, table interface{}, query interface{}, args ...interface{}) error { func Delete(ctx context.Context, db *gorm.DB, table interface{}, queryCondition interface{}, args ...interface{}) error {
return db.WithContext(ctx).Where(query, args...).Delete(table).Error return db.WithContext(ctx).Where(queryCondition, args...).Delete(table).Error
} }
// DeleteByID delete record by id // DeleteByID delete record by id
@@ -33,20 +33,20 @@ func DeleteByID(ctx context.Context, db *gorm.DB, table interface{}, id interfac
// Update record // Update record
// the param of 'table' must be pointer, eg: &StructName // the param of 'table' must be pointer, eg: &StructName
func Update(ctx context.Context, db *gorm.DB, table interface{}, column string, value interface{}, query interface{}, args ...interface{}) error { func Update(ctx context.Context, db *gorm.DB, table interface{}, column string, value interface{}, queryCondition interface{}, args ...interface{}) error {
return db.WithContext(ctx).Model(table).Where(query, args...).Update(column, value).Error return db.WithContext(ctx).Model(table).Where(queryCondition, args...).Update(column, value).Error
} }
// Updates record // Updates record
// the param of 'table' must be pointer, eg: &StructName // the param of 'table' must be pointer, eg: &StructName
func Updates(ctx context.Context, db *gorm.DB, table interface{}, update KV, query interface{}, args ...interface{}) error { func Updates(ctx context.Context, db *gorm.DB, table interface{}, update KV, queryCondition interface{}, args ...interface{}) error {
return db.WithContext(ctx).Model(table).Where(query, args...).Updates(update).Error return db.WithContext(ctx).Model(table).Where(queryCondition, args...).Updates(update).Error
} }
// Get one record // Get one record
// the param of 'table' must be pointer, eg: &StructName // the param of 'table' must be pointer, eg: &StructName
func Get(ctx context.Context, db *gorm.DB, table interface{}, query interface{}, args ...interface{}) error { func Get(ctx context.Context, db *gorm.DB, table interface{}, queryCondition interface{}, args ...interface{}) error {
return db.WithContext(ctx).Where(query, args...).First(table).Error return db.WithContext(ctx).Where(queryCondition, args...).First(table).Error
} }
// GetByID get record by id // GetByID get record by id
@@ -55,15 +55,15 @@ func GetByID(ctx context.Context, db *gorm.DB, table interface{}, id interface{}
} }
// List multiple records, starting from page 0 // List multiple records, starting from page 0
// the param of 'tables' must be slice, eg: []StructName // the param of 'tables' must be a slice, eg: []StructName
func List(ctx context.Context, db *gorm.DB, tables interface{}, page *query.Page, query interface{}, args ...interface{}) error { func List(ctx context.Context, db *gorm.DB, tables interface{}, page *query.Page, queryCondition interface{}, args ...interface{}) error {
return db.WithContext(ctx).Order(page.Sort()).Limit(page.Size()).Offset(page.Offset()).Where(query, args...).Find(tables).Error return db.WithContext(ctx).Order(page.Sort()).Limit(page.Size()).Offset(page.Offset()).Where(queryCondition, args...).Find(tables).Error
} }
// Count number of records // Count number of records
// the param of 'table' must be pointer, eg: &StructName // the param of 'table' must be pointer, eg: &StructName
func Count(ctx context.Context, db *gorm.DB, table interface{}, query interface{}, args ...interface{}) (int64, error) { func Count(ctx context.Context, db *gorm.DB, table interface{}, queryCondition interface{}, args ...interface{}) (int64, error) {
var count int64 var count int64
err := db.WithContext(ctx).Model(table).Where(query, args...).Count(&count).Error err := db.WithContext(ctx).Model(table).Where(queryCondition, args...).Count(&count).Error
return count, err return count, err
} }

View File

@@ -1,3 +1,4 @@
// Package mysql is a library wrapped on top of gorm.io/gorm, with added features such as link tracing, paging queries, etc.
package mysql package mysql
import ( import (

View File

@@ -1,3 +1,4 @@
// Package query is a library for mysql query, support for complex conditional paging queries.
package query package query
import ( import (
@@ -18,7 +19,7 @@ const (
Lt = "lt" Lt = "lt"
// Lte less than or equal // Lte less than or equal
Lte = "lte" Lte = "lte"
// Like like // Like fuzzy lookup
Like = "like" Like = "like"
// AND logic and // AND logic and
@@ -86,7 +87,7 @@ func (c *Column) convert() error {
if c.Exp == "" { if c.Exp == "" {
c.Exp = Eq c.Exp = Eq
} }
if v, ok := expMap[strings.ToLower(c.Exp)]; ok { if v, ok := expMap[strings.ToLower(c.Exp)]; ok { //nolint
c.Exp = v c.Exp = v
if c.Exp == " LIKE " { if c.Exp == " LIKE " {
c.Value = fmt.Sprintf("%%%v%%", c.Value) c.Value = fmt.Sprintf("%%%v%%", c.Value)
@@ -98,7 +99,7 @@ func (c *Column) convert() error {
if c.Logic == "" { if c.Logic == "" {
c.Logic = AND c.Logic = AND
} }
if v, ok := logicMap[strings.ToLower(c.Logic)]; ok { if v, ok := logicMap[strings.ToLower(c.Logic)]; ok { //nolint
c.Logic = v c.Logic = v
} else { } else {
return fmt.Errorf("unknown logic type '%s'", c.Logic) return fmt.Errorf("unknown logic type '%s'", c.Logic)
@@ -108,12 +109,12 @@ func (c *Column) convert() error {
} }
// ConvertToPage converted to conform to gorm rules based on the page size sort parameter // ConvertToPage converted to conform to gorm rules based on the page size sort parameter
func (p *Params) ConvertToPage() (order string, limit int, offset int) { func (p *Params) ConvertToPage() (order string, limit int, offset int) { //nolint
page := NewPage(p.Page, p.Size, p.Sort) page := NewPage(p.Page, p.Size, p.Sort)
order = page.sort order = page.sort
limit = page.size limit = page.size
offset = page.page * page.size offset = page.page * page.size
return return //nolint
} }
// ConvertToGormConditions conversion to gorm-compliant parameters based on the Columns parameter // ConvertToGormConditions conversion to gorm-compliant parameters based on the Columns parameter
@@ -205,9 +206,8 @@ func getExpsAndLogics(keyLen int, paramSrc string) ([]string, []string) { //noli
group = map[string]string{} group = map[string]string{}
continue continue
} else {
group[split[0]] = split[1]
} }
group[split[0]] = split[1]
} }
// handling the last group // handling the last group

View File

@@ -1,3 +1,4 @@
// Package nacoscli provides for getting the configuration from the nacos configuration center and parse it into a structure.
package nacoscli package nacoscli
import ( import (

View File

@@ -1,3 +1,4 @@
// Package prof is wrap the official `net/http/pprof` route and add the profile io wait time route.
package prof package prof
import ( import (
@@ -24,8 +25,8 @@ var (
timeFormat = "20060102T150405" timeFormat = "20060102T150405"
status uint32 status uint32
statusStart uint32 = 1 statusStart uint32 = 1 // status=1
statusStop uint32 = 0 statusStop uint32 // status=0
) )
// WaitSign wait system notification signals // WaitSign wait system notification signals
@@ -52,7 +53,7 @@ type profile struct {
files []string files []string
closeFns []func() closeFns []func()
ctx context.Context //ctx context.Context
stopCh chan struct{} stopCh chan struct{}
} }
@@ -113,7 +114,7 @@ func (p *profile) startProfile() {
} }
if isSamplingTrace { if isSamplingTrace {
err = p.trace() err = p.tracing()
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
} }
@@ -144,7 +145,8 @@ func (p *profile) stopProfile() {
default: default:
} }
p = NewProfile() // reset profile // reset profile
p = NewProfile() //nolint
} }
func (p *profile) checkTimeout() { func (p *profile) checkTimeout() {
@@ -283,7 +285,7 @@ func (p *profile) threadCreate() error {
return nil return nil
} }
func (p *profile) trace() error { func (p *profile) tracing() error {
profileName := "trace" profileName := "trace"
file := getFilePath(profileName) file := getFilePath(profileName)
f, err := os.Create(file) f, err := os.Create(file)
@@ -338,9 +340,9 @@ func getServerName() string {
} }
func joinPath(elem ...string) string { func joinPath(elem ...string) string {
path := strings.Join(elem, "/") dir := strings.Join(elem, "/")
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
return strings.ReplaceAll(path, "/", "\\") return strings.ReplaceAll(dir, "/", "\\")
} }
return path return dir
} }

View File

@@ -1,3 +1,5 @@
// Package replacer is a library of replacement file content, supports replacement of
// files in local directories and embedded directory files via embed.
package replacer package replacer
import ( import (
@@ -117,9 +119,8 @@ func (r *replacerInfo) SetSubDirsAndFiles(subDirs []string, subFiles ...string)
if isSubPath(file, dir) { if isSubPath(file, dir) {
if _, ok := isExistFile[file]; ok { if _, ok := isExistFile[file]; ok {
continue continue
} else {
isExistFile[file] = struct{}{}
} }
isExistFile[file] = struct{}{}
files = append(files, file) files = append(files, file)
} }
} }
@@ -127,9 +128,8 @@ func (r *replacerInfo) SetSubDirsAndFiles(subDirs []string, subFiles ...string)
if isMatchFile(file, sf) { if isMatchFile(file, sf) {
if _, ok := isExistFile[file]; ok { if _, ok := isExistFile[file]; ok {
continue continue
} else {
isExistFile[file] = struct{}{}
} }
isExistFile[file] = struct{}{}
files = append(files, file) files = append(files, file)
} }
} }
@@ -314,12 +314,13 @@ func isForbiddenFile(file string, path string) bool {
} }
func (r *replacerInfo) getNewFilePath(file string) string { func (r *replacerInfo) getNewFilePath(file string) string {
var newFilePath string //var newFilePath string
if r.isActual { //if r.isActual {
newFilePath = r.outPath + strings.Replace(file, r.path, "", 1) // newFilePath = r.outPath + strings.Replace(file, r.path, "", 1)
} else { //} else {
newFilePath = r.outPath + strings.Replace(file, r.path, "", 1) // newFilePath = r.outPath + strings.Replace(file, r.path, "", 1)
} //}
newFilePath := r.outPath + strings.Replace(file, r.path, "", 1)
if gofile.IsWindows() { if gofile.IsWindows() {
newFilePath = strings.ReplaceAll(newFilePath, "/", "\\") newFilePath = strings.ReplaceAll(newFilePath, "/", "\\")
@@ -372,7 +373,7 @@ func listFiles(path string, fs embed.FS) ([]string, error) {
return files, err return files, err
} }
// iterating through the embedded catalogue // iterating through the embedded catalog
func walkDir(dirPath string, allFiles *[]string, fs embed.FS) error { func walkDir(dirPath string, allFiles *[]string, fs embed.FS) error {
files, err := fs.ReadDir(dirPath) files, err := fs.ReadDir(dirPath)
if err != nil { if err != nil {

View File

@@ -58,7 +58,7 @@ func NewBuilder(d registry.Discovery, opts ...Option) resolver.Builder {
return b return b
} }
func (b *builder) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) { func (b *builder) Build(target resolver.Target, cc resolver.ClientConn, _ resolver.BuildOptions) (resolver.Resolver, error) {
var ( var (
err error err error
w registry.Watcher w registry.Watcher

View File

@@ -1,3 +1,4 @@
// Package discovery is service discovery library, supports etcd, consul and nacos.
package discovery package discovery
import ( import (
@@ -94,7 +95,7 @@ func (r *discoveryResolver) Close() {
} }
} }
func (r *discoveryResolver) ResolveNow(options resolver.ResolveNowOptions) {} func (r *discoveryResolver) ResolveNow(_ resolver.ResolveNowOptions) {}
func parseAttributes(md map[string]string) *attributes.Attributes { func parseAttributes(md map[string]string) *attributes.Attributes {
var a *attributes.Attributes var a *attributes.Attributes

View File

@@ -6,47 +6,64 @@ Service registry, corresponding to service [discovery](../discovery) corresponds
```go ```go
func registryService(scheme string, host string, port int) (registry.Registry, *registry.ServiceInstance) { func registryService(scheme string, host string, port int) (registry.Registry, *registry.ServiceInstance) {
instanceEndpoint := fmt.Sprintf("%s://%s:%d", scheme, host, port) var (
cfg := config.Get() instanceEndpoint = fmt.Sprintf("%s://%s:%d", scheme, host, port)
cfg = config.Get()
iRegistry registry.Registry
instance *registry.ServiceInstance
err error
id = cfg.App.Name + "_" + scheme + "_" + host
logField logger.Field
)
switch cfg.App.RegistryDiscoveryType { switch cfg.App.RegistryDiscoveryType {
// registering service with consul // registering service with consul
case "consul": case "consul":
iRegistry, instance, err := consul.NewRegistry( iRegistry, instance, err = consul.NewRegistry(
cfg.Consul.Addr, cfg.Consul.Addr,
cfg.App.Name+"_"+scheme+"_"+host, id,
cfg.App.Name, cfg.App.Name,
[]string{instanceEndpoint}, []string{instanceEndpoint},
) )
if err != nil { if err != nil {
panic(err) panic(err)
} }
return iRegistry, instance logField = logger.Any("consulAddress", cfg.Consul.Addr)
// registering service with etcd // registering service with etcd
case "etcd": case "etcd":
iRegistry, instance, err := etcd.NewRegistry( iRegistry, instance, err = etcd.NewRegistry(
cfg.Etcd.Addrs, cfg.Etcd.Addrs,
cfg.App.Name+"_"+scheme+"_"+host, id,
cfg.App.Name, cfg.App.Name,
[]string{instanceEndpoint}, []string{instanceEndpoint},
) )
if err != nil { if err != nil {
panic(err) panic(err)
} }
return iRegistry, instance logField = logger.Any("etcdAddress", cfg.Etcd.Addrs)
// registering service with nacos // registering service with nacos
case "nacos": case "nacos":
iRegistry, instance, err := nacos.NewRegistry( iRegistry, instance, err = nacos.NewRegistry(
cfg.NacosRd.IPAddr, cfg.NacosRd.IPAddr,
cfg.NacosRd.Port, cfg.NacosRd.Port,
cfg.NacosRd.NamespaceID, cfg.NacosRd.NamespaceID,
cfg.App.Name+"_"+scheme+"_"+host, id,
cfg.App.Name, cfg.App.Name,
[]string{instanceEndpoint}, []string{instanceEndpoint},
) )
if err != nil { if err != nil {
panic(err) panic(err)
} }
logField = logger.String("nacosAddress", fmt.Sprintf("%v:%d", cfg.NacosRd.IPAddr, cfg.NacosRd.Port))
}
if instance != nil {
msg := fmt.Sprintf("register service address to %s", cfg.App.RegistryDiscoveryType)
logger.Info(msg, logField, logger.String("id", id), logger.String("name", cfg.App.Name), logger.String("endpoint", instanceEndpoint))
return iRegistry, instance return iRegistry, instance
} }

View File

@@ -68,7 +68,7 @@ func (d *Client) Service(ctx context.Context, service string, index uint64, pass
} }
// Register register service instance to consul // Register register service instance to consul
func (d *Client) Register(ctx context.Context, svc *registry.ServiceInstance, enableHealthCheck bool) error { func (d *Client) Register(_ context.Context, svc *registry.ServiceInstance, enableHealthCheck bool) error {
addresses := make(map[string]api.ServiceAddress) addresses := make(map[string]api.ServiceAddress)
var addr string var addr string
var port uint64 var port uint64
@@ -120,7 +120,7 @@ func (d *Client) Register(ctx context.Context, svc *registry.ServiceInstance, en
} }
// Deregister deregister service by service ID // Deregister deregister service by service ID
func (d *Client) Deregister(ctx context.Context, serviceID string) error { func (d *Client) Deregister(_ context.Context, serviceID string) error {
d.cancel() d.cancel()
return d.client.Agent().ServiceDeregister(serviceID) return d.client.Agent().ServiceDeregister(serviceID)
} }

View File

@@ -1,3 +1,4 @@
// Package consul is registered as a service using consul.
package consul package consul
import ( import (
@@ -78,7 +79,7 @@ func (r *Registry) Deregister(ctx context.Context, svc *registry.ServiceInstance
} }
// GetService return service by name // GetService return service by name
func (r *Registry) GetService(ctx context.Context, name string) (services []*registry.ServiceInstance, err error) { func (r *Registry) GetService(_ context.Context, name string) (services []*registry.ServiceInstance, err error) {
r.lock.RLock() r.lock.RLock()
defer r.lock.RUnlock() defer r.lock.RUnlock()
set := r.registry[name] set := r.registry[name]
@@ -90,7 +91,7 @@ func (r *Registry) GetService(ctx context.Context, name string) (services []*reg
return nil, fmt.Errorf("service %s not found in registry", name) return nil, fmt.Errorf("service %s not found in registry", name)
} }
services = append(services, ss...) services = append(services, ss...)
return return //nolint
} }
// ListServices return service list. // ListServices return service list.
@@ -107,11 +108,11 @@ func (r *Registry) ListServices() (allServices map[string][]*registry.ServiceIns
services = append(services, ss...) services = append(services, ss...)
allServices[name] = services allServices[name] = services
} }
return return //nolint
} }
// Watch resolve service by name // Watch resolve service by name
func (r *Registry) Watch(ctx context.Context, name string) (registry.Watcher, error) { func (r *Registry) Watch(_ context.Context, name string) (registry.Watcher, error) {
r.lock.Lock() r.lock.Lock()
defer r.lock.Unlock() defer r.lock.Unlock()
set, ok := r.registry[name] set, ok := r.registry[name]

View File

@@ -27,7 +27,7 @@ func (w *watcher) Next() (services []*registry.ServiceInstance, err error) {
if ok { if ok {
services = append(services, ss...) services = append(services, ss...)
} }
return return //nolint
} }
func (w *watcher) Stop() error { func (w *watcher) Stop() error {

View File

@@ -1,3 +1,4 @@
// Package etcd is registered as a service using etcd.
package etcd package etcd
import ( import (
@@ -14,6 +15,7 @@ func marshal(si *registry.ServiceInstance) (string, error) {
return string(data), nil return string(data), nil
} }
// nolint
func unmarshal(data []byte) (si *registry.ServiceInstance, err error) { func unmarshal(data []byte) (si *registry.ServiceInstance, err error) {
err = json.Unmarshal(data, &si) err = json.Unmarshal(data, &si)
return return

View File

@@ -1,3 +1,4 @@
// Package nacos is registered as a service using nacos.
package nacos package nacos
import ( import (

View File

@@ -1,3 +1,4 @@
// Package registry is service registry library, supports etcd, consul and nacos.
package registry package registry
import "context" import "context"

View File

@@ -9,6 +9,7 @@ Circuit Breaker for web middleware and rpc interceptor.
**gin circuit breaker middleware** **gin circuit breaker middleware**
```go ```go
// CircuitBreaker a circuit breaker middleware
func CircuitBreaker(opts ...CircuitBreakerOption) gin.HandlerFunc { func CircuitBreaker(opts ...CircuitBreakerOption) gin.HandlerFunc {
o := defaultCircuitBreakerOptions() o := defaultCircuitBreakerOptions()
o.apply(opts...) o.apply(opts...)
@@ -16,8 +17,7 @@ func CircuitBreaker(opts ...CircuitBreakerOption) gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
breaker := o.group.Get(c.FullPath()).(circuitbreaker.CircuitBreaker) breaker := o.group.Get(c.FullPath()).(circuitbreaker.CircuitBreaker)
if err := breaker.Allow(); err != nil { if err := breaker.Allow(); err != nil {
// NOTE: when client reject request locally, // NOTE: when client reject request locally, keep adding counter let the drop ratio higher.
// continue to add counter let the drop ratio higher.
breaker.MarkFailed() breaker.MarkFailed()
response.Output(c, http.StatusServiceUnavailable, err.Error()) response.Output(c, http.StatusServiceUnavailable, err.Error())
c.Abort() c.Abort()
@@ -27,8 +27,9 @@ func CircuitBreaker(opts ...CircuitBreakerOption) gin.HandlerFunc {
c.Next() c.Next()
code := c.Writer.Status() code := c.Writer.Status()
// NOTE: need to check internal and service unavailable error // NOTE: need to check internal and service unavailable error, e.g. http.StatusInternalServerError
if code == http.StatusInternalServerError || code == http.StatusServiceUnavailable || code == http.StatusGatewayTimeout { _, isHit := o.validCodes[code]
if isHit {
breaker.MarkFailed() breaker.MarkFailed()
} else { } else {
breaker.MarkSuccess() breaker.MarkSuccess()
@@ -37,9 +38,12 @@ func CircuitBreaker(opts ...CircuitBreakerOption) gin.HandlerFunc {
} }
``` ```
<br>
**rpc server circuit breaker interceptor** **rpc server circuit breaker interceptor**
```go ```go
// UnaryServerCircuitBreaker server-side unary circuit breaker interceptor
func UnaryServerCircuitBreaker(opts ...CircuitBreakerOption) grpc.UnaryServerInterceptor { func UnaryServerCircuitBreaker(opts ...CircuitBreakerOption) grpc.UnaryServerInterceptor {
o := defaultCircuitBreakerOptions() o := defaultCircuitBreakerOptions()
o.apply(opts...) o.apply(opts...)
@@ -47,8 +51,7 @@ func UnaryServerCircuitBreaker(opts ...CircuitBreakerOption) grpc.UnaryServerInt
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
breaker := o.group.Get(info.FullMethod).(circuitbreaker.CircuitBreaker) breaker := o.group.Get(info.FullMethod).(circuitbreaker.CircuitBreaker)
if err := breaker.Allow(); err != nil { if err := breaker.Allow(); err != nil {
// NOTE: when client reject request locally, // NOTE: when client reject request locally, keep adding let the drop ratio higher.
// continue to add counter let the drop ratio higher.
breaker.MarkFailed() breaker.MarkFailed()
return nil, errcode.StatusServiceUnavailable.ToRPCErr(err.Error()) return nil, errcode.StatusServiceUnavailable.ToRPCErr(err.Error())
} }
@@ -57,7 +60,8 @@ func UnaryServerCircuitBreaker(opts ...CircuitBreakerOption) grpc.UnaryServerInt
if err != nil { if err != nil {
// NOTE: need to check internal and service unavailable error // NOTE: need to check internal and service unavailable error
s, ok := status.FromError(err) s, ok := status.FromError(err)
if ok && (s.Code() == codes.Internal || s.Code() == codes.Unavailable) { _, isHit := o.validCodes[s.Code()]
if ok && isHit {
breaker.MarkFailed() breaker.MarkFailed()
} else { } else {
breaker.MarkSuccess() breaker.MarkSuccess()

View File

@@ -1,3 +1,4 @@
// Package circuitbreaker is an adaptive circuit breaker library, support for use in gin middleware and grpc interceptors.
package circuitbreaker package circuitbreaker
import ( import (

View File

@@ -117,7 +117,7 @@ func (b *Breaker) summary() (success int64, total int64) {
} }
return 0 return 0
}) })
return return //nolint
} }
// Allow request if error returns nil. // Allow request if error returns nil.
@@ -147,8 +147,7 @@ func (b *Breaker) MarkSuccess() {
// MarkFailed mark request is failed. // MarkFailed mark request is failed.
func (b *Breaker) MarkFailed() { func (b *Breaker) MarkFailed() {
// NOTE: when client reject requets locally, continue add counter let the // NOTE: when client reject request locally, keep adding counter let the drop ratio higher.
// drop ratio higher.
b.stat.Add(0) b.stat.Add(0)
} }
@@ -156,5 +155,5 @@ func (b *Breaker) trueOnProba(proba float64) (truth bool) {
b.randLock.Lock() b.randLock.Lock()
truth = b.r.Float64() < proba truth = b.r.Float64() < proba
b.randLock.Unlock() b.randLock.Unlock()
return return truth
} }

View File

@@ -51,7 +51,7 @@ func (c *cgroup) CPUAcctUsagePerCPU() ([]uint64, error) {
return nil, err return nil, err
} }
var usage []uint64 var usage []uint64
for _, v := range strings.Fields(string(data)) { for _, v := range strings.Fields(data) {
var u uint64 var u uint64
if u, err = parseUint(v); err != nil { if u, err = parseUint(v); err != nil {
return nil, err return nil, err
@@ -90,7 +90,7 @@ func currentcGroup() (*cgroup, error) {
if err != nil { if err != nil {
return nil, err return nil, err
} }
defer fp.Close() defer fp.Close() //nolint
buf := bufio.NewReader(fp) buf := bufio.NewReader(fp)
for { for {
line, err := buf.ReadString('\n') line, err := buf.ReadString('\n')

View File

@@ -32,14 +32,14 @@ func newCgroupCPU() (cpu *cgroupCPU, err error) {
sets, err := cpuSets() sets, err := cpuSets()
if err != nil { if err != nil {
return return nil, err
} }
quota := float64(len(sets)) quota := float64(len(sets))
cq, err := cpuQuota() cq, err := cpuQuota()
if err == nil && cq != -1 { if err == nil && cq != -1 {
var period uint64 var period uint64
if period, err = cpuPeriod(); err != nil { if period, err = cpuPeriod(); err != nil {
return return nil, err
} }
limit := float64(cq) / float64(period) limit := float64(cq) / float64(period)
if limit < quota { if limit < quota {
@@ -50,11 +50,11 @@ func newCgroupCPU() (cpu *cgroupCPU, err error) {
preSystem, err := systemCPUUsage() preSystem, err := systemCPUUsage()
if err != nil { if err != nil {
return return nil, err
} }
preTotal, err := totalCPUUsage() preTotal, err := totalCPUUsage()
if err != nil { if err != nil {
return return nil, err
} }
cpu = &cgroupCPU{ cpu = &cgroupCPU{
frequency: maxFreq, frequency: maxFreq,
@@ -63,7 +63,7 @@ func newCgroupCPU() (cpu *cgroupCPU, err error) {
preSystem: preSystem, preSystem: preSystem,
preTotal: preTotal, preTotal: preTotal,
} }
return return cpu, nil
} }
func (cpu *cgroupCPU) Usage() (u uint64, err error) { func (cpu *cgroupCPU) Usage() (u uint64, err error) {
@@ -73,18 +73,18 @@ func (cpu *cgroupCPU) Usage() (u uint64, err error) {
) )
total, err = totalCPUUsage() total, err = totalCPUUsage()
if err != nil { if err != nil {
return return 0, err
} }
system, err = systemCPUUsage() system, err = systemCPUUsage()
if err != nil { if err != nil {
return return 0, err
} }
if system != cpu.preSystem { if system != cpu.preSystem {
u = uint64(float64((total-cpu.preTotal)*cpu.cores*1e3) / (float64(system-cpu.preSystem) * cpu.quota)) u = uint64(float64((total-cpu.preTotal)*cpu.cores*1e3) / (float64(system-cpu.preSystem) * cpu.quota))
} }
cpu.preSystem = system cpu.preSystem = system
cpu.preTotal = total cpu.preTotal = total
return return u, err
} }
func (cpu *cgroupCPU) Info() Info { func (cpu *cgroupCPU) Info() Info {
@@ -115,45 +115,44 @@ func systemCPUUsage() (usage uint64, err error) {
f *os.File f *os.File
) )
if f, err = os.Open("/proc/stat"); err != nil { if f, err = os.Open("/proc/stat"); err != nil {
return return usage, err
} }
bufReader := bufio.NewReaderSize(nil, 128) bufReader := bufio.NewReaderSize(nil, 128)
defer func() { defer func() {
bufReader.Reset(nil) bufReader.Reset(nil)
f.Close() _ = f.Close()
}() }()
bufReader.Reset(f) bufReader.Reset(f)
for err == nil { for err == nil {
if line, err = bufReader.ReadString('\n'); err != nil { if line, err = bufReader.ReadString('\n'); err != nil {
return return usage, err
} }
parts := strings.Fields(line) parts := strings.Fields(line)
switch parts[0] { if parts[0] == "cpu" {
case "cpu":
if len(parts) < 8 { if len(parts) < 8 {
err = errors.New("bad format of cpu stats") err = errors.New("bad format of cpu stats")
return return usage, err
} }
var totalClockTicks uint64 var totalClockTicks uint64
for _, i := range parts[1:8] { for _, i := range parts[1:8] {
var v uint64 var v uint64
if v, err = strconv.ParseUint(i, 10, 64); err != nil { if v, err = strconv.ParseUint(i, 10, 64); err != nil {
return return usage, err
} }
totalClockTicks += v totalClockTicks += v
} }
usage = (totalClockTicks * nanoSecondsPerSecond) / clockTicksPerSecond usage = (totalClockTicks * nanoSecondsPerSecond) / clockTicksPerSecond
return return usage, nil
} }
} }
err = errors.New("bad stats format") err = errors.New("bad stats format")
return return usage, err
} }
func totalCPUUsage() (usage uint64, err error) { func totalCPUUsage() (usage uint64, err error) {
var cg *cgroup var cg *cgroup
if cg, err = currentcGroup(); err != nil { if cg, err = currentcGroup(); err != nil {
return return 0, err
} }
return cg.CPUAcctUsage() return cg.CPUAcctUsage()
} }
@@ -161,7 +160,7 @@ func totalCPUUsage() (usage uint64, err error) {
func perCPUUsage() (usage []uint64, err error) { func perCPUUsage() (usage []uint64, err error) {
var cg *cgroup var cg *cgroup
if cg, err = currentcGroup(); err != nil { if cg, err = currentcGroup(); err != nil {
return return nil, err
} }
return cg.CPUAcctUsagePerCPU() return cg.CPUAcctUsagePerCPU()
} }
@@ -169,7 +168,7 @@ func perCPUUsage() (usage []uint64, err error) {
func cpuSets() (sets []uint64, err error) { func cpuSets() (sets []uint64, err error) {
var cg *cgroup var cg *cgroup
if cg, err = currentcGroup(); err != nil { if cg, err = currentcGroup(); err != nil {
return return nil, err
} }
return cg.CPUSetCPUs() return cg.CPUSetCPUs()
} }
@@ -177,7 +176,7 @@ func cpuSets() (sets []uint64, err error) {
func cpuQuota() (quota int64, err error) { func cpuQuota() (quota int64, err error) {
var cg *cgroup var cg *cgroup
if cg, err = currentcGroup(); err != nil { if cg, err = currentcGroup(); err != nil {
return return 0, err
} }
return cg.CPUCFSQuotaUs() return cg.CPUCFSQuotaUs()
} }
@@ -185,7 +184,7 @@ func cpuQuota() (quota int64, err error) {
func cpuPeriod() (peroid uint64, err error) { func cpuPeriod() (peroid uint64, err error) {
var cg *cgroup var cg *cgroup
if cg, err = currentcGroup(); err != nil { if cg, err = currentcGroup(); err != nil {
return return 0, err
} }
return cg.CPUCFSPeriodUs() return cg.CPUCFSPeriodUs()
} }

View File

@@ -1,3 +1,4 @@
// Package cpu is a library that calculates cpu and memory usage.
package cpu package cpu
import ( import (
@@ -10,36 +11,36 @@ type psutilCPU struct {
interval time.Duration interval time.Duration
} }
func newPsutilCPU(interval time.Duration) (cpu *psutilCPU, err error) { func newPsutilCPU(interval time.Duration) (*psutilCPU, error) {
cpu = &psutilCPU{interval: interval} psCPU := &psutilCPU{interval: interval}
_, err = cpu.Usage() _, err := psCPU.Usage()
if err != nil { if err != nil {
return return nil, err
} }
return return psCPU, nil
} }
func (ps *psutilCPU) Usage() (u uint64, err error) { func (ps *psutilCPU) Usage() (uint64, error) {
var percents []float64 var u uint64
percents, err = cpu.Percent(ps.interval, false) percents, err := cpu.Percent(ps.interval, false)
if err == nil { if err == nil {
u = uint64(percents[0] * 10) u = uint64(percents[0] * 10)
} }
return return u, err
} }
func (ps *psutilCPU) Info() (info Info) { func (ps *psutilCPU) Info() Info {
stats, err := cpu.Info() stats, err := cpu.Info()
if err != nil { if err != nil {
return return Info{}
} }
cores, err := cpu.Counts(true) cores, err := cpu.Counts(true)
if err != nil { if err != nil {
return return Info{}
} }
info = Info{
return Info{
Frequency: uint64(stats[0].Mhz), Frequency: uint64(stats[0].Mhz),
Quota: float64(cores), Quota: float64(cores),
} }
return
} }

View File

@@ -3,14 +3,13 @@ package cpu
import ( import (
"bufio" "bufio"
"fmt" "fmt"
"io/ioutil"
"os" "os"
"strconv" "strconv"
"strings" "strings"
) )
func readFile(path string) (string, error) { func readFile(path string) (string, error) {
contents, err := ioutil.ReadFile(path) contents, err := os.ReadFile(path)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -101,7 +100,7 @@ func readLinesOffsetN(filename string, offset uint, n int) ([]string, error) {
if err != nil { if err != nil {
return []string{""}, err return []string{""}, err
} }
defer f.Close() defer f.Close() //nolint
var ret []string var ret []string

View File

@@ -1,3 +1,4 @@
// Package ratelimit is an adaptive rate limit library, support for use in gin middleware and grpc interceptors.
package ratelimit package ratelimit
import ( import (
@@ -252,9 +253,8 @@ func (l *BBR) shouldDrop() bool {
// accept current request // accept current request
return false return false
} }
if time.Duration(now-prevDropTime) <= time.Second { if now-prevDropTime <= time.Second {
// just start drop one second ago, // just start drop one second ago, check current inflight count
// check current inflight count
inFlight := atomic.LoadInt64(&l.inFlight) inFlight := atomic.LoadInt64(&l.inFlight)
return inFlight > 1 && inFlight > l.maxInFlight() return inFlight > 1 && inFlight > l.maxInFlight()
} }
@@ -297,8 +297,7 @@ func (l *BBR) Allow() (DoneFunc, error) {
start := time.Now().UnixNano() start := time.Now().UnixNano()
ms := float64(time.Millisecond) ms := float64(time.Millisecond)
return func(DoneInfo) { return func(DoneInfo) {
//nolint rt := int64(math.Ceil(float64(time.Now().UnixNano()-start)) / ms) //nolint
rt := int64(math.Ceil(float64(time.Now().UnixNano()-start)) / ms)
l.rtStat.Add(rt) l.rtStat.Add(rt)
atomic.AddInt64(&l.inFlight, -1) atomic.AddInt64(&l.inFlight, -1)
l.passStat.Add(1) l.passStat.Add(1)

View File

@@ -1,3 +1,4 @@
// Package window is a library that calculates windows cpu and memory usage.
package window package window
// Bucket contains multiple float64 points. // Bucket contains multiple float64 points.

View File

@@ -1,3 +1,5 @@
// Package parser is a library that parses to go structures based on sql
// and generates the code needed based on the template.
package parser package parser
import ( import (
@@ -68,9 +70,9 @@ func ParseSQL(sql string, options ...Option) (map[string]string, error) {
tableNames := make([]string, 0, len(stmts)) tableNames := make([]string, 0, len(stmts))
for _, stmt := range stmts { for _, stmt := range stmts {
if ct, ok := stmt.(*ast.CreateTableStmt); ok { if ct, ok := stmt.(*ast.CreateTableStmt); ok {
code, err := makeCode(ct, opt) //nolint code, err2 := makeCode(ct, opt)
if err != nil { if err2 != nil {
return nil, err return nil, err2
} }
modelStructCodes = append(modelStructCodes, code.modelStruct) modelStructCodes = append(modelStructCodes, code.modelStruct)
updateFieldsCodes = append(updateFieldsCodes, code.updateFields) updateFieldsCodes = append(updateFieldsCodes, code.updateFields)
@@ -150,12 +152,12 @@ func (t tmplField) ConditionZero() string {
// GoZero type of 0 // GoZero type of 0
func (t tmplField) GoZero() string { func (t tmplField) GoZero() string {
switch t.GoType { switch t.GoType {
case "int8", "int16", "int32", "int64", "int", "uint8", "uint16", "uint32", "uint64", "uint", "float64", "float32", //nolint case "int8", "int16", "int32", "int64", "int", "uint8", "uint16", "uint32", "uint64", "uint", "float64", "float32",
"sql.NullInt32", "sql.NullInt64", "sql.NullFloat64": //nolint "sql.NullInt32", "sql.NullInt64", "sql.NullFloat64":
return `= 0` return `= 0`
case "string", "sql.NullString": //nolint case "string", "sql.NullString":
return `= "string"` return `= "string"`
case "time.Time", "*time.Time", "sql.NullTime": //nolint case "time.Time", "*time.Time", "sql.NullTime":
return `= "0000-01-00T00:00:00.000+08:00"` return `= "0000-01-00T00:00:00.000+08:00"`
} }
@@ -165,12 +167,12 @@ func (t tmplField) GoZero() string {
// GoTypeZero type of 0 // GoTypeZero type of 0
func (t tmplField) GoTypeZero() string { func (t tmplField) GoTypeZero() string {
switch t.GoType { switch t.GoType {
case "int8", "int16", "int32", "int64", "int", "uint8", "uint16", "uint32", "uint64", "uint", "float64", "float32", //nolint case "int8", "int16", "int32", "int64", "int", "uint8", "uint16", "uint32", "uint64", "uint", "float64", "float32",
"sql.NullInt32", "sql.NullInt64", "sql.NullFloat64": //nolint "sql.NullInt32", "sql.NullInt64", "sql.NullFloat64":
return `0` return `0`
case "string", "sql.NullString": //nolint case "string", "sql.NullString":
return `""` return `""`
case "time.Time", "*time.Time", "sql.NullTime": //nolint case "time.Time", "*time.Time", "sql.NullTime":
return `0 /*time.Now().Second()*/` return `0 /*time.Now().Second()*/`
} }
@@ -209,7 +211,6 @@ const (
columnMysqlModel = __mysqlModel__ columnMysqlModel = __mysqlModel__
) )
// nolint
var ignoreColumns = map[string]struct{}{ var ignoreColumns = map[string]struct{}{
columnID: {}, columnID: {},
columnCreatedAt: {}, columnCreatedAt: {},
@@ -481,6 +482,8 @@ func getModelCode(data modelCodes) (string, error) {
} }
func getUpdateFieldsCode(data tmplData, isEmbed bool) (string, error) { func getUpdateFieldsCode(data tmplData, isEmbed bool) (string, error) {
_ = isEmbed
// filter fields // filter fields
var newFields = []tmplField{} var newFields = []tmplField{}
for _, field := range data.Fields { for _, field := range data.Fields {
@@ -525,7 +528,7 @@ func getHandlerStructCodes(data tmplData) (string, error) {
return postStructCode + putStructCode + getStructCode, nil return postStructCode + putStructCode + getStructCode, nil
} }
// customised filter fields // customized filter fields
func tmplExecuteWithFilter(data tmplData, tmpl *template.Template, reservedColumns ...string) (string, error) { func tmplExecuteWithFilter(data tmplData, tmpl *template.Template, reservedColumns ...string) (string, error) {
var newFields = []tmplField{} var newFields = []tmplField{}
for _, field := range data.Fields { for _, field := range data.Fields {
@@ -668,13 +671,13 @@ func mysqlToGoType(colTp *types.FieldType, style NullStyle) (name string, path s
name = "sql.NullFloat64" name = "sql.NullFloat64"
case mysql.TypeString, mysql.TypeVarchar, mysql.TypeVarString, case mysql.TypeString, mysql.TypeVarchar, mysql.TypeVarString,
mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob: mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob:
name = "sql.NullString" //nolint name = "sql.NullString"
case mysql.TypeTimestamp, mysql.TypeDatetime, mysql.TypeDate: case mysql.TypeTimestamp, mysql.TypeDatetime, mysql.TypeDate:
name = "sql.NullTime" name = "sql.NullTime"
case mysql.TypeDecimal, mysql.TypeNewDecimal: case mysql.TypeDecimal, mysql.TypeNewDecimal:
name = "sql.NullString" //nolint name = "sql.NullString"
case mysql.TypeJSON: case mysql.TypeJSON:
name = "sql.NullString" //nolint name = "sql.NullString"
default: default:
return "UnSupport", "" return "UnSupport", ""
} }
@@ -690,7 +693,7 @@ func mysqlToGoType(colTp *types.FieldType, style NullStyle) (name string, path s
if mysql.HasUnsignedFlag(colTp.Flag) { if mysql.HasUnsignedFlag(colTp.Flag) {
name = "uint64" name = "uint64"
} else { } else {
name = "int64" //nolint name = "int64"
} }
case mysql.TypeFloat, mysql.TypeDouble: case mysql.TypeFloat, mysql.TypeDouble:
name = "float64" name = "float64"
@@ -711,7 +714,7 @@ func mysqlToGoType(colTp *types.FieldType, style NullStyle) (name string, path s
name = "*" + name name = "*" + name
} }
} }
return return name, path
} }
func goTypeToProto(fields []tmplField) []tmplField { func goTypeToProto(fields []tmplField) []tmplField {
@@ -758,7 +761,7 @@ func getDefaultValue(expr ast.ExprNode) (value string) {
} }
} }
} }
return return value
} }
var acronym = map[string]struct{}{ var acronym = map[string]struct{}{

View File

@@ -1,9 +1,10 @@
package parser package parser
import ( import (
"github.com/pkg/errors"
"sync" "sync"
"text/template" "text/template"
"github.com/pkg/errors"
) )
var ( var (

View File

@@ -1,3 +1,6 @@
// Package sql2code provides for generating code for different purposes according to sql,
// support generating json, gorm model, update parameter, request parameter code,
// sql can be obtained from parameter, file, db three ways, priority from high to low.
package sql2code package sql2code
import ( import (

View File

@@ -1,3 +1,4 @@
// Package cpu is a library that counts system and process cpu usage.
package cpu package cpu
import ( import (

View File

@@ -1,3 +1,4 @@
// Package mem is a library that counts system and process memory usage.
package mem package mem
import ( import (

View File

@@ -3,14 +3,21 @@
package stat package stat
import "syscall" import (
"fmt"
"syscall"
)
// nolint
func init() { func init() {
go func() { go func() {
for { for {
select { select {
case <-notifyCh: case <-notifyCh:
syscall.Kill(syscall.Getpid(), syscall.SIGTRAP) err := syscall.Kill(syscall.Getpid(), syscall.SIGTRAP)
if err != nil {
fmt.Println(err)
}
} }
} }
}() }()

View File

@@ -1,3 +1,4 @@
// Package stat provides for counting system and process cpu and memory information, alarm notification support.
package stat package stat
import ( import (
@@ -68,6 +69,7 @@ func Init(opts ...Option) {
o := &options{} o := &options{}
o.apply(opts...) o.apply(opts...)
//nolint
go func() { go func() {
printTick := time.NewTicker(printInfoInterval) printTick := time.NewTicker(printInfoInterval)
defer printTick.Stop() defer printTick.Stop()
@@ -87,16 +89,16 @@ func Init(opts ...Option) {
}() }()
} }
// nolint
func sendSystemSignForLinux() { func sendSystemSignForLinux() {
select { select {
case notifyCh <- struct{}{}: case notifyCh <- struct{}{}:
default: default:
} }
} }
func printUsageInfo() *statData { func printUsageInfo() *statData {
defer func() { recover() }() defer func() { _ = recover() }()
mSys := mem.GetSystemMemory() mSys := mem.GetSystemMemory()
mProc := mem.GetProcessMemory() mProc := mem.GetProcessMemory()

View File

@@ -5,13 +5,12 @@ import (
"os" "os"
"go.opentelemetry.io/otel/exporters/stdout/stdouttrace" "go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
stdout "go.opentelemetry.io/otel/exporters/stdout/stdouttrace"
sdkTrace "go.opentelemetry.io/otel/sdk/trace" sdkTrace "go.opentelemetry.io/otel/sdk/trace"
) )
// NewConsoleExporter output to console // NewConsoleExporter output to console
func NewConsoleExporter() (sdkTrace.SpanExporter, error) { func NewConsoleExporter() (sdkTrace.SpanExporter, error) {
return stdout.New(stdout.WithPrettyPrint()) return stdouttrace.New(stdouttrace.WithPrettyPrint())
} }
// NewFileExporter output to file, note: close the file before ending // NewFileExporter output to file, note: close the file before ending
@@ -37,9 +36,9 @@ func NewFileExporter(filename string) (sdkTrace.SpanExporter, *os.File, error) {
func newExporter(w io.Writer) (sdkTrace.SpanExporter, error) { func newExporter(w io.Writer) (sdkTrace.SpanExporter, error) {
return stdouttrace.New( return stdouttrace.New(
stdouttrace.WithWriter(w), stdouttrace.WithWriter(w),
// Use human readable output. // output to console.
stdouttrace.WithPrettyPrint(), stdouttrace.WithPrettyPrint(),
// Do not print timestamps for the demo. // do not print timestamps for the demo.
stdouttrace.WithoutTimestamps(), stdouttrace.WithoutTimestamps(),
) )
} }

View File

@@ -22,6 +22,7 @@ func SetTraceName(name string) {
func NewSpan(ctx context.Context, spanName string, tags map[string]interface{}) (context.Context, trace.Span) { func NewSpan(ctx context.Context, spanName string, tags map[string]interface{}) (context.Context, trace.Span) {
var opts []trace.SpanStartOption var opts []trace.SpanStartOption
//nolint
for k, v := range tags { for k, v := range tags {
var tag attribute.KeyValue var tag attribute.KeyValue
switch v.(type) { switch v.(type) {

View File

@@ -1,3 +1,4 @@
// Package tracer is a library wrapped in go.opentelemetry.io/otel.
package tracer package tracer
import ( import (

View File

@@ -1,3 +1,4 @@
// Package utils is a library of commonly used utility functions.
package utils package utils
import ( import (
@@ -16,14 +17,14 @@ func GetHostname() string {
} }
// GetLocalHTTPAddrPairs get available http server and request address // GetLocalHTTPAddrPairs get available http server and request address
func GetLocalHTTPAddrPairs() (string, string) { func GetLocalHTTPAddrPairs() (serverAddr string, requestAddr string) {
port, err := GetAvailablePort() port, err := GetAvailablePort()
if err != nil { if err != nil {
fmt.Printf("GetAvailablePort error: %v\n", err) fmt.Printf("GetAvailablePort error: %v\n", err)
return "", "" return "", ""
} }
serverAddr := fmt.Sprintf(":%d", port) serverAddr = fmt.Sprintf(":%d", port)
requestAddr := fmt.Sprintf("http://127.0.0.1:%d", port) requestAddr = fmt.Sprintf("http://127.0.0.1:%d", port)
return serverAddr, requestAddr return serverAddr, requestAddr
} }