mirror of
https://github.com/zeromicro/go-zero.git
synced 2026-05-12 01:10:00 +08:00
Compare commits
56 Commits
tools/goct
...
v1.6.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3866b5741a | ||
|
|
5fbe8ff5c4 | ||
|
|
6f763f71f9 | ||
|
|
80377f18e7 | ||
|
|
8690859c7d | ||
|
|
d744038198 | ||
|
|
58ad8cac8a | ||
|
|
74886a151e | ||
|
|
c5eda1f155 | ||
|
|
b5b7c054ca | ||
|
|
6c8073b691 | ||
|
|
64d430d424 | ||
|
|
f138cc792e | ||
|
|
b20ec8aedb | ||
|
|
a53254fa91 | ||
|
|
08563482e5 | ||
|
|
968727412d | ||
|
|
6f3d094eba | ||
|
|
2d3ebb9b62 | ||
|
|
8c0bb27136 | ||
|
|
cf987295df | ||
|
|
8c92b3af7d | ||
|
|
5dd9342703 | ||
|
|
3ef59f6a71 | ||
|
|
f12802abc7 | ||
|
|
6f0fe67804 | ||
|
|
f44f0e7e62 | ||
|
|
cdd95296db | ||
|
|
3e794cf991 | ||
|
|
bbce95e7e1 | ||
|
|
0449450c64 | ||
|
|
9f9a12ea57 | ||
|
|
cc2a7e97f9 | ||
|
|
09d7af76af | ||
|
|
c233a66601 | ||
|
|
94fa12560c | ||
|
|
7d90f906f5 | ||
|
|
f372b98d96 | ||
|
|
459d3025c5 | ||
|
|
e9e55125a9 | ||
|
|
159ecb7386 | ||
|
|
69bb746a1d | ||
|
|
d184f96b13 | ||
|
|
c7dacb0146 | ||
|
|
2207477b60 | ||
|
|
105ab590ff | ||
|
|
2f4c58ed73 | ||
|
|
1631aa02ad | ||
|
|
4df10eef5d | ||
|
|
3d552ea7a8 | ||
|
|
74b87ac9fd | ||
|
|
ba1d6e3664 | ||
|
|
2096cd5749 | ||
|
|
2eb2fa26f6 | ||
|
|
bc4187ca90 | ||
|
|
b7be25b98b |
16
SECURITY.md
Normal file
16
SECURITY.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
We publish releases monthly.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| >= 1.4.4 | :white_check_mark: |
|
||||
| < 1.4.4 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
https://github.com/zeromicro/go-zero/security/advisories
|
||||
|
||||
Accepted vulnerabilities are expected to be fixed within a month.
|
||||
@@ -130,7 +130,7 @@ func (r *redisBitSet) check(ctx context.Context, offsets []uint) (bool, error) {
|
||||
}
|
||||
|
||||
resp, err := r.store.ScriptRunCtx(ctx, testScript, []string{r.key}, args)
|
||||
if err == redis.Nil {
|
||||
if errors.Is(err, redis.Nil) {
|
||||
return false, nil
|
||||
} else if err != nil {
|
||||
return false, err
|
||||
@@ -162,7 +162,7 @@ func (r *redisBitSet) set(ctx context.Context, offsets []uint) error {
|
||||
}
|
||||
|
||||
_, err = r.store.ScriptRunCtx(ctx, setScript, []string{r.key}, args)
|
||||
if err == redis.Nil {
|
||||
if errors.Is(err, redis.Nil) {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -31,9 +31,10 @@ type (
|
||||
Name() string
|
||||
|
||||
// Allow checks if the request is allowed.
|
||||
// If allowed, a promise will be returned, the caller needs to call promise.Accept()
|
||||
// on success, or call promise.Reject() on failure.
|
||||
// If not allow, ErrServiceUnavailable will be returned.
|
||||
// If allowed, a promise will be returned,
|
||||
// otherwise ErrServiceUnavailable will be returned as the error.
|
||||
// The caller needs to call promise.Accept() on success,
|
||||
// or call promise.Reject() on failure.
|
||||
Allow() (Promise, error)
|
||||
|
||||
// Do runs the given request if the Breaker accepts it.
|
||||
|
||||
@@ -52,6 +52,7 @@ func (b *googleBreaker) accept() error {
|
||||
|
||||
func (b *googleBreaker) allow() (internalPromise, error) {
|
||||
if err := b.accept(); err != nil {
|
||||
b.markFailure()
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ var (
|
||||
zero = big.NewInt(0)
|
||||
)
|
||||
|
||||
// DhKey defines the Diffie Hellman key.
|
||||
// DhKey defines the Diffie-Hellman key.
|
||||
type DhKey struct {
|
||||
PriKey *big.Int
|
||||
PubKey *big.Int
|
||||
@@ -46,7 +46,7 @@ func ComputeKey(pubKey, priKey *big.Int) (*big.Int, error) {
|
||||
return new(big.Int).Exp(pubKey, priKey, p), nil
|
||||
}
|
||||
|
||||
// GenerateKey returns a Diffie Hellman key.
|
||||
// GenerateKey returns a Diffie-Hellman key.
|
||||
func GenerateKey() (*DhKey, error) {
|
||||
var err error
|
||||
var x *big.Int
|
||||
|
||||
@@ -128,8 +128,8 @@ func (c *Cache) Take(key string, fetch func() (any, error)) (any, error) {
|
||||
|
||||
var fresh bool
|
||||
val, err := c.barrier.Do(key, func() (any, error) {
|
||||
// because O(1) on map search in memory, and fetch is an IO query
|
||||
// so we do double check, cache might be taken by another call
|
||||
// because O(1) on map search in memory, and fetch is an IO query,
|
||||
// so we do double-check, cache might be taken by another call
|
||||
if val, ok := c.doGet(key); ok {
|
||||
return val, nil
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ func addOrMergeFields(info *fieldInfo, key string, child *fieldInfo, fullName st
|
||||
return newConflictKeyError(fullName)
|
||||
}
|
||||
|
||||
if err := mergeFields(prev, key, child.children, fullName); err != nil {
|
||||
if err := mergeFields(prev, child.children, fullName); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
@@ -281,7 +281,7 @@ func getTagName(field reflect.StructField) string {
|
||||
return field.Name
|
||||
}
|
||||
|
||||
func mergeFields(prev *fieldInfo, key string, children map[string]*fieldInfo, fullName string) error {
|
||||
func mergeFields(prev *fieldInfo, children map[string]*fieldInfo, fullName string) error {
|
||||
if len(prev.children) == 0 || len(children) == 0 {
|
||||
return newConflictKeyError(fullName)
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ func (c *cluster) load(cli EtcdClient, key string) int64 {
|
||||
break
|
||||
}
|
||||
|
||||
logx.Error(err)
|
||||
logx.Errorf("%s, key is %s", err.Error(), key)
|
||||
time.Sleep(coolDownInterval)
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import "gopkg.in/cheggaaa/pb.v1"
|
||||
type (
|
||||
// A Scanner is used to read lines.
|
||||
Scanner interface {
|
||||
// Scan checks if has remaining to read.
|
||||
// Scan checks if it has remaining to read.
|
||||
Scan() bool
|
||||
// Text returns next line.
|
||||
Text() string
|
||||
|
||||
@@ -352,7 +352,7 @@ func (s Stream) Parallel(fn ParallelFunc, opts ...Option) {
|
||||
}, opts...).Done()
|
||||
}
|
||||
|
||||
// Reduce is an utility method to let the caller deal with the underlying channel.
|
||||
// Reduce is a utility method to let the caller deal with the underlying channel.
|
||||
func (s Stream) Reduce(fn ReduceFunc) (any, error) {
|
||||
return fn(s.source)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package iox
|
||||
|
||||
import "os"
|
||||
|
||||
// RedirectInOut redirects stdin to r, stdout to w, and callers need to call restore afterwards.
|
||||
// RedirectInOut redirects stdin to r, stdout to w, and callers need to call restore afterward.
|
||||
func RedirectInOut() (restore func(), err error) {
|
||||
var r, w *os.File
|
||||
r, w, err = os.Pipe()
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
const bufSize = 32 * 1024
|
||||
|
||||
// CountLines returns the number of lines in file.
|
||||
// CountLines returns the number of lines in the file.
|
||||
func CountLines(file string) (int, error) {
|
||||
f, err := os.Open(file)
|
||||
if err != nil {
|
||||
|
||||
@@ -2,11 +2,12 @@ package iox
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// A TextLineScanner is a scanner that can scan lines from given reader.
|
||||
// A TextLineScanner is a scanner that can scan lines from the given reader.
|
||||
type TextLineScanner struct {
|
||||
reader *bufio.Reader
|
||||
hasNext bool
|
||||
@@ -14,7 +15,7 @@ type TextLineScanner struct {
|
||||
err error
|
||||
}
|
||||
|
||||
// NewTextLineScanner returns a TextLineScanner with given reader.
|
||||
// NewTextLineScanner returns a TextLineScanner with the given reader.
|
||||
func NewTextLineScanner(reader io.Reader) *TextLineScanner {
|
||||
return &TextLineScanner{
|
||||
reader: bufio.NewReader(reader),
|
||||
@@ -30,7 +31,7 @@ func (scanner *TextLineScanner) Scan() bool {
|
||||
|
||||
line, err := scanner.reader.ReadString('\n')
|
||||
scanner.line = strings.TrimRight(line, "\n")
|
||||
if err == io.EOF {
|
||||
if errors.Is(err, io.EOF) {
|
||||
scanner.hasNext = false
|
||||
return true
|
||||
} else if err != nil {
|
||||
|
||||
@@ -125,7 +125,7 @@ func (lim *TokenLimiter) reserveN(ctx context.Context, now time.Time, n int) boo
|
||||
})
|
||||
// redis allowed == false
|
||||
// Lua boolean false -> r Nil bulk reply
|
||||
if err == redis.Nil {
|
||||
if errors.Is(err, redis.Nil) {
|
||||
return false
|
||||
}
|
||||
if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) {
|
||||
|
||||
@@ -138,10 +138,10 @@ func (as *adaptiveShedder) Allow() (Promise, error) {
|
||||
func (as *adaptiveShedder) addFlying(delta int64) {
|
||||
flying := atomic.AddInt64(&as.flying, delta)
|
||||
// update avgFlying when the request is finished.
|
||||
// this strategy makes avgFlying have a little bit lag against flying, and smoother.
|
||||
// this strategy makes avgFlying have a little bit of lag against flying, and smoother.
|
||||
// when the flying requests increase rapidly, avgFlying increase slower, accept more requests.
|
||||
// when the flying requests drop rapidly, avgFlying drop slower, accept fewer requests.
|
||||
// it makes the service to serve as more requests as possible.
|
||||
// it makes the service to serve as many requests as possible.
|
||||
if delta < 0 {
|
||||
as.avgFlyingLock.Lock()
|
||||
as.avgFlying = as.avgFlying*flyingBeta + float64(flying)*(1-flyingBeta)
|
||||
@@ -200,7 +200,7 @@ func (as *adaptiveShedder) minRt() float64 {
|
||||
func (as *adaptiveShedder) overloadFactor() float64 {
|
||||
// as.cpuThreshold must be less than cpuMax
|
||||
factor := (cpuMax - float64(stat.CpuUsage())) / (cpuMax - float64(as.cpuThreshold))
|
||||
// at least accept 10% of acceptable requests even cpu is highly overloaded.
|
||||
// at least accept 10% of acceptable requests, even cpu is highly overloaded.
|
||||
return mathx.Between(factor, overloadFactorLowerBound, 1)
|
||||
}
|
||||
|
||||
@@ -250,14 +250,14 @@ func (as *adaptiveShedder) systemOverloaded() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// WithBuckets customizes the Shedder with given number of buckets.
|
||||
// WithBuckets customizes the Shedder with the given number of buckets.
|
||||
func WithBuckets(buckets int) ShedderOption {
|
||||
return func(opts *shedderOptions) {
|
||||
opts.buckets = buckets
|
||||
}
|
||||
}
|
||||
|
||||
// WithCpuThreshold customizes the Shedder with given cpu threshold.
|
||||
// WithCpuThreshold customizes the Shedder with the given cpu threshold.
|
||||
func WithCpuThreshold(threshold int64) ShedderOption {
|
||||
return func(opts *shedderOptions) {
|
||||
opts.cpuThreshold = threshold
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"github.com/zeromicro/go-zero/core/syncx"
|
||||
)
|
||||
|
||||
// A ShedderGroup is a manager to manage key based shedders.
|
||||
// A ShedderGroup is a manager to manage key-based shedders.
|
||||
type ShedderGroup struct {
|
||||
options []ShedderOption
|
||||
manager *syncx.ResourceManager
|
||||
|
||||
@@ -42,7 +42,7 @@ func Debugv(ctx context.Context, v interface{}) {
|
||||
getLogger(ctx).Debugv(v)
|
||||
}
|
||||
|
||||
// Debugw writes msg along with fields into access log.
|
||||
// Debugw writes msg along with fields into the access log.
|
||||
func Debugw(ctx context.Context, msg string, fields ...LogField) {
|
||||
getLogger(ctx).Debugw(msg, fields...)
|
||||
}
|
||||
@@ -63,7 +63,7 @@ func Errorv(ctx context.Context, v any) {
|
||||
getLogger(ctx).Errorv(v)
|
||||
}
|
||||
|
||||
// Errorw writes msg along with fields into error log.
|
||||
// Errorw writes msg along with fields into the error log.
|
||||
func Errorw(ctx context.Context, msg string, fields ...LogField) {
|
||||
getLogger(ctx).Errorw(msg, fields...)
|
||||
}
|
||||
@@ -88,7 +88,7 @@ func Infov(ctx context.Context, v any) {
|
||||
getLogger(ctx).Infov(v)
|
||||
}
|
||||
|
||||
// Infow writes msg along with fields into access log.
|
||||
// Infow writes msg along with fields into the access log.
|
||||
func Infow(ctx context.Context, msg string, fields ...LogField) {
|
||||
getLogger(ctx).Infow(msg, fields...)
|
||||
}
|
||||
@@ -108,10 +108,11 @@ func SetLevel(level uint32) {
|
||||
logx.SetLevel(level)
|
||||
}
|
||||
|
||||
// SetUp sets up the logx. If already set up, just return nil.
|
||||
// we allow SetUp to be called multiple times, because for example
|
||||
// SetUp sets up the logx.
|
||||
// If already set up, return nil.
|
||||
// We allow SetUp to be called multiple times, because, for example,
|
||||
// we need to allow different service frameworks to initialize logx respectively.
|
||||
// the same logic for SetUp
|
||||
// The same logic for SetUp
|
||||
func SetUp(c LogConf) error {
|
||||
return logx.SetUp(c)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package logx
|
||||
|
||||
// A LessLogger is a logger that control to log once during the given duration.
|
||||
// A LessLogger is a logger that controls to log once during the given duration.
|
||||
type LessLogger struct {
|
||||
*limitedExecutor
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ func Debugv(v any) {
|
||||
}
|
||||
}
|
||||
|
||||
// Debugw writes msg along with fields into access log.
|
||||
// Debugw writes msg along with fields into the access log.
|
||||
func Debugw(msg string, fields ...LogField) {
|
||||
if shallLog(DebugLevel) {
|
||||
writeDebug(msg, fields...)
|
||||
@@ -142,7 +142,7 @@ func Errorv(v any) {
|
||||
}
|
||||
}
|
||||
|
||||
// Errorw writes msg along with fields into error log.
|
||||
// Errorw writes msg along with fields into the error log.
|
||||
func Errorw(msg string, fields ...LogField) {
|
||||
if shallLog(ErrorLevel) {
|
||||
writeError(msg, fields...)
|
||||
@@ -208,7 +208,7 @@ func Infov(v any) {
|
||||
}
|
||||
}
|
||||
|
||||
// Infow writes msg along with fields into access log.
|
||||
// Infow writes msg along with fields into the access log.
|
||||
func Infow(msg string, fields ...LogField) {
|
||||
if shallLog(InfoLevel) {
|
||||
writeInfo(msg, fields...)
|
||||
@@ -254,11 +254,12 @@ func SetWriter(w Writer) {
|
||||
}
|
||||
}
|
||||
|
||||
// SetUp sets up the logx. If already set up, just return nil.
|
||||
// we allow SetUp to be called multiple times, because for example
|
||||
// SetUp sets up the logx.
|
||||
// If already set up, return nil.
|
||||
// We allow SetUp to be called multiple times, because, for example,
|
||||
// we need to allow different service frameworks to initialize logx respectively.
|
||||
func SetUp(c LogConf) (err error) {
|
||||
// Just ignore the subsequent SetUp calls.
|
||||
// Ignore the later SetUp calls.
|
||||
// Because multiple services in one process might call SetUp respectively.
|
||||
// Need to wait for the first caller to complete the execution.
|
||||
setupOnce.Do(func() {
|
||||
@@ -480,7 +481,7 @@ func writeDebug(val any, fields ...LogField) {
|
||||
getWriter().Debug(val, addCaller(fields...)...)
|
||||
}
|
||||
|
||||
// writeError writes v into error log.
|
||||
// writeError writes v into the error log.
|
||||
// Not checking shallLog here is for performance consideration.
|
||||
// If we check shallLog here, the fmt.Sprint might be called even if the log level is not enabled.
|
||||
// The caller should check shallLog before calling this function.
|
||||
@@ -520,7 +521,7 @@ func writeStack(msg string) {
|
||||
getWriter().Stack(fmt.Sprintf("%s\n%s", msg, string(debug.Stack())))
|
||||
}
|
||||
|
||||
// writeStat writes v into stat log.
|
||||
// writeStat writes v into the stat log.
|
||||
// Not checking shallLog here is for performance consideration.
|
||||
// If we check shallLog here, the fmt.Sprint might be called even if the log level is not enabled.
|
||||
// The caller should check shallLog before calling this function.
|
||||
|
||||
@@ -570,7 +570,7 @@ func TestErrorfWithWrappedError(t *testing.T) {
|
||||
old := writer.Swap(w)
|
||||
defer writer.Store(old)
|
||||
|
||||
Errorf("hello %w", errors.New(message))
|
||||
Errorf("hello %s", errors.New(message))
|
||||
assert.True(t, strings.Contains(w.String(), "hello there"))
|
||||
}
|
||||
|
||||
|
||||
@@ -319,7 +319,7 @@ func (l *RotateLogger) maybeCompressFile(file string) {
|
||||
}()
|
||||
|
||||
if _, err := os.Stat(file); err != nil {
|
||||
// file not exists or other error, ignore compression
|
||||
// file doesn't exist or another error, ignore compression
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ const (
|
||||
)
|
||||
|
||||
// Marshal marshals the given val and returns the map that contains the fields.
|
||||
// optional=another is not implemented, and it's hard to implement and not common used.
|
||||
// optional=another is not implemented, and it's hard to implement and not commonly used.
|
||||
func Marshal(val any) (map[string]map[string]any, error) {
|
||||
ret := make(map[string]map[string]any)
|
||||
tp := reflect.TypeOf(val)
|
||||
|
||||
@@ -39,7 +39,7 @@ var (
|
||||
)
|
||||
|
||||
type (
|
||||
// Unmarshaler is used to unmarshal with given tag key.
|
||||
// Unmarshaler is used to unmarshal with the given tag key.
|
||||
Unmarshaler struct {
|
||||
key string
|
||||
opts unmarshalOptions
|
||||
@@ -69,7 +69,7 @@ func NewUnmarshaler(key string, opts ...UnmarshalOption) *Unmarshaler {
|
||||
return &unmarshaler
|
||||
}
|
||||
|
||||
// UnmarshalKey unmarshals m into v with tag key.
|
||||
// UnmarshalKey unmarshals m into v with the tag key.
|
||||
func UnmarshalKey(m map[string]any, v any) error {
|
||||
return keyUnmarshaler.Unmarshal(m, v)
|
||||
}
|
||||
@@ -629,7 +629,7 @@ func (u *Unmarshaler) processFieldPrimitiveWithJSONNumber(fieldType reflect.Type
|
||||
return err
|
||||
}
|
||||
|
||||
// if value is a pointer, we need to check overflow with the pointer's value.
|
||||
// if the value is a pointer, we need to check overflow with the pointer's value.
|
||||
derefedValue := value
|
||||
for derefedValue.Type().Kind() == reflect.Ptr {
|
||||
derefedValue = derefedValue.Elem()
|
||||
|
||||
@@ -5866,7 +5866,7 @@ type mockValuerWithParent struct {
|
||||
ok bool
|
||||
}
|
||||
|
||||
func (m mockValuerWithParent) Value(key string) (any, bool) {
|
||||
func (m mockValuerWithParent) Value(_ string) (any, bool) {
|
||||
return m.value, m.ok
|
||||
}
|
||||
|
||||
|
||||
@@ -416,7 +416,7 @@ func parseOption(fieldOpts *fieldOptions, fieldName, option string) error {
|
||||
}
|
||||
|
||||
// parseOptions parses the given options in tag.
|
||||
// for example: `json:"name,options=foo|bar"` or `json:"name,options=[foo,bar]"`
|
||||
// for example, `json:"name,options=foo|bar"` or `json:"name,options=[foo,bar]"`
|
||||
func parseOptions(val string) []string {
|
||||
if len(val) == 0 {
|
||||
return nil
|
||||
|
||||
@@ -26,9 +26,9 @@ type (
|
||||
parent valuerWithParent
|
||||
}
|
||||
|
||||
// mapValuer is a type for map to meet the Valuer interface.
|
||||
// mapValuer is a type for the map to meet the Valuer interface.
|
||||
mapValuer map[string]any
|
||||
// simpleValuer is a type to get value from current node.
|
||||
// simpleValuer is a type to get value from the current node.
|
||||
simpleValuer node
|
||||
// recursiveValuer is a type to get the value recursively from current and parent nodes.
|
||||
recursiveValuer node
|
||||
|
||||
@@ -36,6 +36,6 @@ type fakeCreator struct {
|
||||
err error
|
||||
}
|
||||
|
||||
func (fc fakeCreator) Create(name string) (file *os.File, err error) {
|
||||
func (fc fakeCreator) Create(_ string) (file *os.File, err error) {
|
||||
return fc.file, fc.err
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ func (q *Queue) AddListener(listener Listener) {
|
||||
q.listeners = append(q.listeners, listener)
|
||||
}
|
||||
|
||||
// Broadcast broadcasts message to all event channels.
|
||||
// Broadcast broadcasts the message to all event channels.
|
||||
func (q *Queue) Broadcast(message any) {
|
||||
go func() {
|
||||
q.eventLock.Lock()
|
||||
@@ -202,7 +202,7 @@ func (q *Queue) produce() {
|
||||
}
|
||||
|
||||
func (q *Queue) produceOne(producer Producer) (string, bool) {
|
||||
// avoid panic quit the producer, just log it and continue
|
||||
// avoid panic quit the producer, log it and continue
|
||||
defer rescue.Recover()
|
||||
|
||||
return producer.Produce()
|
||||
|
||||
@@ -67,7 +67,7 @@ func (p *mockedPusher) Name() string {
|
||||
return p.name
|
||||
}
|
||||
|
||||
func (p *mockedPusher) Push(s string) error {
|
||||
func (p *mockedPusher) Push(_ string) error {
|
||||
if proba.TrueOnProba(failProba) {
|
||||
return errors.New("dummy")
|
||||
}
|
||||
|
||||
@@ -71,6 +71,6 @@ func (m *mockedWriter) Write(report *StatReport) error {
|
||||
|
||||
type badWriter struct{}
|
||||
|
||||
func (b *badWriter) Write(report *StatReport) error {
|
||||
func (b *badWriter) Write(_ *StatReport) error {
|
||||
return errors.New("bad")
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package stat
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -28,3 +29,14 @@ func TestRemoteWriterFail(t *testing.T) {
|
||||
})
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestRemoteWriterError(t *testing.T) {
|
||||
defer gock.Off()
|
||||
|
||||
gock.New("http://foo.com").ReplyError(errors.New("foo"))
|
||||
writer := NewRemoteWriter("http://foo.com")
|
||||
err := writer.Write(&StatReport{
|
||||
Name: "bar",
|
||||
})
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package stat
|
||||
|
||||
import "time"
|
||||
|
||||
// A Task is a task that is reported to Metrics.
|
||||
// A Task is a task reported to Metrics.
|
||||
type Task struct {
|
||||
Drop bool
|
||||
Duration time.Duration
|
||||
|
||||
@@ -41,7 +41,7 @@ func RawFieldNames(in any, postgreSql ...bool) []string {
|
||||
out = append(out, fmt.Sprintf("`%s`", fi.Name))
|
||||
}
|
||||
default:
|
||||
// get tag name with the tag opton, e.g.:
|
||||
// get tag name with the tag option, e.g.:
|
||||
// `db:"id"`
|
||||
// `db:"id,type=char,length=16"`
|
||||
// `db:",type=char,length=16"`
|
||||
|
||||
2
core/stores/cache/cacheopt.go
vendored
2
core/stores/cache/cacheopt.go
vendored
@@ -8,7 +8,7 @@ const (
|
||||
)
|
||||
|
||||
type (
|
||||
// An Options is used to store the cache options.
|
||||
// Options is used to store the cache options.
|
||||
Options struct {
|
||||
Expiry time.Duration
|
||||
NotFoundExpiry time.Duration
|
||||
|
||||
41
core/stores/redis/breakerhook.go
Normal file
41
core/stores/redis/breakerhook.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
red "github.com/redis/go-redis/v9"
|
||||
"github.com/zeromicro/go-zero/core/breaker"
|
||||
"github.com/zeromicro/go-zero/core/lang"
|
||||
)
|
||||
|
||||
var ignoreCmds = map[string]lang.PlaceholderType{
|
||||
"blpop": {},
|
||||
}
|
||||
|
||||
type breakerHook struct {
|
||||
brk breaker.Breaker
|
||||
}
|
||||
|
||||
func (h breakerHook) DialHook(next red.DialHook) red.DialHook {
|
||||
return next
|
||||
}
|
||||
|
||||
func (h breakerHook) ProcessHook(next red.ProcessHook) red.ProcessHook {
|
||||
return func(ctx context.Context, cmd red.Cmder) error {
|
||||
if _, ok := ignoreCmds[cmd.Name()]; ok {
|
||||
return next(ctx, cmd)
|
||||
}
|
||||
|
||||
return h.brk.DoWithAcceptable(func() error {
|
||||
return next(ctx, cmd)
|
||||
}, acceptable)
|
||||
}
|
||||
}
|
||||
|
||||
func (h breakerHook) ProcessPipelineHook(next red.ProcessPipelineHook) red.ProcessPipelineHook {
|
||||
return func(ctx context.Context, cmds []red.Cmder) error {
|
||||
return h.brk.DoWithAcceptable(func() error {
|
||||
return next(ctx, cmds)
|
||||
}, acceptable)
|
||||
}
|
||||
}
|
||||
135
core/stores/redis/breakerhook_test.go
Normal file
135
core/stores/redis/breakerhook_test.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/alicebob/miniredis/v2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/zeromicro/go-zero/core/breaker"
|
||||
)
|
||||
|
||||
func TestBreakerHook_ProcessHook(t *testing.T) {
|
||||
t.Run("breakerHookOpen", func(t *testing.T) {
|
||||
s := miniredis.RunT(t)
|
||||
|
||||
rds := MustNewRedis(RedisConf{
|
||||
Host: s.Addr(),
|
||||
Type: NodeType,
|
||||
})
|
||||
|
||||
someError := errors.New("ERR some error")
|
||||
s.SetError(someError.Error())
|
||||
|
||||
var err error
|
||||
for i := 0; i < 1000; i++ {
|
||||
_, err = rds.Get("key")
|
||||
if err != nil && err.Error() != someError.Error() {
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.Equal(t, breaker.ErrServiceUnavailable, err)
|
||||
})
|
||||
|
||||
t.Run("breakerHookClose", func(t *testing.T) {
|
||||
s := miniredis.RunT(t)
|
||||
|
||||
rds := MustNewRedis(RedisConf{
|
||||
Host: s.Addr(),
|
||||
Type: NodeType,
|
||||
})
|
||||
|
||||
var err error
|
||||
for i := 0; i < 1000; i++ {
|
||||
_, err = rds.Get("key")
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.NotEqual(t, breaker.ErrServiceUnavailable, err)
|
||||
})
|
||||
|
||||
t.Run("breakerHook_ignoreCmd", func(t *testing.T) {
|
||||
s := miniredis.RunT(t)
|
||||
|
||||
rds := MustNewRedis(RedisConf{
|
||||
Host: s.Addr(),
|
||||
Type: NodeType,
|
||||
})
|
||||
|
||||
someError := errors.New("ERR some error")
|
||||
s.SetError(someError.Error())
|
||||
|
||||
var err error
|
||||
|
||||
node, err := getRedis(rds)
|
||||
assert.NoError(t, err)
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
_, err = rds.Blpop(node, "key")
|
||||
if err != nil && err.Error() != someError.Error() {
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.Equal(t, someError.Error(), err.Error())
|
||||
})
|
||||
}
|
||||
|
||||
func TestBreakerHook_ProcessPipelineHook(t *testing.T) {
|
||||
t.Run("breakerPipelineHookOpen", func(t *testing.T) {
|
||||
s := miniredis.RunT(t)
|
||||
|
||||
rds := MustNewRedis(RedisConf{
|
||||
Host: s.Addr(),
|
||||
Type: NodeType,
|
||||
})
|
||||
|
||||
someError := errors.New("ERR some error")
|
||||
s.SetError(someError.Error())
|
||||
|
||||
var err error
|
||||
for i := 0; i < 1000; i++ {
|
||||
err = rds.Pipelined(
|
||||
func(pipe Pipeliner) error {
|
||||
pipe.Incr(context.Background(), "pipelined_counter")
|
||||
pipe.Expire(context.Background(), "pipelined_counter", time.Hour)
|
||||
pipe.ZAdd(context.Background(), "zadd", Z{Score: 12, Member: "zadd"})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil && err.Error() != someError.Error() {
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.Equal(t, breaker.ErrServiceUnavailable, err)
|
||||
})
|
||||
|
||||
t.Run("breakerPipelineHookClose", func(t *testing.T) {
|
||||
s := miniredis.RunT(t)
|
||||
|
||||
rds := MustNewRedis(RedisConf{
|
||||
Host: s.Addr(),
|
||||
Type: NodeType,
|
||||
})
|
||||
|
||||
var err error
|
||||
for i := 0; i < 1000; i++ {
|
||||
err = rds.Pipelined(
|
||||
func(pipe Pipeliner) error {
|
||||
pipe.Incr(context.Background(), "pipelined_counter")
|
||||
pipe.Expire(context.Background(), "pipelined_counter", time.Hour)
|
||||
pipe.ZAdd(context.Background(), "zadd", Z{Score: 12, Member: "zadd"})
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.NotEqual(t, breaker.ErrServiceUnavailable, err)
|
||||
})
|
||||
}
|
||||
@@ -47,7 +47,7 @@ func (rc RedisConf) NewRedis() *Redis {
|
||||
opts = append(opts, WithTLS())
|
||||
}
|
||||
|
||||
return New(rc.Host, opts...)
|
||||
return newRedis(rc.Host, opts...)
|
||||
}
|
||||
|
||||
// Validate validates the RedisConf.
|
||||
|
||||
@@ -23,17 +23,18 @@ import (
|
||||
const spanName = "redis"
|
||||
|
||||
var (
|
||||
durationHook = hook{}
|
||||
defaultDurationHook = durationHook{}
|
||||
redisCmdsAttributeKey = attribute.Key("redis.cmds")
|
||||
)
|
||||
|
||||
type hook struct{}
|
||||
type durationHook struct {
|
||||
}
|
||||
|
||||
func (h hook) DialHook(next red.DialHook) red.DialHook {
|
||||
func (h durationHook) DialHook(next red.DialHook) red.DialHook {
|
||||
return next
|
||||
}
|
||||
|
||||
func (h hook) ProcessHook(next red.ProcessHook) red.ProcessHook {
|
||||
func (h durationHook) ProcessHook(next red.ProcessHook) red.ProcessHook {
|
||||
return func(ctx context.Context, cmd red.Cmder) error {
|
||||
start := timex.Now()
|
||||
ctx, endSpan := h.startSpan(ctx, cmd)
|
||||
@@ -57,7 +58,7 @@ func (h hook) ProcessHook(next red.ProcessHook) red.ProcessHook {
|
||||
}
|
||||
}
|
||||
|
||||
func (h hook) ProcessPipelineHook(next red.ProcessPipelineHook) red.ProcessPipelineHook {
|
||||
func (h durationHook) ProcessPipelineHook(next red.ProcessPipelineHook) red.ProcessPipelineHook {
|
||||
return func(ctx context.Context, cmds []red.Cmder) error {
|
||||
if len(cmds) == 0 {
|
||||
return next(ctx, cmds)
|
||||
@@ -83,6 +84,33 @@ func (h hook) ProcessPipelineHook(next red.ProcessPipelineHook) red.ProcessPipel
|
||||
}
|
||||
}
|
||||
|
||||
func (h durationHook) startSpan(ctx context.Context, cmds ...red.Cmder) (context.Context, func(err error)) {
|
||||
tracer := trace.TracerFromContext(ctx)
|
||||
|
||||
ctx, span := tracer.Start(ctx,
|
||||
spanName,
|
||||
oteltrace.WithSpanKind(oteltrace.SpanKindClient),
|
||||
)
|
||||
|
||||
cmdStrs := make([]string, 0, len(cmds))
|
||||
for _, cmd := range cmds {
|
||||
cmdStrs = append(cmdStrs, cmd.Name())
|
||||
}
|
||||
span.SetAttributes(redisCmdsAttributeKey.StringSlice(cmdStrs))
|
||||
|
||||
return ctx, func(err error) {
|
||||
defer span.End()
|
||||
|
||||
if err == nil || errors.Is(err, red.Nil) {
|
||||
span.SetStatus(codes.Ok, "")
|
||||
return
|
||||
}
|
||||
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
span.RecordError(err)
|
||||
}
|
||||
}
|
||||
|
||||
func formatError(err error) string {
|
||||
if err == nil || errors.Is(err, red.Nil) {
|
||||
return ""
|
||||
@@ -95,7 +123,7 @@ func formatError(err error) string {
|
||||
}
|
||||
|
||||
switch {
|
||||
case err == io.EOF:
|
||||
case errors.Is(err, io.EOF):
|
||||
return "eof"
|
||||
case errors.Is(err, context.DeadlineExceeded):
|
||||
return "context deadline"
|
||||
@@ -123,30 +151,3 @@ func logDuration(ctx context.Context, cmds []red.Cmder, duration time.Duration)
|
||||
}
|
||||
logx.WithContext(ctx).WithDuration(duration).Slowf("[REDIS] slowcall on executing: %s", buf.String())
|
||||
}
|
||||
|
||||
func (h hook) startSpan(ctx context.Context, cmds ...red.Cmder) (context.Context, func(err error)) {
|
||||
tracer := trace.TracerFromContext(ctx)
|
||||
|
||||
ctx, span := tracer.Start(ctx,
|
||||
spanName,
|
||||
oteltrace.WithSpanKind(oteltrace.SpanKindClient),
|
||||
)
|
||||
|
||||
cmdStrs := make([]string, 0, len(cmds))
|
||||
for _, cmd := range cmds {
|
||||
cmdStrs = append(cmdStrs, cmd.Name())
|
||||
}
|
||||
span.SetAttributes(redisCmdsAttributeKey.StringSlice(cmdStrs))
|
||||
|
||||
return ctx, func(err error) {
|
||||
defer span.End()
|
||||
|
||||
if err == nil || errors.Is(err, red.Nil) {
|
||||
span.SetStatus(codes.Ok, "")
|
||||
return
|
||||
}
|
||||
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
span.RecordError(err)
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ func TestHookProcessCase1(t *testing.T) {
|
||||
tracetest.NewInMemoryExporter(t)
|
||||
w := logtest.NewCollector(t)
|
||||
|
||||
err := durationHook.ProcessHook(func(ctx context.Context, cmd red.Cmder) error {
|
||||
err := defaultDurationHook.ProcessHook(func(ctx context.Context, cmd red.Cmder) error {
|
||||
assert.Equal(t, "redis", tracesdk.SpanFromContext(ctx).(interface{ Name() string }).Name())
|
||||
return nil
|
||||
})(context.Background(), red.NewCmd(context.Background()))
|
||||
@@ -36,7 +36,7 @@ func TestHookProcessCase2(t *testing.T) {
|
||||
tracetest.NewInMemoryExporter(t)
|
||||
w := logtest.NewCollector(t)
|
||||
|
||||
err := durationHook.ProcessHook(func(ctx context.Context, cmd red.Cmder) error {
|
||||
err := defaultDurationHook.ProcessHook(func(ctx context.Context, cmd red.Cmder) error {
|
||||
assert.Equal(t, "redis", tracesdk.SpanFromContext(ctx).(interface{ Name() string }).Name())
|
||||
time.Sleep(slowThreshold.Load() + time.Millisecond)
|
||||
return nil
|
||||
@@ -54,12 +54,12 @@ func TestHookProcessPipelineCase1(t *testing.T) {
|
||||
tracetest.NewInMemoryExporter(t)
|
||||
w := logtest.NewCollector(t)
|
||||
|
||||
err := durationHook.ProcessPipelineHook(func(ctx context.Context, cmds []red.Cmder) error {
|
||||
err := defaultDurationHook.ProcessPipelineHook(func(ctx context.Context, cmds []red.Cmder) error {
|
||||
return nil
|
||||
})(context.Background(), nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = durationHook.ProcessPipelineHook(func(ctx context.Context, cmds []red.Cmder) error {
|
||||
err = defaultDurationHook.ProcessPipelineHook(func(ctx context.Context, cmds []red.Cmder) error {
|
||||
assert.Equal(t, "redis", tracesdk.SpanFromContext(ctx).(interface{ Name() string }).Name())
|
||||
return nil
|
||||
})(context.Background(), []red.Cmder{
|
||||
@@ -74,7 +74,7 @@ func TestHookProcessPipelineCase2(t *testing.T) {
|
||||
tracetest.NewInMemoryExporter(t)
|
||||
w := logtest.NewCollector(t)
|
||||
|
||||
err := durationHook.ProcessPipelineHook(func(ctx context.Context, cmds []red.Cmder) error {
|
||||
err := defaultDurationHook.ProcessPipelineHook(func(ctx context.Context, cmds []red.Cmder) error {
|
||||
assert.Equal(t, "redis", tracesdk.SpanFromContext(ctx).(interface{ Name() string }).Name())
|
||||
time.Sleep(slowThreshold.Load() + time.Millisecond)
|
||||
return nil
|
||||
@@ -91,7 +91,7 @@ func TestHookProcessPipelineCase2(t *testing.T) {
|
||||
func TestHookProcessPipelineCase3(t *testing.T) {
|
||||
te := tracetest.NewInMemoryExporter(t)
|
||||
|
||||
err := durationHook.ProcessPipelineHook(func(ctx context.Context, cmds []red.Cmder) error {
|
||||
err := defaultDurationHook.ProcessPipelineHook(func(ctx context.Context, cmds []red.Cmder) error {
|
||||
assert.Equal(t, "redis", tracesdk.SpanFromContext(ctx).(interface{ Name() string }).Name())
|
||||
return assert.AnError
|
||||
})(context.Background(), []red.Cmder{
|
||||
@@ -19,7 +19,7 @@ func TestRedisMetric(t *testing.T) {
|
||||
cfg := devserver.Config{}
|
||||
_ = conf.FillDefault(&cfg)
|
||||
server := devserver.NewServer(cfg)
|
||||
server.StartAsync()
|
||||
server.StartAsync(cfg)
|
||||
time.Sleep(time.Second)
|
||||
|
||||
metricReqDur.Observe(8, "test-cmd")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -36,7 +36,7 @@ func (m myHook) ProcessHook(next red.ProcessHook) red.ProcessHook {
|
||||
if cmd.Name() == "ping" && !m.includePing {
|
||||
return next(ctx, cmd)
|
||||
}
|
||||
return errors.New("hook error")
|
||||
return errors.New("durationHook error")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ func TestRedis_NonBlock(t *testing.T) {
|
||||
|
||||
t.Run("nonBlock true", func(t *testing.T) {
|
||||
s := miniredis.RunT(t)
|
||||
// use hook to simulate redis ping error
|
||||
// use durationHook to simulate redis ping error
|
||||
_, err := NewRedis(RedisConf{
|
||||
Host: s.Addr(),
|
||||
NonBlock: true,
|
||||
|
||||
@@ -37,8 +37,11 @@ func getClient(r *Redis) (*red.Client, error) {
|
||||
MinIdleConns: idleConns,
|
||||
TLSConfig: tlsConfig,
|
||||
})
|
||||
store.AddHook(durationHook)
|
||||
for _, hook := range r.hooks {
|
||||
|
||||
hooks := append([]red.Hook{defaultDurationHook, breakerHook{
|
||||
brk: r.brk,
|
||||
}}, r.hooks...)
|
||||
for _, hook := range hooks {
|
||||
store.AddHook(hook)
|
||||
}
|
||||
|
||||
|
||||
@@ -33,8 +33,11 @@ func getCluster(r *Redis) (*red.ClusterClient, error) {
|
||||
MinIdleConns: idleConns,
|
||||
TLSConfig: tlsConfig,
|
||||
})
|
||||
store.AddHook(durationHook)
|
||||
for _, hook := range r.hooks {
|
||||
|
||||
hooks := append([]red.Hook{defaultDurationHook, breakerHook{
|
||||
brk: r.brk,
|
||||
}}, r.hooks...)
|
||||
for _, hook := range hooks {
|
||||
store.AddHook(hook)
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ func TestGetCluster(t *testing.T) {
|
||||
Addr: r.Addr(),
|
||||
Type: ClusterType,
|
||||
tls: true,
|
||||
hooks: []red.Hook{durationHook},
|
||||
hooks: []red.Hook{defaultDurationHook},
|
||||
})
|
||||
if assert.NoError(t, err) {
|
||||
assert.NotNil(t, c)
|
||||
|
||||
@@ -2,6 +2,7 @@ package redis
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"sync/atomic"
|
||||
@@ -64,7 +65,7 @@ func (rl *RedisLock) AcquireCtx(ctx context.Context) (bool, error) {
|
||||
resp, err := rl.store.ScriptRunCtx(ctx, lockScript, []string{rl.key}, []string{
|
||||
rl.id, strconv.Itoa(int(seconds)*millisPerSecond + tolerance),
|
||||
})
|
||||
if err == red.Nil {
|
||||
if errors.Is(err, red.Nil) {
|
||||
return false, nil
|
||||
} else if err != nil {
|
||||
logx.Errorf("Error on acquiring lock for %s, %s", rl.key, err.Error())
|
||||
|
||||
@@ -20,7 +20,7 @@ func TestSqlxMetric(t *testing.T) {
|
||||
_ = conf.FillDefault(&cfg)
|
||||
cfg.Port = 6480
|
||||
server := devserver.NewServer(cfg)
|
||||
server.StartAsync()
|
||||
server.StartAsync(cfg)
|
||||
time.Sleep(time.Second)
|
||||
|
||||
metricReqDur.Observe(8, "test-cmd")
|
||||
|
||||
@@ -13,7 +13,7 @@ const (
|
||||
|
||||
// NewMysql returns a mysql connection.
|
||||
func NewMysql(datasource string, opts ...SqlOption) SqlConn {
|
||||
opts = append(opts, withMysqlAcceptable())
|
||||
opts = append([]SqlOption{withMysqlAcceptable()}, opts...)
|
||||
return NewSqlConn(mysqlDriverName, datasource, opts...)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package sqlx
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/go-sql-driver/mysql"
|
||||
@@ -38,7 +37,6 @@ func TestBreakerOnNotHandlingDuplicateEntry(t *testing.T) {
|
||||
func TestMysqlAcceptable(t *testing.T) {
|
||||
conn := NewMysql("nomysql").(*commonSqlConn)
|
||||
withMysqlAcceptable()(conn)
|
||||
assert.EqualValues(t, reflect.ValueOf(mysqlAcceptable).Pointer(), reflect.ValueOf(conn.accept).Pointer())
|
||||
assert.True(t, mysqlAcceptable(nil))
|
||||
assert.False(t, mysqlAcceptable(errors.New("any")))
|
||||
assert.False(t, mysqlAcceptable(new(mysql.MySQLError)))
|
||||
|
||||
@@ -315,6 +315,13 @@ func (db *commonSqlConn) queryRows(ctx context.Context, scanner func(*sql.Rows)
|
||||
// acceptable is the func to check if the error can be accepted.
|
||||
func WithAcceptable(acceptable func(err error) bool) SqlOption {
|
||||
return func(conn *commonSqlConn) {
|
||||
conn.accept = acceptable
|
||||
if conn.accept == nil {
|
||||
conn.accept = acceptable
|
||||
} else {
|
||||
pre := conn.accept
|
||||
conn.accept = func(err error) bool {
|
||||
return pre(err) || acceptable(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,6 +264,45 @@ func TestBreakerWithScanError(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestWithAcceptable(t *testing.T) {
|
||||
var (
|
||||
acceptableErr = errors.New("acceptable")
|
||||
acceptableErr2 = errors.New("acceptable2")
|
||||
acceptableErr3 = errors.New("acceptable3")
|
||||
)
|
||||
opts := []SqlOption{
|
||||
WithAcceptable(func(err error) bool {
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
return errors.Is(err, acceptableErr)
|
||||
}),
|
||||
WithAcceptable(func(err error) bool {
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
return errors.Is(err, acceptableErr2)
|
||||
}),
|
||||
WithAcceptable(func(err error) bool {
|
||||
if err == nil {
|
||||
return true
|
||||
}
|
||||
return errors.Is(err, acceptableErr3)
|
||||
}),
|
||||
}
|
||||
|
||||
var conn = &commonSqlConn{}
|
||||
for _, opt := range opts {
|
||||
opt(conn)
|
||||
}
|
||||
|
||||
assert.True(t, conn.accept(nil))
|
||||
assert.False(t, conn.accept(assert.AnError))
|
||||
assert.True(t, conn.accept(acceptableErr))
|
||||
assert.True(t, conn.accept(acceptableErr2))
|
||||
assert.True(t, conn.accept(acceptableErr3))
|
||||
}
|
||||
|
||||
func buildConn() (mock sqlmock.Sqlmock, err error) {
|
||||
_, err = connManager.GetResource(mockedDatasource, func() (io.Closer, error) {
|
||||
var db *sql.DB
|
||||
|
||||
@@ -59,7 +59,13 @@ func StartAgent(c Config) {
|
||||
|
||||
// StopAgent shuts down the span processors in the order they were registered.
|
||||
func StopAgent() {
|
||||
_ = tp.Shutdown(context.Background())
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
if tp != nil {
|
||||
_ = tp.Shutdown(context.Background())
|
||||
tp = nil
|
||||
}
|
||||
}
|
||||
|
||||
func createExporter(c Config) (sdktrace.SpanExporter, error) {
|
||||
|
||||
@@ -34,7 +34,7 @@ type mockSpan struct {
|
||||
options []trace.EventOption
|
||||
}
|
||||
|
||||
func (m *mockSpan) End(options ...trace.SpanEndOption) {
|
||||
func (m *mockSpan) End(_ ...trace.SpanEndOption) {
|
||||
}
|
||||
|
||||
func (m *mockSpan) AddEvent(name string, options ...trace.EventOption) {
|
||||
@@ -46,20 +46,20 @@ func (m *mockSpan) IsRecording() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *mockSpan) RecordError(err error, options ...trace.EventOption) {
|
||||
func (m *mockSpan) RecordError(_ error, _ ...trace.EventOption) {
|
||||
}
|
||||
|
||||
func (m *mockSpan) SpanContext() trace.SpanContext {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (m *mockSpan) SetStatus(code codes.Code, description string) {
|
||||
func (m *mockSpan) SetStatus(_ codes.Code, _ string) {
|
||||
}
|
||||
|
||||
func (m *mockSpan) SetName(name string) {
|
||||
func (m *mockSpan) SetName(_ string) {
|
||||
}
|
||||
|
||||
func (m *mockSpan) SetAttributes(kv ...attribute.KeyValue) {
|
||||
func (m *mockSpan) SetAttributes(_ ...attribute.KeyValue) {
|
||||
}
|
||||
|
||||
func (m *mockSpan) TracerProvider() trace.TracerProvider {
|
||||
|
||||
@@ -4,5 +4,5 @@ import "net/http"
|
||||
|
||||
// TraceIdKey is the trace id header.
|
||||
// https://www.w3.org/TR/trace-context/#trace-id
|
||||
// May change it to trace-id afterwards.
|
||||
// May change it to trace-id afterward.
|
||||
var TraceIdKey = http.CanonicalHeaderKey("x-trace-id")
|
||||
|
||||
45
go.mod
45
go.mod
@@ -4,24 +4,24 @@ go 1.19
|
||||
|
||||
require (
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||
github.com/alicebob/miniredis/v2 v2.31.1
|
||||
github.com/alicebob/miniredis/v2 v2.32.1
|
||||
github.com/fatih/color v1.16.0
|
||||
github.com/fullstorydev/grpcurl v1.8.9
|
||||
github.com/go-sql-driver/mysql v1.7.1
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0
|
||||
github.com/golang/mock v1.6.0
|
||||
github.com/golang/protobuf v1.5.3
|
||||
github.com/golang/protobuf v1.5.4
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/jackc/pgx/v5 v5.5.3
|
||||
github.com/jackc/pgx/v5 v5.5.5
|
||||
github.com/jhump/protoreflect v1.15.6
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/pelletier/go-toml/v2 v2.1.1
|
||||
github.com/pelletier/go-toml/v2 v2.2.0
|
||||
github.com/prometheus/client_golang v1.18.0
|
||||
github.com/redis/go-redis/v9 v9.4.0
|
||||
github.com/spaolacci/murmur3 v1.1.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
go.etcd.io/etcd/api/v3 v3.5.12
|
||||
go.etcd.io/etcd/client/v3 v3.5.12
|
||||
go.etcd.io/etcd/api/v3 v3.5.13
|
||||
go.etcd.io/etcd/client/v3 v3.5.13
|
||||
go.mongodb.org/mongo-driver v1.13.1
|
||||
go.opentelemetry.io/otel v1.19.0
|
||||
go.opentelemetry.io/otel/exporters/jaeger v1.17.0
|
||||
@@ -33,22 +33,23 @@ require (
|
||||
go.opentelemetry.io/otel/trace v1.19.0
|
||||
go.uber.org/automaxprocs v1.5.3
|
||||
go.uber.org/goleak v1.2.1
|
||||
golang.org/x/net v0.21.0
|
||||
golang.org/x/sys v0.17.0
|
||||
golang.org/x/net v0.24.0
|
||||
golang.org/x/sys v0.19.0
|
||||
golang.org/x/time v0.5.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80
|
||||
google.golang.org/grpc v1.62.0
|
||||
google.golang.org/protobuf v1.32.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de
|
||||
google.golang.org/grpc v1.63.0
|
||||
google.golang.org/protobuf v1.33.0
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.28
|
||||
gopkg.in/h2non/gock.v1 v1.1.2
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
k8s.io/api v0.29.2
|
||||
k8s.io/apimachinery v0.29.2
|
||||
k8s.io/client-go v0.29.2
|
||||
k8s.io/api v0.29.3
|
||||
k8s.io/apimachinery v0.29.3
|
||||
k8s.io/client-go v0.29.3
|
||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bufbuild/protocompile v0.8.0 // indirect
|
||||
@@ -96,22 +97,22 @@ require (
|
||||
github.com/xdg-go/scram v1.1.2 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
|
||||
github.com/yuin/gopher-lua v1.1.0 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.12 // indirect
|
||||
github.com/yuin/gopher-lua v1.1.1 // indirect
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.13 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.19.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
go.uber.org/zap v1.24.0 // indirect
|
||||
golang.org/x/crypto v0.19.0 // indirect
|
||||
golang.org/x/oauth2 v0.16.0 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/oauth2 v0.17.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/term v0.17.0 // indirect
|
||||
golang.org/x/term v0.19.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/klog/v2 v2.110.1 // indirect
|
||||
|
||||
93
go.sum
93
go.sum
@@ -1,11 +1,12 @@
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
||||
github.com/DmitriyVTitov/size v1.5.0/go.mod h1:le6rNI4CoLQV1b9gzp1+3d7hMAD/uu2QcJ+aYbNgiU0=
|
||||
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
|
||||
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 h1:uvdUDbHQHO85qeSydJtItA4T55Pw6BtAejd0APRJOCE=
|
||||
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
|
||||
github.com/alicebob/miniredis/v2 v2.31.1 h1:7XAt0uUg3DtwEKW5ZAGa+K7FZV2DdKQo5K/6TTnfX8Y=
|
||||
github.com/alicebob/miniredis/v2 v2.31.1/go.mod h1:UB/T2Uztp7MlFSDakaX1sTXUv5CASoprx0wulRT6HBg=
|
||||
github.com/alicebob/miniredis/v2 v2.32.1 h1:Bz7CciDnYSaa0mX5xODh6GUITRSx+cVhjNoOR4JssBo=
|
||||
github.com/alicebob/miniredis/v2 v2.32.1/go.mod h1:AqkLNAfUm0K07J28hnAyyQKf/x0YkCY/g5DCtuL01Mw=
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
@@ -48,8 +49,8 @@ github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
|
||||
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
@@ -57,13 +58,12 @@ github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang/glog v1.2.0 h1:uCdmnmatrKCgMBlM4rMuJZWOkPDqdbZPnrMXDY4gI68=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
@@ -88,8 +88,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.5.3 h1:Ces6/M3wbDXYpM8JyyPD57ivTtJACFZJd885pdIaV2s=
|
||||
github.com/jackc/pgx/v5 v5.5.3/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
|
||||
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jhump/protoreflect v1.15.6 h1:WMYJbw2Wo+KOWwZFvgY0jMoVHM6i4XIvRs2RcBj5VmI=
|
||||
@@ -139,8 +139,8 @@ github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4
|
||||
github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
|
||||
github.com/openzipkin/zipkin-go v0.4.2 h1:zjqfqHjUpPmB3c1GlCvvgsM1G4LkvqQbBDueDOCg/jA=
|
||||
github.com/openzipkin/zipkin-go v0.4.2/go.mod h1:ZeVkFjuuBiSy13y8vpSDCjMi9GoI3hPpCJSBx/EYFhY=
|
||||
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
|
||||
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo=
|
||||
github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
@@ -165,6 +165,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
@@ -186,14 +187,14 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE=
|
||||
github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
|
||||
go.etcd.io/etcd/api/v3 v3.5.12 h1:W4sw5ZoU2Juc9gBWuLk5U6fHfNVyY1WC5g9uiXZio/c=
|
||||
go.etcd.io/etcd/api/v3 v3.5.12/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.12 h1:EYDL6pWwyOsylrQyLp2w+HkQ46ATiOvoEdMarindU2A=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.12/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4=
|
||||
go.etcd.io/etcd/client/v3 v3.5.12 h1:v5lCPXn1pf1Uu3M4laUE2hp/geOTc5uPcYYsNe1lDxg=
|
||||
go.etcd.io/etcd/client/v3 v3.5.12/go.mod h1:tSbBCakoWmmddL+BKVAJHa9km+O/E+bumDe9mSbPiqw=
|
||||
github.com/yuin/gopher-lua v1.1.1 h1:kYKnWBjvbNP4XLT3+bPEwAXJx262OhaHDWDVOPjL46M=
|
||||
github.com/yuin/gopher-lua v1.1.1/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw=
|
||||
go.etcd.io/etcd/api/v3 v3.5.13 h1:8WXU2/NBge6AUF1K1gOexB6e07NgsN1hXK0rSTtgSp4=
|
||||
go.etcd.io/etcd/api/v3 v3.5.13/go.mod h1:gBqlqkcMMZMVTMm4NDZloEVJzxQOQIls8splbqBDa0c=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.13 h1:RVZSAnWWWiI5IrYAXjQorajncORbS0zI48LQlE2kQWg=
|
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.13/go.mod h1:XxHT4u1qU12E2+po+UVPrEeL94Um6zL58ppuJWXSAB8=
|
||||
go.etcd.io/etcd/client/v3 v3.5.13 h1:o0fHTNJLeO0MyVbc7I3fsCf6nrOqn5d+diSarKnB2js=
|
||||
go.etcd.io/etcd/client/v3 v3.5.13/go.mod h1:cqiAeY8b5DEEcpxvgWKsbLIWNM/8Wy2xJSDMtioMcoI=
|
||||
go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk=
|
||||
go.mongodb.org/mongo-driver v1.13.1/go.mod h1:wcDf1JBCXy2mOW0bWHwO/IOYqdca1MPCwDtFu/Z9+eo=
|
||||
go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
|
||||
@@ -234,8 +235,8 @@ golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
|
||||
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
@@ -248,10 +249,10 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
|
||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
|
||||
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
|
||||
golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
|
||||
golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -272,12 +273,12 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
|
||||
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
|
||||
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@@ -301,18 +302,18 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
|
||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
|
||||
google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk=
|
||||
google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY=
|
||||
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
|
||||
google.golang.org/grpc v1.63.0 h1:WjKe+dnvABXyPJMD7KDNLxtoGk5tgk+YFWN6cBWjZE8=
|
||||
google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
@@ -328,12 +329,12 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A=
|
||||
k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0=
|
||||
k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8=
|
||||
k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU=
|
||||
k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg=
|
||||
k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA=
|
||||
k8s.io/api v0.29.3 h1:2ORfZ7+bGC3YJqGpV0KSDDEVf8hdGQ6A03/50vj8pmw=
|
||||
k8s.io/api v0.29.3/go.mod h1:y2yg2NTyHUUkIoTC+phinTnEa3KFM6RZ3szxt014a80=
|
||||
k8s.io/apimachinery v0.29.3 h1:2tbx+5L7RNvqJjn7RIuIKu9XTsIZ9Z5wX2G22XAa5EU=
|
||||
k8s.io/apimachinery v0.29.3/go.mod h1:hx/S4V2PNW4OMg3WizRrHutyB5la0iCUbZym+W0EQIU=
|
||||
k8s.io/client-go v0.29.3 h1:R/zaZbEAxqComZ9FHeQwOh3Y1ZUs7FaHKZdQtIc2WZg=
|
||||
k8s.io/client-go v0.29.3/go.mod h1:tkDisCvgPfiRpxGnOORfkljmS+UrW+WtXAy2fTvXJB0=
|
||||
k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0=
|
||||
k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo=
|
||||
k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780=
|
||||
|
||||
@@ -2,11 +2,12 @@ package devserver
|
||||
|
||||
// Config is config for inner http server.
|
||||
type Config struct {
|
||||
Enabled bool `json:",default=true"`
|
||||
Host string `json:",optional"`
|
||||
Port int `json:",default=6060"`
|
||||
MetricsPath string `json:",default=/metrics"`
|
||||
HealthPath string `json:",default=/healthz"`
|
||||
EnableMetrics bool `json:",default=true"`
|
||||
EnablePprof bool `json:",default=true"`
|
||||
Enabled bool `json:",default=true"`
|
||||
Host string `json:",optional"`
|
||||
Port int `json:",default=6060"`
|
||||
MetricsPath string `json:",default=/metrics"`
|
||||
HealthPath string `json:",default=/healthz"`
|
||||
EnableMetrics bool `json:",default=true"`
|
||||
EnablePprof bool `json:",default=true"`
|
||||
HealthResponse string `json:",default=OK"`
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@ import (
|
||||
|
||||
var once sync.Once
|
||||
|
||||
// Server is inner http server, expose some useful observability information of app.
|
||||
// For example health check, metrics and pprof.
|
||||
// Server is an inner http server, expose some useful observability information of app.
|
||||
// For example, health check, metrics and pprof.
|
||||
type Server struct {
|
||||
config Config
|
||||
server *http.ServeMux
|
||||
@@ -32,13 +32,14 @@ func NewServer(config Config) *Server {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Server) addRoutes() {
|
||||
func (s *Server) addRoutes(c Config) {
|
||||
// route path, routes list
|
||||
s.handleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
|
||||
_ = json.NewEncoder(w).Encode(s.routes)
|
||||
})
|
||||
|
||||
// health
|
||||
s.handleFunc(s.config.HealthPath, health.CreateHttpHandler())
|
||||
s.handleFunc(s.config.HealthPath, health.CreateHttpHandler(c.HealthResponse))
|
||||
|
||||
// metrics
|
||||
if s.config.EnableMetrics {
|
||||
@@ -46,6 +47,7 @@ func (s *Server) addRoutes() {
|
||||
prometheus.Enable()
|
||||
s.handleFunc(s.config.MetricsPath, promhttp.Handler().ServeHTTP)
|
||||
}
|
||||
|
||||
// pprof
|
||||
if s.config.EnablePprof {
|
||||
s.handleFunc("/debug/pprof/", pprof.Index)
|
||||
@@ -62,8 +64,8 @@ func (s *Server) handleFunc(pattern string, handler http.HandlerFunc) {
|
||||
}
|
||||
|
||||
// StartAsync start inner http server background.
|
||||
func (s *Server) StartAsync() {
|
||||
s.addRoutes()
|
||||
func (s *Server) StartAsync(c Config) {
|
||||
s.addRoutes(c)
|
||||
threading.GoSafe(func() {
|
||||
addr := fmt.Sprintf("%s:%d", s.config.Host, s.config.Port)
|
||||
logx.Infof("Starting dev http server at %s", addr)
|
||||
@@ -78,7 +80,7 @@ func StartAgent(c Config) {
|
||||
once.Do(func() {
|
||||
if c.Enabled {
|
||||
s := NewServer(c)
|
||||
s.StartAsync()
|
||||
s.StartAsync(c)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
var defaultHealthManager = newComboHealthManager()
|
||||
|
||||
type (
|
||||
// Probe represents readiness status of given component.
|
||||
// Probe represents readiness status of a given component.
|
||||
Probe interface {
|
||||
// MarkReady sets a ready state for the endpoint handlers.
|
||||
MarkReady()
|
||||
@@ -44,10 +44,10 @@ func AddProbe(probe Probe) {
|
||||
}
|
||||
|
||||
// CreateHttpHandler create health http handler base on given probe.
|
||||
func CreateHttpHandler() http.HandlerFunc {
|
||||
func CreateHttpHandler(healthResponse string) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, _ *http.Request) {
|
||||
if defaultHealthManager.IsReady() {
|
||||
_, _ = w.Write([]byte("OK"))
|
||||
_, _ = w.Write([]byte(healthResponse))
|
||||
} else {
|
||||
http.Error(w, "Service Unavailable\n"+defaultHealthManager.verboseInfo(),
|
||||
http.StatusServiceUnavailable)
|
||||
|
||||
@@ -121,7 +121,7 @@ func TestAddGlobalProbes(t *testing.T) {
|
||||
|
||||
func TestCreateHttpHandler(t *testing.T) {
|
||||
cleanupForTest(t)
|
||||
srv := httptest.NewServer(CreateHttpHandler())
|
||||
srv := httptest.NewServer(CreateHttpHandler("OK"))
|
||||
defer srv.Close()
|
||||
|
||||
resp, err := http.Get(srv.URL)
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
type DepositServer struct{}
|
||||
|
||||
// Deposit handles the deposit requests.
|
||||
func (*DepositServer) Deposit(ctx context.Context, req *DepositRequest) (*DepositResponse, error) {
|
||||
func (*DepositServer) Deposit(_ context.Context, req *DepositRequest) (*DepositResponse, error) {
|
||||
if req.GetAmount() < 0 {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "cannot deposit %v", req.GetAmount())
|
||||
}
|
||||
|
||||
@@ -301,6 +301,7 @@ go-zero 已被许多公司用于生产部署,接入场景如在线教育、电
|
||||
>97. 上海荣时信息科技有限公司
|
||||
>98. 上海同犀智能科技有限公司
|
||||
>99. 新华三技术有限公司
|
||||
>100. 上海邑脉科技有限公司
|
||||
|
||||
如果贵公司也已使用 go-zero,欢迎在 [登记地址](https://github.com/zeromicro/go-zero/issues/602) 登记,仅仅为了推广,不做其它用途。
|
||||
|
||||
|
||||
@@ -217,9 +217,12 @@ func (ng *engine) notFoundHandler(next http.Handler) http.Handler {
|
||||
handler.TraceHandler(ng.conf.Name,
|
||||
"",
|
||||
handler.WithTraceIgnorePaths(ng.conf.TraceIgnorePaths)),
|
||||
ng.getLogHandler(),
|
||||
)
|
||||
|
||||
if ng.conf.Middlewares.Log {
|
||||
chn = chn.Append(ng.getLogHandler())
|
||||
}
|
||||
|
||||
var h http.Handler
|
||||
if next != nil {
|
||||
h = chn.Then(next)
|
||||
|
||||
@@ -435,7 +435,7 @@ type mockedRouter struct {
|
||||
func (m mockedRouter) ServeHTTP(_ http.ResponseWriter, _ *http.Request) {
|
||||
}
|
||||
|
||||
func (m mockedRouter) Handle(_, _ string, handler http.Handler) error {
|
||||
func (m mockedRouter) Handle(_, _ string, _ http.Handler) error {
|
||||
return errors.New("foo")
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,8 @@ func executeCallbacks(w http.ResponseWriter, r *http.Request, next http.Handler,
|
||||
}
|
||||
}
|
||||
|
||||
func handleVerificationFailure(w http.ResponseWriter, r *http.Request, next http.Handler, strict bool, code int) {
|
||||
func handleVerificationFailure(w http.ResponseWriter, r *http.Request, next http.Handler,
|
||||
strict bool, _ int) {
|
||||
if strict {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
} else {
|
||||
|
||||
@@ -327,7 +327,7 @@ func buildRequest(rs requestSettings) (*http.Request, error) {
|
||||
query,
|
||||
bodySign,
|
||||
}, "\n")
|
||||
rs.signature = codec.HmacBase64([]byte(key), contentOfSign)
|
||||
rs.signature = codec.HmacBase64(key, contentOfSign)
|
||||
}
|
||||
|
||||
var mode string
|
||||
|
||||
@@ -224,7 +224,7 @@ func (m flushableResponseWriter) Write(p []byte) (int, error) {
|
||||
return m.writer.Write(p)
|
||||
}
|
||||
|
||||
func (m flushableResponseWriter) WriteHeader(statusCode int) {
|
||||
func (m flushableResponseWriter) WriteHeader(_ int) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
@@ -240,6 +240,6 @@ func (t *halfWriter) Write(p []byte) (n int, err error) {
|
||||
type badWriter struct {
|
||||
}
|
||||
|
||||
func (b *badWriter) Write(p []byte) (n int, err error) {
|
||||
func (b *badWriter) Write(_ []byte) (n int, err error) {
|
||||
return 0, io.ErrClosedPipe
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ type mockedReadCloser struct {
|
||||
errMsg string
|
||||
}
|
||||
|
||||
func (m mockedReadCloser) Read(p []byte) (n int, err error) {
|
||||
func (m mockedReadCloser) Read(_ []byte) (n int, err error) {
|
||||
return 0, errors.New(m.errMsg)
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ var (
|
||||
Subsystem: "requests",
|
||||
Name: "duration_ms",
|
||||
Help: "http server requests duration(ms).",
|
||||
Labels: []string{"path", "method"},
|
||||
Labels: []string{"path", "method", "code"},
|
||||
Buckets: []float64{5, 10, 25, 50, 100, 250, 500, 750, 1000},
|
||||
})
|
||||
|
||||
@@ -26,7 +26,7 @@ var (
|
||||
Subsystem: "requests",
|
||||
Name: "code_total",
|
||||
Help: "http server requests error count.",
|
||||
Labels: []string{"path", "code", "method"},
|
||||
Labels: []string{"path", "method", "code"},
|
||||
})
|
||||
)
|
||||
|
||||
@@ -37,8 +37,9 @@ func PrometheusHandler(path, method string) func(http.Handler) http.Handler {
|
||||
startTime := timex.Now()
|
||||
cw := response.NewWithCodeResponseWriter(w)
|
||||
defer func() {
|
||||
metricServerReqDur.Observe(timex.Since(startTime).Milliseconds(), path, method)
|
||||
metricServerReqCodeTotal.Inc(path, strconv.Itoa(cw.Code), method)
|
||||
code := strconv.Itoa(cw.Code)
|
||||
metricServerReqDur.Observe(timex.Since(startTime).Milliseconds(), path, method, code)
|
||||
metricServerReqCodeTotal.Inc(path, method, code)
|
||||
}()
|
||||
|
||||
next.ServeHTTP(cw, r)
|
||||
|
||||
@@ -191,6 +191,15 @@ func (tw *timeoutWriter) Write(p []byte) (int, error) {
|
||||
return tw.wbuf.Write(p)
|
||||
}
|
||||
|
||||
func (tw *timeoutWriter) WriteHeader(code int) {
|
||||
tw.mu.Lock()
|
||||
defer tw.mu.Unlock()
|
||||
|
||||
if !tw.wroteHeader {
|
||||
tw.writeHeaderLocked(code)
|
||||
}
|
||||
}
|
||||
|
||||
func (tw *timeoutWriter) writeHeaderLocked(code int) {
|
||||
checkWriteHeaderCode(code)
|
||||
|
||||
@@ -209,15 +218,6 @@ func (tw *timeoutWriter) writeHeaderLocked(code int) {
|
||||
}
|
||||
}
|
||||
|
||||
func (tw *timeoutWriter) WriteHeader(code int) {
|
||||
tw.mu.Lock()
|
||||
defer tw.mu.Unlock()
|
||||
|
||||
if !tw.wroteHeader {
|
||||
tw.writeHeaderLocked(code)
|
||||
}
|
||||
}
|
||||
|
||||
func checkWriteHeaderCode(code int) {
|
||||
if code < 100 || code > 599 {
|
||||
panic(fmt.Sprintf("invalid WriteHeader code %v", code))
|
||||
|
||||
@@ -175,6 +175,6 @@ func (m mockedReader) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m mockedReader) Read(p []byte) (n int, err error) {
|
||||
func (m mockedReader) Read(_ []byte) (n int, err error) {
|
||||
return 0, errors.New("dummy")
|
||||
}
|
||||
|
||||
@@ -15,18 +15,37 @@ import (
|
||||
)
|
||||
|
||||
func TestParseForm(t *testing.T) {
|
||||
var v struct {
|
||||
Name string `form:"name"`
|
||||
Age int `form:"age"`
|
||||
Percent float64 `form:"percent,optional"`
|
||||
}
|
||||
t.Run("slice", func(t *testing.T) {
|
||||
var v struct {
|
||||
Name string `form:"name"`
|
||||
Age int `form:"age"`
|
||||
Percent float64 `form:"percent,optional"`
|
||||
}
|
||||
|
||||
r, err := http.NewRequest(http.MethodGet, "/a?name=hello&age=18&percent=3.4", http.NoBody)
|
||||
assert.Nil(t, err)
|
||||
assert.Nil(t, Parse(r, &v))
|
||||
assert.Equal(t, "hello", v.Name)
|
||||
assert.Equal(t, 18, v.Age)
|
||||
assert.Equal(t, 3.4, v.Percent)
|
||||
r, err := http.NewRequest(
|
||||
http.MethodGet,
|
||||
"/a?name=hello&age=18&percent=3.4",
|
||||
http.NoBody)
|
||||
assert.Nil(t, err)
|
||||
assert.Nil(t, Parse(r, &v))
|
||||
assert.Equal(t, "hello", v.Name)
|
||||
assert.Equal(t, 18, v.Age)
|
||||
assert.Equal(t, 3.4, v.Percent)
|
||||
})
|
||||
|
||||
t.Run("no value", func(t *testing.T) {
|
||||
var v struct {
|
||||
NoValue string `form:"noValue,optional"`
|
||||
}
|
||||
|
||||
r, err := http.NewRequest(
|
||||
http.MethodGet,
|
||||
"/a?name=hello&age=18&percent=3.4&statuses=try&statuses=done&singleValue=one",
|
||||
http.NoBody)
|
||||
assert.Nil(t, err)
|
||||
assert.Nil(t, Parse(r, &v))
|
||||
assert.Equal(t, 0, len(v.NoValue))
|
||||
})
|
||||
}
|
||||
|
||||
func TestParseForm_Error(t *testing.T) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
@@ -88,6 +89,26 @@ func SetOkHandler(handler func(context.Context, any) any) {
|
||||
okHandler = handler
|
||||
}
|
||||
|
||||
// Stream writes data into w with streaming mode.
|
||||
// The ctx is used to control the streaming loop, typically use r.Context().
|
||||
// The fn is called repeatedly until it returns false.
|
||||
func Stream(ctx context.Context, w http.ResponseWriter, fn func(w io.Writer) bool) {
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return
|
||||
default:
|
||||
hasMore := fn(w)
|
||||
if flusher, ok := w.(http.Flusher); ok {
|
||||
flusher.Flush()
|
||||
}
|
||||
if !hasMore {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WriteJson writes v as json string into w with code.
|
||||
func WriteJson(w http.ResponseWriter, code int, v any) {
|
||||
if err := doWriteJson(w, code, v); err != nil {
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package httpx
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -239,6 +242,60 @@ func TestWriteJsonMarshalFailed(t *testing.T) {
|
||||
assert.Equal(t, http.StatusInternalServerError, w.code)
|
||||
}
|
||||
|
||||
func TestStream(t *testing.T) {
|
||||
t.Run("regular case", func(t *testing.T) {
|
||||
channel := make(chan string)
|
||||
go func() {
|
||||
defer close(channel)
|
||||
for index := 0; index < 5; index++ {
|
||||
channel <- fmt.Sprintf("%d", index)
|
||||
}
|
||||
}()
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
Stream(context.Background(), w, func(w io.Writer) bool {
|
||||
output, ok := <-channel
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
outputBytes := bytes.NewBufferString(output)
|
||||
_, err := w.Write(append(outputBytes.Bytes(), []byte("\n")...))
|
||||
return err == nil
|
||||
})
|
||||
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
assert.Equal(t, "0\n1\n2\n3\n4\n", w.Body.String())
|
||||
})
|
||||
|
||||
t.Run("context done", func(t *testing.T) {
|
||||
channel := make(chan string)
|
||||
go func() {
|
||||
defer close(channel)
|
||||
for index := 0; index < 5; index++ {
|
||||
channel <- fmt.Sprintf("num: %d", index)
|
||||
}
|
||||
}()
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
cancel()
|
||||
Stream(ctx, w, func(w io.Writer) bool {
|
||||
output, ok := <-channel
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
outputBytes := bytes.NewBufferString(output)
|
||||
_, err := w.Write(append(outputBytes.Bytes(), []byte("\n")...))
|
||||
return err == nil
|
||||
})
|
||||
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
assert.Equal(t, "", w.Body.String())
|
||||
})
|
||||
}
|
||||
|
||||
type tracedResponseWriter struct {
|
||||
headers map[string][]string
|
||||
builder strings.Builder
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package httpx
|
||||
|
||||
import "net/http"
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const xForwardedFor = "X-Forwarded-For"
|
||||
|
||||
@@ -11,7 +14,7 @@ func GetFormValues(r *http.Request) (map[string]any, error) {
|
||||
}
|
||||
|
||||
if err := r.ParseMultipartForm(maxMemory); err != nil {
|
||||
if err != http.ErrNotMultipart {
|
||||
if !errors.Is(err, http.ErrNotMultipart) {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,12 @@ package gogen
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"go/ast"
|
||||
goformat "go/format"
|
||||
"go/importer"
|
||||
goparser "go/parser"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -48,6 +53,10 @@ var (
|
||||
noStructTagApi string
|
||||
//go:embed testdata/nest_type_api.api
|
||||
nestTypeApi string
|
||||
//go:embed testdata/import_twice.api
|
||||
importTwiceApi string
|
||||
//go:embed testdata/another_import_api.api
|
||||
anotherImportApi string
|
||||
)
|
||||
|
||||
func TestParser(t *testing.T) {
|
||||
@@ -232,6 +241,46 @@ func TestHasImportApi(t *testing.T) {
|
||||
validate(t, filename)
|
||||
}
|
||||
|
||||
func TestImportTwiceOnExperimental(t *testing.T) {
|
||||
defaultExperimental := env.Get(env.GoctlExperimental)
|
||||
env.Set(t, env.GoctlExperimental, "on")
|
||||
defer env.Set(t, env.GoctlExperimental, defaultExperimental)
|
||||
|
||||
filename := "greet.api"
|
||||
err := os.WriteFile(filename, []byte(importTwiceApi), os.ModePerm)
|
||||
assert.Nil(t, err)
|
||||
defer os.Remove(filename)
|
||||
|
||||
importApiName := "importApi.api"
|
||||
err = os.WriteFile(importApiName, []byte(importApi), os.ModePerm)
|
||||
assert.Nil(t, err)
|
||||
defer os.Remove(importApiName)
|
||||
|
||||
hasImportApiName := "hasImportApi.api"
|
||||
err = os.WriteFile(hasImportApiName, []byte(hasImportApi), os.ModePerm)
|
||||
assert.Nil(t, err)
|
||||
defer os.Remove(hasImportApiName)
|
||||
|
||||
anotherImportApiName := "anotherImportApi.api"
|
||||
err = os.WriteFile(anotherImportApiName, []byte(anotherImportApi), os.ModePerm)
|
||||
assert.Nil(t, err)
|
||||
defer os.Remove(anotherImportApiName)
|
||||
|
||||
api, err := parser.Parse(filename)
|
||||
assert.Nil(t, err)
|
||||
|
||||
var hasInline bool
|
||||
for _, ty := range api.Types {
|
||||
if ty.Name() == "ImportData" {
|
||||
hasInline = true
|
||||
break
|
||||
}
|
||||
}
|
||||
assert.True(t, hasInline)
|
||||
|
||||
validate(t, filename)
|
||||
}
|
||||
|
||||
func TestNoStructApi(t *testing.T) {
|
||||
filename := "greet.api"
|
||||
err := os.WriteFile(filename, []byte(noStructTagApi), os.ModePerm)
|
||||
@@ -287,6 +336,9 @@ func validateWithCamel(t *testing.T, api, camel string) {
|
||||
code, err := os.ReadFile(path)
|
||||
assert.Nil(t, err)
|
||||
assert.Nil(t, validateCode(string(code)))
|
||||
if strings.HasSuffix(path, "types.go") {
|
||||
assert.Nil(t, checkRedeclaredType(string(code)))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
@@ -301,3 +353,20 @@ func validateCode(code string) error {
|
||||
_, err := goformat.Source([]byte(code))
|
||||
return err
|
||||
}
|
||||
|
||||
func checkRedeclaredType(code string) error {
|
||||
fset := token.NewFileSet()
|
||||
f, err := goparser.ParseFile(fset, "", code, goparser.ParseComments)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
conf := types.Config{
|
||||
Error: func(err error) {},
|
||||
Importer: importer.Default(),
|
||||
}
|
||||
|
||||
info := types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}
|
||||
_, err = conf.Check(f.Name.Name, fset, []*ast.File{f}, &info)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -18,19 +18,6 @@ const defaultLogicPackage = "logic"
|
||||
//go:embed handler.tpl
|
||||
var handlerTemplate string
|
||||
|
||||
type handlerInfo struct {
|
||||
PkgName string
|
||||
ImportPackages string
|
||||
ImportHttpxPackage string
|
||||
HandlerName string
|
||||
RequestType string
|
||||
LogicName string
|
||||
LogicType string
|
||||
Call string
|
||||
HasResp bool
|
||||
HasRequest bool
|
||||
}
|
||||
|
||||
func genHandler(dir, rootPkg string, cfg *config.Config, group spec.Group, route spec.Route) error {
|
||||
handler := getHandlerName(route)
|
||||
handlerPath := getHandlerFolderPath(group, route)
|
||||
@@ -40,23 +27,6 @@ func genHandler(dir, rootPkg string, cfg *config.Config, group spec.Group, route
|
||||
handler = strings.Title(handler)
|
||||
logicName = pkgName
|
||||
}
|
||||
|
||||
return doGenToFile(dir, handler, cfg, group, route, handlerInfo{
|
||||
PkgName: pkgName,
|
||||
ImportPackages: genHandlerImports(group, route, rootPkg),
|
||||
HandlerName: handler,
|
||||
RequestType: util.Title(route.RequestTypeName()),
|
||||
LogicName: logicName,
|
||||
LogicType: strings.Title(getLogicName(route)),
|
||||
Call: strings.Title(strings.TrimSuffix(handler, "Handler")),
|
||||
HasResp: len(route.ResponseTypeName()) > 0,
|
||||
HasRequest: len(route.RequestTypeName()) > 0,
|
||||
})
|
||||
}
|
||||
|
||||
func doGenToFile(dir, handler string, cfg *config.Config, group spec.Group,
|
||||
route spec.Route, handleObj handlerInfo,
|
||||
) error {
|
||||
filename, err := format.FileNamingFormat(cfg.NamingFormat, handler)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -70,7 +40,19 @@ func doGenToFile(dir, handler string, cfg *config.Config, group spec.Group,
|
||||
category: category,
|
||||
templateFile: handlerTemplateFile,
|
||||
builtinTemplate: handlerTemplate,
|
||||
data: handleObj,
|
||||
data: map[string]any{
|
||||
"PkgName": pkgName,
|
||||
"ImportPackages": genHandlerImports(group, route, rootPkg),
|
||||
"HandlerName": handler,
|
||||
"RequestType": util.Title(route.RequestTypeName()),
|
||||
"LogicName": logicName,
|
||||
"LogicType": strings.Title(getLogicName(route)),
|
||||
"Call": strings.Title(strings.TrimSuffix(handler, "Handler")),
|
||||
"HasResp": len(route.ResponseTypeName()) > 0,
|
||||
"HasRequest": len(route.RequestTypeName()) > 0,
|
||||
"HasDoc": len(route.JoinedDoc()) > 0,
|
||||
"Doc": getDoc(route.JoinedDoc()),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ func genLogicByRoute(dir, rootPkg string, cfg *config.Config, group spec.Group,
|
||||
category: category,
|
||||
templateFile: logicTemplateFile,
|
||||
builtinTemplate: logicTemplate,
|
||||
data: map[string]string{
|
||||
data: map[string]any{
|
||||
"pkgName": subDir[strings.LastIndex(subDir, "/")+1:],
|
||||
"imports": imports,
|
||||
"logic": strings.Title(logic),
|
||||
@@ -70,6 +70,8 @@ func genLogicByRoute(dir, rootPkg string, cfg *config.Config, group spec.Group,
|
||||
"responseType": responseString,
|
||||
"returnString": returnString,
|
||||
"request": requestString,
|
||||
"hasDoc": len(route.JoinedDoc()) > 0,
|
||||
"doc": getDoc(route.JoinedDoc()),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ type (
|
||||
method string
|
||||
path string
|
||||
handler string
|
||||
doc string
|
||||
}
|
||||
)
|
||||
|
||||
@@ -92,13 +93,24 @@ func genRoutes(dir, rootPkg string, cfg *config.Config, api *spec.ApiSpec) error
|
||||
var gbuilder strings.Builder
|
||||
gbuilder.WriteString("[]rest.Route{")
|
||||
for _, r := range g.routes {
|
||||
fmt.Fprintf(&gbuilder, `
|
||||
{
|
||||
Method: %s,
|
||||
Path: "%s",
|
||||
Handler: %s,
|
||||
},`,
|
||||
r.method, r.path, r.handler)
|
||||
var routeString string
|
||||
if len(r.doc) > 0 {
|
||||
routeString = fmt.Sprintf(`
|
||||
{
|
||||
%s
|
||||
Method: %s,
|
||||
Path: "%s",
|
||||
Handler: %s,
|
||||
},`, getDoc(r.doc), r.method, r.path, r.handler)
|
||||
} else {
|
||||
routeString = fmt.Sprintf(`
|
||||
{
|
||||
Method: %s,
|
||||
Path: "%s",
|
||||
Handler: %s,
|
||||
},`, r.method, r.path, r.handler)
|
||||
}
|
||||
fmt.Fprint(&gbuilder, routeString)
|
||||
}
|
||||
|
||||
var jwt string
|
||||
@@ -239,6 +251,7 @@ func getRoutes(api *spec.ApiSpec) ([]group, error) {
|
||||
method: mapping[r.Method],
|
||||
path: r.Path,
|
||||
handler: handler,
|
||||
doc: r.JoinedDoc(),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
{{.ImportPackages}}
|
||||
)
|
||||
|
||||
{{if .HasDoc}}{{.Doc}}{{end}}
|
||||
func {{.HandlerName}}(svcCtx *svc.ServiceContext) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
{{if .HasRequest}}var req types.{{.RequestType}}
|
||||
|
||||
@@ -10,6 +10,7 @@ type {{.logic}} struct {
|
||||
svcCtx *svc.ServiceContext
|
||||
}
|
||||
|
||||
{{if .hasDoc}}{{.doc}}{{end}}
|
||||
func New{{.logic}}(ctx context.Context, svcCtx *svc.ServiceContext) *{{.logic}} {
|
||||
return &{{.logic}}{
|
||||
Logger: logx.WithContext(ctx),
|
||||
|
||||
17
tools/goctl/api/gogen/testdata/another_import_api.api
vendored
Normal file
17
tools/goctl/api/gogen/testdata/another_import_api.api
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
import "importApi.api"
|
||||
|
||||
type AnotherRequest {
|
||||
Name string `path:"name,options=you|me"`
|
||||
}
|
||||
|
||||
type AnotherResponse {
|
||||
Message string `json:"message"` // message
|
||||
}
|
||||
|
||||
@server(
|
||||
group: greet
|
||||
)
|
||||
service A-api {
|
||||
@handler AnotherImportHandler
|
||||
get /greet/from/another/:name(AnotherRequest) returns (AnotherResponse)
|
||||
}
|
||||
@@ -16,5 +16,11 @@ service A-api {
|
||||
@server(
|
||||
handler: GreetHandler
|
||||
)
|
||||
get /greet/from/:name(Request) returns (Response)
|
||||
}
|
||||
get /greet/from/:name (Request) returns (Response)
|
||||
|
||||
@doc(
|
||||
summary: "comment comment comment"
|
||||
)
|
||||
@handler NoResponseHandler
|
||||
get /greet/get (Request)
|
||||
}
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
import "importApi.api"
|
||||
|
||||
type Request struct {
|
||||
type Request {
|
||||
Name string `path:"name,options=you|me"`
|
||||
}
|
||||
|
||||
type Response struct {
|
||||
type Response {
|
||||
Message string `json:"message"` // message
|
||||
}
|
||||
|
||||
@server(
|
||||
group: greet
|
||||
)
|
||||
service A-api {
|
||||
@server(
|
||||
handler: GreetHandler
|
||||
)
|
||||
@handler GreetHandler
|
||||
get /greet/from/:name(Request) returns (Response)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
type ImportData struct {
|
||||
type ImportData {
|
||||
Name string `path:"name,options=you|me"`
|
||||
}
|
||||
}
|
||||
|
||||
2
tools/goctl/api/gogen/testdata/import_twice.api
vendored
Normal file
2
tools/goctl/api/gogen/testdata/import_twice.api
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
import "hasImportApi.api"
|
||||
import "anotherImportApi.api"
|
||||
@@ -181,3 +181,11 @@ func golangExpr(ty spec.Type, pkg ...string) string {
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
func getDoc(doc string) string {
|
||||
if len(doc) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
return "// " + strings.Trim(doc, "\"")
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ require (
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||
github.com/emicklei/proto v1.13.2
|
||||
github.com/fatih/structtag v1.2.0
|
||||
github.com/go-sql-driver/mysql v1.7.1
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/gookit/color v1.5.4
|
||||
github.com/iancoleman/strcase v0.3.0
|
||||
github.com/spf13/cobra v1.8.0
|
||||
@@ -17,11 +17,12 @@ require (
|
||||
github.com/zeromicro/ddl-parser v1.0.5
|
||||
github.com/zeromicro/go-zero v1.6.3
|
||||
golang.org/x/text v0.14.0
|
||||
google.golang.org/grpc v1.62.0
|
||||
google.golang.org/protobuf v1.32.0
|
||||
google.golang.org/grpc v1.63.0
|
||||
google.golang.org/protobuf v1.33.0
|
||||
)
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 // indirect
|
||||
github.com/alicebob/miniredis/v2 v2.31.1 // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210521184019-c5ad59b459ec // indirect
|
||||
@@ -41,7 +42,7 @@ require (
|
||||
github.com/go-openapi/swag v0.22.4 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
@@ -50,7 +51,7 @@ require (
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgx/v5 v5.5.3 // indirect
|
||||
github.com/jackc/pgx/v5 v5.5.4 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
@@ -93,15 +94,15 @@ require (
|
||||
go.uber.org/zap v1.24.0 // indirect
|
||||
golang.org/x/crypto v0.19.0 // indirect
|
||||
golang.org/x/net v0.21.0 // indirect
|
||||
golang.org/x/oauth2 v0.16.0 // indirect
|
||||
golang.org/x/oauth2 v0.17.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
golang.org/x/term v0.17.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
google.golang.org/appengine v1.6.8 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 // indirect
|
||||
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
||||
github.com/DmitriyVTitov/size v1.5.0/go.mod h1:le6rNI4CoLQV1b9gzp1+3d7hMAD/uu2QcJ+aYbNgiU0=
|
||||
@@ -51,8 +53,8 @@ github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
|
||||
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
@@ -63,8 +65,8 @@ github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
||||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
@@ -90,8 +92,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.5.3 h1:Ces6/M3wbDXYpM8JyyPD57ivTtJACFZJd885pdIaV2s=
|
||||
github.com/jackc/pgx/v5 v5.5.3/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||
github.com/jackc/pgx/v5 v5.5.4 h1:Xp2aQS8uXButQdnCMWNmvx6UysWQQC+u1EoizjguY+8=
|
||||
github.com/jackc/pgx/v5 v5.5.4/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
@@ -237,8 +239,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
|
||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||
golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ=
|
||||
golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -285,18 +287,18 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
|
||||
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
|
||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
|
||||
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80 h1:Lj5rbfG876hIAYFjqiJnPHfhXbv+nzTWfm04Fg/XSVU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240123012728-ef4313101c80/go.mod h1:4jWUdICTdgc3Ibxmr8nAJiiLHwQBY0UI0XZcEMaFKaA=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80 h1:AjyfHzEPEFp/NpvfN5g+KDla3EMojjhRVZc1i7cj+oM=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240123012728-ef4313101c80/go.mod h1:PAREbraiVEVGVdTZsVWjSbbTtSyGbAgIIvni8a8CD5s=
|
||||
google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk=
|
||||
google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de h1:F6qOa9AZTYJXOUEr4jDysRDLrm4PHePlge4v4TGAlxY=
|
||||
google.golang.org/genproto v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:VUhTRKeHn9wwcdrk73nvdC9gF178Tzhmt/qyaFcPLSo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de h1:jFNzHPIeuzhdRwVhbZdiym9q0ory/xY3sA+v2wPg8I0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:5iCWqnniDlqZHrd3neWVTOwvh/v6s3232omMecelax8=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY=
|
||||
google.golang.org/grpc v1.63.0 h1:WjKe+dnvABXyPJMD7KDNLxtoGk5tgk+YFWN6cBWjZE8=
|
||||
google.golang.org/grpc v1.63.0/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
|
||||
@@ -178,7 +178,7 @@
|
||||
"short": "Generate postgresql model",
|
||||
"datasource": {
|
||||
"short": "Generate model from datasource",
|
||||
"url": "The data source of database,like \"root:password@tcp(127.0.0.1:3306)/database",
|
||||
"url": "The data source of database,like \"postgres://root:password@127.0.0.1:5432/database?sslmode=disable\"",
|
||||
"table": "The table or table globbing patterns in the database",
|
||||
"schema": "The schema or schema globbing patterns in the database",
|
||||
"cache": "Generate code with cache [optional]",
|
||||
|
||||
@@ -32,11 +32,8 @@ type API struct {
|
||||
func convert2API(a *ast.AST, importSet map[string]lang.PlaceholderType, is *importstack.ImportStack) (*API, error) {
|
||||
var api = new(API)
|
||||
api.importManager = is
|
||||
api.importSet = make(map[string]lang.PlaceholderType)
|
||||
api.importSet = importSet
|
||||
api.Filename = a.Filename
|
||||
for k, v := range importSet {
|
||||
api.importSet[k] = v
|
||||
}
|
||||
one := a.Stmts[0]
|
||||
syntax, ok := one.(*ast.SyntaxStmt)
|
||||
if !ok {
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
[English](readme.md) | 简体中文
|
||||
|
||||
goctl 使用见文档 https://go-zero.dev/cn/docs/goctl/goctl/
|
||||
goctl 使用见文档 https://go-zero.dev/docs/tutorials/cli/overview
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
English | [简体中文](readme-cn.md)
|
||||
|
||||
Read document at https://go-zero.dev/docs/goctl/goctl
|
||||
Read document at https://go-zero.dev/docs/tutorials/cli/overview
|
||||
|
||||
@@ -11,15 +11,17 @@ import (
|
||||
"github.com/zeromicro/go-zero/tools/goctl/util"
|
||||
"github.com/zeromicro/go-zero/tools/goctl/util/format"
|
||||
"github.com/zeromicro/go-zero/tools/goctl/util/pathx"
|
||||
"github.com/zeromicro/go-zero/tools/goctl/util/stringx"
|
||||
)
|
||||
|
||||
//go:embed main.tpl
|
||||
var mainTemplate string
|
||||
|
||||
type MainServiceTemplateData struct {
|
||||
Service string
|
||||
ServerPkg string
|
||||
Pkg string
|
||||
GRPCService string
|
||||
Service string
|
||||
ServerPkg string
|
||||
Pkg string
|
||||
}
|
||||
|
||||
// GenMain generates the main file of the rpc service, which is an rpc service program call entry
|
||||
@@ -57,9 +59,10 @@ func (g *Generator) GenMain(ctx DirContext, proto parser.Proto, cfg *conf.Config
|
||||
}
|
||||
imports = append(imports, remoteImport)
|
||||
serviceNames = append(serviceNames, MainServiceTemplateData{
|
||||
Service: parser.CamelCase(e.Name),
|
||||
ServerPkg: serverPkg,
|
||||
Pkg: proto.PbPackage,
|
||||
GRPCService: parser.CamelCase(e.Name),
|
||||
Service: stringx.From(e.Name).ToCamel(),
|
||||
ServerPkg: serverPkg,
|
||||
Pkg: proto.PbPackage,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package generator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
@@ -86,7 +87,7 @@ func findPbFile(current string, src string, grpc bool) (string, error) {
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err == os.ErrExist {
|
||||
if errors.Is(err, os.ErrExist) {
|
||||
return filepath.Dir(filepath.Join(current, ret)), nil
|
||||
}
|
||||
return "", err
|
||||
|
||||
@@ -92,7 +92,7 @@ func (g *Generator) genServerGroup(ctx DirContext, proto parser.Proto, cfg *conf
|
||||
if err = util.With("server").GoFmt(true).Parse(text).SaveTo(map[string]any{
|
||||
"head": head,
|
||||
"unimplementedServer": fmt.Sprintf("%s.Unimplemented%sServer", proto.PbPackage,
|
||||
stringx.From(service.Name).ToCamel()),
|
||||
parser.CamelCase(service.Name)),
|
||||
"server": stringx.From(service.Name).ToCamel(),
|
||||
"imports": strings.Join(imports.KeysStr(), pathx.NL),
|
||||
"funcs": strings.Join(funcList, pathx.NL),
|
||||
@@ -143,7 +143,7 @@ func (g *Generator) genServerInCompatibility(ctx DirContext, proto parser.Proto,
|
||||
return util.With("server").GoFmt(true).Parse(text).SaveTo(map[string]any{
|
||||
"head": head,
|
||||
"unimplementedServer": fmt.Sprintf("%s.Unimplemented%sServer", proto.PbPackage,
|
||||
stringx.From(service.Name).ToCamel()),
|
||||
parser.CamelCase(service.Name)),
|
||||
"server": stringx.From(service.Name).ToCamel(),
|
||||
"imports": strings.Join(imports.KeysStr(), pathx.NL),
|
||||
"funcs": strings.Join(funcList, pathx.NL),
|
||||
|
||||
@@ -23,7 +23,7 @@ func main() {
|
||||
ctx := svc.NewServiceContext(c)
|
||||
|
||||
s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {
|
||||
{{range .serviceNames}} {{.Pkg}}.Register{{.Service}}Server(grpcServer, {{.ServerPkg}}.New{{.Service}}Server(ctx))
|
||||
{{range .serviceNames}} {{.Pkg}}.Register{{.GRPCService}}Server(grpcServer, {{.ServerPkg}}.New{{.Service}}Server(ctx))
|
||||
{{end}}
|
||||
if c.Mode == service.DevMode || c.Mode == service.TestMode {
|
||||
reflection.Register(grpcServer)
|
||||
|
||||
@@ -115,7 +115,7 @@ func split(content string) ([]string, error) {
|
||||
for {
|
||||
r, _, err := reader.ReadRune()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
if errors.Is(err, io.EOF) {
|
||||
if buffer.Len() > 0 {
|
||||
list = append(list, buffer.String())
|
||||
}
|
||||
|
||||
@@ -16,10 +16,15 @@ func Unpacking(name, destPath string, mapper func(f *zip.File) bool) error {
|
||||
}
|
||||
defer r.Close()
|
||||
|
||||
destAbsPath, err := filepath.Abs(destPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, file := range r.File {
|
||||
ok := mapper(file)
|
||||
if ok {
|
||||
err = fileCopy(file, destPath)
|
||||
err = fileCopy(file, destAbsPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -34,7 +39,12 @@ func fileCopy(file *zip.File, destPath string) error {
|
||||
return err
|
||||
}
|
||||
defer rc.Close()
|
||||
filename := filepath.Join(destPath, filepath.Base(file.Name))
|
||||
abs, err := filepath.Abs(file.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
filename := filepath.Join(destPath, filepath.Base(abs))
|
||||
dir := filepath.Dir(filename)
|
||||
err = pathx.MkdirIfNotExist(dir)
|
||||
if err != nil {
|
||||
|
||||
@@ -142,7 +142,7 @@ func (m mockClientConn) GetOrBuildProducer(builder balancer.ProducerBuilder) (
|
||||
return builder.Build(m)
|
||||
}
|
||||
|
||||
func (m mockClientConn) UpdateAddresses(addresses []resolver.Address) {
|
||||
func (m mockClientConn) UpdateAddresses(_ []resolver.Address) {
|
||||
}
|
||||
|
||||
func (m mockClientConn) Connect() {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user