Compare commits

..

31 Commits

Author SHA1 Message Date
Kevin Wan
0e0abc3a95 chore: update warning message (#1487) 2022-01-26 23:47:57 +08:00
anqiansong
696fda1db4 patch: goctl migrate (#1485)
* * Add signal check
* Add deprecated pkg check

* fix typo `replacementBuilderx`

* output to console if verbose

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-01-26 23:24:25 +08:00
Kevin Wan
c1d2634427 chore: update go version for goctl (#1484) 2022-01-26 14:27:43 +08:00
Kevin Wan
4b7a680ac5 refactor: rename from tal-tech to zeromicro for goctl (#1481) 2022-01-25 23:15:07 +08:00
Kevin Wan
b3e7d2901f Feature/trie ac automation (#1479)
* fix: trie ac automation issues

* fix: trie ac automation issues

* fix: trie ac automation issues

* fix: trie ac automation issues
2022-01-25 11:14:56 +08:00
anqiansong
cdf7ec213c fix #1468 (#1478)
Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-01-24 22:23:20 +08:00
Kevin Wan
f1102fb262 chore: optimize string search with Aho–Corasick algorithm (#1476)
* chore: optimize string search with Aho–Corasick algorithm

* chore: optimize keywords replacer

* fix: replacer bugs

* chore: reorder members
2022-01-23 23:37:02 +08:00
Keqi Huang
09d1fad6e0 Polish the words in readme.md (#1475) 2022-01-22 12:20:11 +08:00
Kevin Wan
379c65a3ef docs: add go-zero users (#1473) 2022-01-20 22:36:17 +08:00
Kevin Wan
fdc7f64d6f chore: update unauthorized callback calling order (#1469)
* chore: update unauthorized callback calling order

* chore: add comments
2022-01-20 21:09:45 +08:00
anqiansong
df0f8ed59e Fix/issue#1289 (#1460)
* fix #1289

* Add unit test case

* fix `jwtTransKey`

* fix `jwtTransKey`

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-01-18 11:52:30 +08:00
anqiansong
c903966fc7 patch: save missing templates to disk (#1463)
Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-01-18 10:45:05 +08:00
anqiansong
e57fa8ff53 Fix/issue#1447 (#1458)
* Add data for template to render

* fix #1447

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-01-18 10:36:38 +08:00
Kevin Wan
bf2feee5b7 feat: implement console plain output for debug logs (#1456)
* feat: implement console plain output for debug logs

* chore: rename console encoding to plain

* chore: refactor names
2022-01-17 12:43:15 +08:00
Letian Jiang
ce05c429fc chore: check interface satisfaction w/o allocating new variable (#1454) 2022-01-16 23:34:42 +08:00
Kevin Wan
272a3f347d chore: remove jwt deprecated (#1452) 2022-01-16 10:34:44 +08:00
shenbaise9527
13db7a1931 feat: 支持redis的LTrim方法 (#1443) 2022-01-16 10:27:34 +08:00
Kevin Wan
468c237189 chore: upgrade dependencies (#1444)
* chore: upgrade dependencies

* ci: upgrade go to 1.15
2022-01-14 11:01:02 +08:00
Kevin Wan
b9b80c068b ci: add translator action (#1441) 2022-01-12 17:57:39 +08:00
anqiansong
9b592b3dee Feature rpc protoc (#1251)
* code generation by protoc

* generate pb by protoc direct

* support: grpc code generation by protoc directly

* format code

* check --go_out & --go-grpc_out

* fix typo

* Update version

* fix typo

* optimize: remove deprecated unit test

* format code

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-01-11 20:34:25 +08:00
Kevin Wan
2203809e5e chore: fix typo (#1437) 2022-01-11 20:23:59 +08:00
Kevin Wan
8d6d37f71e remove unnecessary drain, fix data race (#1435)
* remove unnecessary drain, fix data race

* chore: fix parameter order

* refactor: rename MapVoid to ForEach in mr
2022-01-11 16:17:51 +08:00
Kevin Wan
ea4f2af67f fix: mr goroutine leak on context deadline (#1433)
* fix: mr goroutine leak on context deadline

* test: update fx test check
2022-01-10 22:06:10 +08:00
Kevin Wan
53af194ef9 chore: refactor periodlimit (#1428)
* chore: refactor periodlimit

* chore: add comments
2022-01-09 16:22:34 +08:00
Kevin Wan
5e0e2d2b14 docs: add go-zero users (#1425) 2022-01-08 21:41:27 +08:00
Kevin Wan
74c99184c5 docs: add go-zero users (#1424) 2022-01-08 17:08:44 +08:00
Kevin Wan
eb4b86137a fix: golint issue (#1423) 2022-01-08 16:06:56 +08:00
Kevin Wan
9c4f4f3b4e update docs (#1421) 2022-01-07 12:08:45 +08:00
spectatorMrZ
240132e7c7 Fix pg model generation without tag (#1407)
1. fix pg model struct haven't tag
2. add pg command test from datasource
2022-01-07 10:45:26 +08:00
anqiansong
9d67fc4cfb feat: Add migrate (#1419)
* Add migrate

* Remove unused module

* refactor filename

* rename refactor to migrate

Co-authored-by: anqiansong <anqiansong@bytedance.com>
2022-01-06 18:48:34 +08:00
Kevin Wan
892f93a716 docs: update install readme (#1417) 2022-01-05 12:31:49 +08:00
190 changed files with 2724 additions and 874 deletions

View File

@@ -15,7 +15,7 @@ jobs:
- name: Set up Go 1.x - name: Set up Go 1.x
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: ^1.14 go-version: ^1.15
id: go id: go
- name: Check out code into the Go module directory - name: Check out code into the Go module directory

18
.github/workflows/issue-translator.yml vendored Normal file
View File

@@ -0,0 +1,18 @@
name: 'issue-translator'
on:
issue_comment:
types: [created]
issues:
types: [opened]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: tomsun28/issues-translate-action@v2.6
with:
IS_MODIFY_TITLE: true
# not require, default false, . Decide whether to modify the issue title
# if true, the robot account @Issues-translate-bot must have modification permissions, invite @Issues-translate-bot to your project or use your custom bot.
CUSTOM_BOT_NOTE: Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿
# not require. Customize the translation robot prefix message.

View File

@@ -40,7 +40,7 @@ We will help you to contribute in different areas like filing issues, developing
getting your work reviewed and merged. getting your work reviewed and merged.
If you have questions about the development process, If you have questions about the development process,
feel free to [file an issue](https://github.com/tal-tech/go-zero/issues/new/choose). feel free to [file an issue](https://github.com/zeromicro/go-zero/issues/new/choose).
## Find something to work on ## Find something to work on
@@ -50,10 +50,10 @@ Here is how you get started.
### Find a good first topic ### Find a good first topic
[go-zero](https://github.com/tal-tech/go-zero) has beginner-friendly issues that provide a good first issue. [go-zero](https://github.com/zeromicro/go-zero) has beginner-friendly issues that provide a good first issue.
For example, [go-zero](https://github.com/tal-tech/go-zero) has For example, [go-zero](https://github.com/zeromicro/go-zero) has
[help wanted](https://github.com/tal-tech/go-zero/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) and [help wanted](https://github.com/zeromicro/go-zero/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) and
[good first issue](https://github.com/tal-tech/go-zero/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) [good first issue](https://github.com/zeromicro/go-zero/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)
labels for issues that should not need deep knowledge of the system. labels for issues that should not need deep knowledge of the system.
We can help new contributors who wish to work on such issues. We can help new contributors who wish to work on such issues.
@@ -79,7 +79,7 @@ This is a rough outline of what a contributor's workflow looks like:
- Create a topic branch from where to base the contribution. This is usually master. - Create a topic branch from where to base the contribution. This is usually master.
- Make commits of logical units. - Make commits of logical units.
- Push changes in a topic branch to a personal fork of the repository. - Push changes in a topic branch to a personal fork of the repository.
- Submit a pull request to [go-zero](https://github.com/tal-tech/go-zero). - Submit a pull request to [go-zero](https://github.com/zeromicro/go-zero).
## Creating Pull Requests ## Creating Pull Requests

View File

@@ -14,6 +14,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/zeromicro/go-zero/core/stringx" "github.com/zeromicro/go-zero/core/stringx"
"go.uber.org/goleak"
) )
func TestBuffer(t *testing.T) { func TestBuffer(t *testing.T) {
@@ -563,9 +564,6 @@ func equal(t *testing.T, stream Stream, data []interface{}) {
} }
func runCheckedTest(t *testing.T, fn func(t *testing.T)) { func runCheckedTest(t *testing.T, fn func(t *testing.T)) {
goroutines := runtime.NumGoroutine() defer goleak.VerifyNone(t)
fn(t) fn(t)
// let scheduler schedule first
time.Sleep(time.Millisecond)
assert.True(t, runtime.NumGoroutine() <= goroutines)
} }

View File

@@ -8,9 +8,8 @@ import (
"github.com/zeromicro/go-zero/core/stores/redis" "github.com/zeromicro/go-zero/core/stores/redis"
) )
const ( // to be compatible with aliyun redis, we cannot use `local key = KEYS[1]` to reuse the key
// to be compatible with aliyun redis, we cannot use `local key = KEYS[1]` to reuse the key const periodScript = `local limit = tonumber(ARGV[1])
periodScript = `local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2]) local window = tonumber(ARGV[2])
local current = redis.call("INCRBY", KEYS[1], 1) local current = redis.call("INCRBY", KEYS[1], 1)
if current == 1 then if current == 1 then
@@ -23,8 +22,6 @@ elseif current == limit then
else else
return 0 return 0
end` end`
zoneDiff = 3600 * 8 // GMT+8 for our services
)
const ( const (
// Unknown means not initialized state. // Unknown means not initialized state.
@@ -104,7 +101,9 @@ func (h *PeriodLimit) Take(key string) (int, error) {
func (h *PeriodLimit) calcExpireSeconds() int { func (h *PeriodLimit) calcExpireSeconds() int {
if h.align { if h.align {
unix := time.Now().Unix() + zoneDiff now := time.Now()
_, offset := now.Zone()
unix := now.Unix() + int64(offset)
return h.period - int(unix%int64(h.period)) return h.period - int(unix%int64(h.period))
} }
@@ -112,6 +111,8 @@ func (h *PeriodLimit) calcExpireSeconds() int {
} }
// Align returns a func to customize a PeriodLimit with alignment. // Align returns a func to customize a PeriodLimit with alignment.
// For example, if we want to limit end users with 5 sms verification messages every day,
// we need to align with the local timezone and the start of the day.
func Align() PeriodOption { func Align() PeriodOption {
return func(l *PeriodLimit) { return func(l *PeriodLimit) {
l.align = true l.align = true

View File

@@ -85,8 +85,8 @@ func (lim *TokenLimiter) Allow() bool {
} }
// AllowN reports whether n events may happen at time now. // AllowN reports whether n events may happen at time now.
// Use this method if you intend to drop / skip events that exceed the rate rate. // Use this method if you intend to drop / skip events that exceed the rate.
// Otherwise use Reserve or Wait. // Otherwise, use Reserve or Wait.
func (lim *TokenLimiter) AllowN(now time.Time, n int) bool { func (lim *TokenLimiter) AllowN(now time.Time, n int) bool {
return lim.reserveN(now, n) return lim.reserveN(now, n)
} }
@@ -112,7 +112,8 @@ func (lim *TokenLimiter) reserveN(now time.Time, n int) bool {
// Lua boolean false -> r Nil bulk reply // Lua boolean false -> r Nil bulk reply
if err == redis.Nil { if err == redis.Nil {
return false return false
} else if err != nil { }
if err != nil {
logx.Errorf("fail to use rate limiter: %s, use in-process limiter for rescue", err) logx.Errorf("fail to use rate limiter: %s, use in-process limiter for rescue", err)
lim.startMonitor() lim.startMonitor()
return lim.rescueLimiter.AllowN(now, n) return lim.rescueLimiter.AllowN(now, n)

View File

@@ -3,10 +3,11 @@ package logx
// A LogConf is a logging config. // A LogConf is a logging config.
type LogConf struct { type LogConf struct {
ServiceName string `json:",optional"` ServiceName string `json:",optional"`
Mode string `json:",default=console,options=console|file|volume"` Mode string `json:",default=console,options=[console,file,volume]"`
Encoding string `json:",default=json,options=[json,plain]"`
TimeFormat string `json:",optional"` TimeFormat string `json:",optional"`
Path string `json:",default=logs"` Path string `json:",default=logs"`
Level string `json:",default=info,options=info|error|severe"` Level string `json:",default=info,options=[info,error,severe]"`
Compress bool `json:",optional"` Compress bool `json:",optional"`
KeepDays int `json:",optional"` KeepDays int `json:",optional"`
StackCooldownMillis int `json:",default=100"` StackCooldownMillis int `json:",default=100"`

View File

@@ -79,10 +79,15 @@ func (l *durationLogger) WithDuration(duration time.Duration) Logger {
} }
func (l *durationLogger) write(writer io.Writer, level string, val interface{}) { func (l *durationLogger) write(writer io.Writer, level string, val interface{}) {
outputJson(writer, &durationLogger{ switch encoding {
Timestamp: getTimestamp(), case plainEncodingType:
Level: level, writePlainAny(writer, level, val, l.Duration)
Content: val, default:
Duration: l.Duration, outputJson(writer, &durationLogger{
}) Timestamp: getTimestamp(),
Level: level,
Content: val,
Duration: l.Duration,
})
}
} }

View File

@@ -37,6 +37,19 @@ func TestWithDurationInfo(t *testing.T) {
assert.True(t, strings.Contains(builder.String(), "duration"), builder.String()) assert.True(t, strings.Contains(builder.String(), "duration"), builder.String())
} }
func TestWithDurationInfoConsole(t *testing.T) {
old := encoding
encoding = plainEncodingType
defer func() {
encoding = old
}()
var builder strings.Builder
log.SetOutput(&builder)
WithDuration(time.Second).Info("foo")
assert.True(t, strings.Contains(builder.String(), "ms"), builder.String())
}
func TestWithDurationInfof(t *testing.T) { func TestWithDurationInfof(t *testing.T) {
var builder strings.Builder var builder strings.Builder
log.SetOutput(&builder) log.SetOutput(&builder)

View File

@@ -1,6 +1,7 @@
package logx package logx
import ( import (
"bytes"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
@@ -31,6 +32,15 @@ const (
SevereLevel SevereLevel
) )
const (
jsonEncodingType = iota
plainEncodingType
jsonEncoding = "json"
plainEncoding = "plain"
plainEncodingSep = '\t'
)
const ( const (
accessFilename = "access.log" accessFilename = "access.log"
errorFilename = "error.log" errorFilename = "error.log"
@@ -65,6 +75,7 @@ var (
timeFormat = "2006-01-02T15:04:05.000Z07" timeFormat = "2006-01-02T15:04:05.000Z07"
writeConsole bool writeConsole bool
logLevel uint32 logLevel uint32
encoding = jsonEncodingType
// use uint32 for atomic operations // use uint32 for atomic operations
disableStat uint32 disableStat uint32
infoLog io.WriteCloser infoLog io.WriteCloser
@@ -124,6 +135,12 @@ func SetUp(c LogConf) error {
if len(c.TimeFormat) > 0 { if len(c.TimeFormat) > 0 {
timeFormat = c.TimeFormat timeFormat = c.TimeFormat
} }
switch c.Encoding {
case plainEncoding:
encoding = plainEncodingType
default:
encoding = jsonEncodingType
}
switch c.Mode { switch c.Mode {
case consoleMode: case consoleMode:
@@ -407,21 +424,31 @@ func infoTextSync(msg string) {
} }
func outputAny(writer io.Writer, level string, val interface{}) { func outputAny(writer io.Writer, level string, val interface{}) {
info := logEntry{ switch encoding {
Timestamp: getTimestamp(), case plainEncodingType:
Level: level, writePlainAny(writer, level, val)
Content: val, default:
info := logEntry{
Timestamp: getTimestamp(),
Level: level,
Content: val,
}
outputJson(writer, info)
} }
outputJson(writer, info)
} }
func outputText(writer io.Writer, level, msg string) { func outputText(writer io.Writer, level, msg string) {
info := logEntry{ switch encoding {
Timestamp: getTimestamp(), case plainEncodingType:
Level: level, writePlainText(writer, level, msg)
Content: msg, default:
info := logEntry{
Timestamp: getTimestamp(),
Level: level,
Content: msg,
}
outputJson(writer, info)
} }
outputJson(writer, info)
} }
func outputError(writer io.Writer, msg string, callDepth int) { func outputError(writer io.Writer, msg string, callDepth int) {
@@ -565,6 +592,62 @@ func statSync(msg string) {
} }
} }
func writePlainAny(writer io.Writer, level string, val interface{}, fields ...string) {
switch v := val.(type) {
case string:
writePlainText(writer, level, v, fields...)
case error:
writePlainText(writer, level, v.Error(), fields...)
case fmt.Stringer:
writePlainText(writer, level, v.String(), fields...)
default:
var buf bytes.Buffer
buf.WriteString(getTimestamp())
buf.WriteByte(plainEncodingSep)
buf.WriteString(level)
for _, item := range fields {
buf.WriteByte(plainEncodingSep)
buf.WriteString(item)
}
buf.WriteByte(plainEncodingSep)
if err := json.NewEncoder(&buf).Encode(val); err != nil {
log.Println(err.Error())
return
}
buf.WriteByte('\n')
if atomic.LoadUint32(&initialized) == 0 || writer == nil {
log.Println(buf.String())
return
}
if _, err := writer.Write(buf.Bytes()); err != nil {
log.Println(err.Error())
}
}
}
func writePlainText(writer io.Writer, level, msg string, fields ...string) {
var buf bytes.Buffer
buf.WriteString(getTimestamp())
buf.WriteByte(plainEncodingSep)
buf.WriteString(level)
for _, item := range fields {
buf.WriteByte(plainEncodingSep)
buf.WriteString(item)
}
buf.WriteByte(plainEncodingSep)
buf.WriteString(msg)
buf.WriteByte('\n')
if atomic.LoadUint32(&initialized) == 0 || writer == nil {
log.Println(buf.String())
return
}
if _, err := writer.Write(buf.Bytes()); err != nil {
log.Println(err.Error())
}
}
type logWriter struct { type logWriter struct {
logger *log.Logger logger *log.Logger
} }

View File

@@ -141,6 +141,78 @@ func TestStructedLogInfov(t *testing.T) {
}) })
} }
func TestStructedLogInfoConsoleAny(t *testing.T) {
doTestStructedLogConsole(t, func(writer io.WriteCloser) {
infoLog = writer
}, func(v ...interface{}) {
old := encoding
encoding = plainEncodingType
defer func() {
encoding = old
}()
Infov(v)
})
}
func TestStructedLogInfoConsoleAnyString(t *testing.T) {
doTestStructedLogConsole(t, func(writer io.WriteCloser) {
infoLog = writer
}, func(v ...interface{}) {
old := encoding
encoding = plainEncodingType
defer func() {
encoding = old
}()
Infov(fmt.Sprint(v...))
})
}
func TestStructedLogInfoConsoleAnyError(t *testing.T) {
doTestStructedLogConsole(t, func(writer io.WriteCloser) {
infoLog = writer
}, func(v ...interface{}) {
old := encoding
encoding = plainEncodingType
defer func() {
encoding = old
}()
Infov(errors.New(fmt.Sprint(v...)))
})
}
func TestStructedLogInfoConsoleAnyStringer(t *testing.T) {
doTestStructedLogConsole(t, func(writer io.WriteCloser) {
infoLog = writer
}, func(v ...interface{}) {
old := encoding
encoding = plainEncodingType
defer func() {
encoding = old
}()
Infov(ValStringer{
val: fmt.Sprint(v...),
})
})
}
func TestStructedLogInfoConsoleText(t *testing.T) {
doTestStructedLogConsole(t, func(writer io.WriteCloser) {
infoLog = writer
}, func(v ...interface{}) {
old := encoding
encoding = plainEncodingType
defer func() {
encoding = old
}()
Info(fmt.Sprint(v...))
})
}
func TestStructedLogSlow(t *testing.T) { func TestStructedLogSlow(t *testing.T) {
doTestStructedLog(t, levelSlow, func(writer io.WriteCloser) { doTestStructedLog(t, levelSlow, func(writer io.WriteCloser) {
slowLog = writer slowLog = writer
@@ -432,6 +504,17 @@ func doTestStructedLog(t *testing.T, level string, setup func(writer io.WriteClo
assert.True(t, strings.Contains(val, message)) assert.True(t, strings.Contains(val, message))
} }
func doTestStructedLogConsole(t *testing.T, setup func(writer io.WriteCloser),
write func(...interface{})) {
const message = "hello there"
writer := new(mockWriter)
setup(writer)
atomic.StoreUint32(&initialized, 1)
write(message)
println(writer.String())
assert.True(t, strings.Contains(writer.String(), message))
}
func testSetLevelTwiceWithMode(t *testing.T, mode string) { func testSetLevelTwiceWithMode(t *testing.T, mode string) {
SetUp(LogConf{ SetUp(LogConf{
Mode: mode, Mode: mode,
@@ -456,3 +539,11 @@ func testSetLevelTwiceWithMode(t *testing.T, mode string) {
ErrorStackf(message) ErrorStackf(message)
assert.Equal(t, 0, writer.builder.Len()) assert.Equal(t, 0, writer.builder.Len())
} }
type ValStringer struct {
val string
}
func (v ValStringer) String() string {
return v.val
}

View File

@@ -77,16 +77,24 @@ func (l *traceLogger) WithDuration(duration time.Duration) Logger {
} }
func (l *traceLogger) write(writer io.Writer, level string, val interface{}) { func (l *traceLogger) write(writer io.Writer, level string, val interface{}) {
outputJson(writer, &traceLogger{ traceID := traceIdFromContext(l.ctx)
logEntry: logEntry{ spanID := spanIdFromContext(l.ctx)
Timestamp: getTimestamp(),
Level: level, switch encoding {
Duration: l.Duration, case plainEncodingType:
Content: val, writePlainAny(writer, level, val, l.Duration, traceID, spanID)
}, default:
Trace: traceIdFromContext(l.ctx), outputJson(writer, &traceLogger{
Span: spanIdFromContext(l.ctx), logEntry: logEntry{
}) Timestamp: getTimestamp(),
Level: level,
Duration: l.Duration,
Content: val,
},
Trace: traceID,
Span: spanID,
})
}
} }
// WithContext sets ctx to log, for keeping tracing information. // WithContext sets ctx to log, for keeping tracing information.

View File

@@ -82,6 +82,37 @@ func TestTraceInfo(t *testing.T) {
assert.True(t, strings.Contains(buf.String(), spanKey)) assert.True(t, strings.Contains(buf.String(), spanKey))
} }
func TestTraceInfoConsole(t *testing.T) {
old := encoding
encoding = plainEncodingType
defer func() {
encoding = old
}()
var buf mockWriter
atomic.StoreUint32(&initialized, 1)
infoLog = newLogWriter(log.New(&buf, "", flags))
otp := otel.GetTracerProvider()
tp := sdktrace.NewTracerProvider(sdktrace.WithSampler(sdktrace.AlwaysSample()))
otel.SetTracerProvider(tp)
defer otel.SetTracerProvider(otp)
ctx, _ := tp.Tracer("foo").Start(context.Background(), "bar")
l := WithContext(ctx).(*traceLogger)
SetLevel(InfoLevel)
l.WithDuration(time.Second).Info(testlog)
assert.True(t, strings.Contains(buf.String(), traceIdFromContext(ctx)))
assert.True(t, strings.Contains(buf.String(), spanIdFromContext(ctx)))
buf.Reset()
l.WithDuration(time.Second).Infof(testlog)
assert.True(t, strings.Contains(buf.String(), traceIdFromContext(ctx)))
assert.True(t, strings.Contains(buf.String(), spanIdFromContext(ctx)))
buf.Reset()
l.WithDuration(time.Second).Infov(testlog)
assert.True(t, strings.Contains(buf.String(), traceIdFromContext(ctx)))
assert.True(t, strings.Contains(buf.String(), spanIdFromContext(ctx)))
}
func TestTraceSlow(t *testing.T) { func TestTraceSlow(t *testing.T) {
var buf mockWriter var buf mockWriter
atomic.StoreUint32(&initialized, 1) atomic.StoreUint32(&initialized, 1)

View File

@@ -742,7 +742,9 @@ func getValueWithChainedKeys(m Valuer, keys []string) (interface{}, bool) {
if len(keys) == 1 { if len(keys) == 1 {
v, ok := m.Value(keys[0]) v, ok := m.Value(keys[0])
return v, ok return v, ok
} else if len(keys) > 1 { }
if len(keys) > 1 {
if v, ok := m.Value(keys[0]); ok { if v, ok := m.Value(keys[0]); ok {
if nextm, ok := v.(map[string]interface{}); ok { if nextm, ok := v.(map[string]interface{}); ok {
return getValueWithChainedKeys(MapValuer(nextm), keys[1:]) return getValueWithChainedKeys(MapValuer(nextm), keys[1:])

View File

@@ -24,12 +24,12 @@ var (
) )
type ( type (
// ForEachFunc is used to do element processing, but no output.
ForEachFunc func(item interface{})
// GenerateFunc is used to let callers send elements into source. // GenerateFunc is used to let callers send elements into source.
GenerateFunc func(source chan<- interface{}) GenerateFunc func(source chan<- interface{})
// MapFunc is used to do element processing and write the output to writer. // MapFunc is used to do element processing and write the output to writer.
MapFunc func(item interface{}, writer Writer) MapFunc func(item interface{}, writer Writer)
// VoidMapFunc is used to do element processing, but no output.
VoidMapFunc func(item interface{})
// MapperFunc is used to do element processing and write the output to writer, // MapperFunc is used to do element processing and write the output to writer,
// use cancel func to cancel the processing. // use cancel func to cancel the processing.
MapperFunc func(item interface{}, writer Writer, cancel func(error)) MapperFunc func(item interface{}, writer Writer, cancel func(error))
@@ -69,7 +69,6 @@ func Finish(fns ...func() error) error {
cancel(err) cancel(err)
} }
}, func(pipe <-chan interface{}, cancel func(error)) { }, func(pipe <-chan interface{}, cancel func(error)) {
drain(pipe)
}, WithWorkers(len(fns))) }, WithWorkers(len(fns)))
} }
@@ -79,7 +78,7 @@ func FinishVoid(fns ...func()) {
return return
} }
MapVoid(func(source chan<- interface{}) { ForEach(func(source chan<- interface{}) {
for _, fn := range fns { for _, fn := range fns {
source <- fn source <- fn
} }
@@ -89,6 +88,13 @@ func FinishVoid(fns ...func()) {
}, WithWorkers(len(fns))) }, WithWorkers(len(fns)))
} }
// ForEach maps all elements from given generate but no output.
func ForEach(generate GenerateFunc, mapper ForEachFunc, opts ...Option) {
drain(Map(generate, func(item interface{}, writer Writer) {
mapper(item)
}, opts...))
}
// Map maps all elements generated from given generate func, and returns an output channel. // Map maps all elements generated from given generate func, and returns an output channel.
func Map(generate GenerateFunc, mapper MapFunc, opts ...Option) chan interface{} { func Map(generate GenerateFunc, mapper MapFunc, opts ...Option) chan interface{} {
options := buildOptions(opts...) options := buildOptions(opts...)
@@ -106,11 +112,11 @@ func Map(generate GenerateFunc, mapper MapFunc, opts ...Option) chan interface{}
func MapReduce(generate GenerateFunc, mapper MapperFunc, reducer ReducerFunc, func MapReduce(generate GenerateFunc, mapper MapperFunc, reducer ReducerFunc,
opts ...Option) (interface{}, error) { opts ...Option) (interface{}, error) {
source := buildSource(generate) source := buildSource(generate)
return MapReduceWithSource(source, mapper, reducer, opts...) return MapReduceChan(source, mapper, reducer, opts...)
} }
// MapReduceWithSource maps all elements from source, and reduce the output elements with given reducer. // MapReduceChan maps all elements from source, and reduce the output elements with given reducer.
func MapReduceWithSource(source <-chan interface{}, mapper MapperFunc, reducer ReducerFunc, func MapReduceChan(source <-chan interface{}, mapper MapperFunc, reducer ReducerFunc,
opts ...Option) (interface{}, error) { opts ...Option) (interface{}, error) {
options := buildOptions(opts...) options := buildOptions(opts...)
output := make(chan interface{}) output := make(chan interface{})
@@ -160,13 +166,18 @@ func MapReduceWithSource(source <-chan interface{}, mapper MapperFunc, reducer R
mapper(item, w, cancel) mapper(item, w, cancel)
}, source, collector, done, options.workers) }, source, collector, done, options.workers)
value, ok := <-output select {
if err := retErr.Load(); err != nil { case <-options.ctx.Done():
return nil, err cancel(context.DeadlineExceeded)
} else if ok { return nil, context.DeadlineExceeded
return value, nil case value, ok := <-output:
} else { if err := retErr.Load(); err != nil {
return nil, ErrReduceNoOutput return nil, err
} else if ok {
return value, nil
} else {
return nil, ErrReduceNoOutput
}
} }
} }
@@ -175,18 +186,12 @@ func MapReduceWithSource(source <-chan interface{}, mapper MapperFunc, reducer R
func MapReduceVoid(generate GenerateFunc, mapper MapperFunc, reducer VoidReducerFunc, opts ...Option) error { func MapReduceVoid(generate GenerateFunc, mapper MapperFunc, reducer VoidReducerFunc, opts ...Option) error {
_, err := MapReduce(generate, mapper, func(input <-chan interface{}, writer Writer, cancel func(error)) { _, err := MapReduce(generate, mapper, func(input <-chan interface{}, writer Writer, cancel func(error)) {
reducer(input, cancel) reducer(input, cancel)
// We need to write a placeholder to let MapReduce to continue on reducer done,
// otherwise, all goroutines are waiting. The placeholder will be discarded by MapReduce.
writer.Write(lang.Placeholder)
}, opts...) }, opts...)
return err if errors.Is(err, ErrReduceNoOutput) {
} return nil
}
// MapVoid maps all elements from given generate but no output. return err
func MapVoid(generate GenerateFunc, mapper VoidMapFunc, opts ...Option) {
drain(Map(generate, func(item interface{}, writer Writer) {
mapper(item)
}, opts...))
} }
// WithContext customizes a mapreduce processing accepts a given ctx. // WithContext customizes a mapreduce processing accepts a given ctx.

View File

@@ -13,6 +13,7 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/zeromicro/go-zero/core/stringx" "github.com/zeromicro/go-zero/core/stringx"
"github.com/zeromicro/go-zero/core/syncx" "github.com/zeromicro/go-zero/core/syncx"
"go.uber.org/goleak"
) )
var errDummy = errors.New("dummy") var errDummy = errors.New("dummy")
@@ -22,6 +23,8 @@ func init() {
} }
func TestFinish(t *testing.T) { func TestFinish(t *testing.T) {
defer goleak.VerifyNone(t)
var total uint32 var total uint32
err := Finish(func() error { err := Finish(func() error {
atomic.AddUint32(&total, 2) atomic.AddUint32(&total, 2)
@@ -39,14 +42,20 @@ func TestFinish(t *testing.T) {
} }
func TestFinishNone(t *testing.T) { func TestFinishNone(t *testing.T) {
defer goleak.VerifyNone(t)
assert.Nil(t, Finish()) assert.Nil(t, Finish())
} }
func TestFinishVoidNone(t *testing.T) { func TestFinishVoidNone(t *testing.T) {
defer goleak.VerifyNone(t)
FinishVoid() FinishVoid()
} }
func TestFinishErr(t *testing.T) { func TestFinishErr(t *testing.T) {
defer goleak.VerifyNone(t)
var total uint32 var total uint32
err := Finish(func() error { err := Finish(func() error {
atomic.AddUint32(&total, 2) atomic.AddUint32(&total, 2)
@@ -63,6 +72,8 @@ func TestFinishErr(t *testing.T) {
} }
func TestFinishVoid(t *testing.T) { func TestFinishVoid(t *testing.T) {
defer goleak.VerifyNone(t)
var total uint32 var total uint32
FinishVoid(func() { FinishVoid(func() {
atomic.AddUint32(&total, 2) atomic.AddUint32(&total, 2)
@@ -75,7 +86,57 @@ func TestFinishVoid(t *testing.T) {
assert.Equal(t, uint32(10), atomic.LoadUint32(&total)) assert.Equal(t, uint32(10), atomic.LoadUint32(&total))
} }
func TestForEach(t *testing.T) {
const tasks = 1000
t.Run("all", func(t *testing.T) {
defer goleak.VerifyNone(t)
var count uint32
ForEach(func(source chan<- interface{}) {
for i := 0; i < tasks; i++ {
source <- i
}
}, func(item interface{}) {
atomic.AddUint32(&count, 1)
}, WithWorkers(-1))
assert.Equal(t, tasks, int(count))
})
t.Run("odd", func(t *testing.T) {
defer goleak.VerifyNone(t)
var count uint32
ForEach(func(source chan<- interface{}) {
for i := 0; i < tasks; i++ {
source <- i
}
}, func(item interface{}) {
if item.(int)%2 == 0 {
atomic.AddUint32(&count, 1)
}
})
assert.Equal(t, tasks/2, int(count))
})
t.Run("all", func(t *testing.T) {
defer goleak.VerifyNone(t)
ForEach(func(source chan<- interface{}) {
for i := 0; i < tasks; i++ {
source <- i
}
}, func(item interface{}) {
panic("foo")
})
})
}
func TestMap(t *testing.T) { func TestMap(t *testing.T) {
defer goleak.VerifyNone(t)
tests := []struct { tests := []struct {
mapper MapFunc mapper MapFunc
expect int expect int
@@ -128,6 +189,8 @@ func TestMap(t *testing.T) {
} }
func TestMapReduce(t *testing.T) { func TestMapReduce(t *testing.T) {
defer goleak.VerifyNone(t)
tests := []struct { tests := []struct {
mapper MapperFunc mapper MapperFunc
reducer ReducerFunc reducer ReducerFunc
@@ -203,7 +266,22 @@ func TestMapReduce(t *testing.T) {
} }
} }
func TestMapReducePanicBothMapperAndReducer(t *testing.T) {
defer goleak.VerifyNone(t)
_, _ = MapReduce(func(source chan<- interface{}) {
source <- 0
source <- 1
}, func(item interface{}, writer Writer, cancel func(error)) {
panic("foo")
}, func(pipe <-chan interface{}, writer Writer, cancel func(error)) {
panic("bar")
})
}
func TestMapReduceWithReduerWriteMoreThanOnce(t *testing.T) { func TestMapReduceWithReduerWriteMoreThanOnce(t *testing.T) {
defer goleak.VerifyNone(t)
assert.Panics(t, func() { assert.Panics(t, func() {
MapReduce(func(source chan<- interface{}) { MapReduce(func(source chan<- interface{}) {
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
@@ -220,6 +298,8 @@ func TestMapReduceWithReduerWriteMoreThanOnce(t *testing.T) {
} }
func TestMapReduceVoid(t *testing.T) { func TestMapReduceVoid(t *testing.T) {
defer goleak.VerifyNone(t)
var value uint32 var value uint32
tests := []struct { tests := []struct {
mapper MapperFunc mapper MapperFunc
@@ -296,6 +376,8 @@ func TestMapReduceVoid(t *testing.T) {
} }
func TestMapReduceVoidWithDelay(t *testing.T) { func TestMapReduceVoidWithDelay(t *testing.T) {
defer goleak.VerifyNone(t)
var result []int var result []int
err := MapReduceVoid(func(source chan<- interface{}) { err := MapReduceVoid(func(source chan<- interface{}) {
source <- 0 source <- 0
@@ -319,9 +401,11 @@ func TestMapReduceVoidWithDelay(t *testing.T) {
} }
func TestMapVoid(t *testing.T) { func TestMapVoid(t *testing.T) {
defer goleak.VerifyNone(t)
const tasks = 1000 const tasks = 1000
var count uint32 var count uint32
MapVoid(func(source chan<- interface{}) { ForEach(func(source chan<- interface{}) {
for i := 0; i < tasks; i++ { for i := 0; i < tasks; i++ {
source <- i source <- i
} }
@@ -333,6 +417,8 @@ func TestMapVoid(t *testing.T) {
} }
func TestMapReducePanic(t *testing.T) { func TestMapReducePanic(t *testing.T) {
defer goleak.VerifyNone(t)
v, err := MapReduce(func(source chan<- interface{}) { v, err := MapReduce(func(source chan<- interface{}) {
source <- 0 source <- 0
source <- 1 source <- 1
@@ -350,6 +436,8 @@ func TestMapReducePanic(t *testing.T) {
} }
func TestMapReduceVoidCancel(t *testing.T) { func TestMapReduceVoidCancel(t *testing.T) {
defer goleak.VerifyNone(t)
var result []int var result []int
err := MapReduceVoid(func(source chan<- interface{}) { err := MapReduceVoid(func(source chan<- interface{}) {
source <- 0 source <- 0
@@ -371,6 +459,8 @@ func TestMapReduceVoidCancel(t *testing.T) {
} }
func TestMapReduceVoidCancelWithRemains(t *testing.T) { func TestMapReduceVoidCancelWithRemains(t *testing.T) {
defer goleak.VerifyNone(t)
var done syncx.AtomicBool var done syncx.AtomicBool
var result []int var result []int
err := MapReduceVoid(func(source chan<- interface{}) { err := MapReduceVoid(func(source chan<- interface{}) {
@@ -396,6 +486,8 @@ func TestMapReduceVoidCancelWithRemains(t *testing.T) {
} }
func TestMapReduceWithoutReducerWrite(t *testing.T) { func TestMapReduceWithoutReducerWrite(t *testing.T) {
defer goleak.VerifyNone(t)
uids := []int{1, 2, 3} uids := []int{1, 2, 3}
res, err := MapReduce(func(source chan<- interface{}) { res, err := MapReduce(func(source chan<- interface{}) {
for _, uid := range uids { for _, uid := range uids {
@@ -412,6 +504,8 @@ func TestMapReduceWithoutReducerWrite(t *testing.T) {
} }
func TestMapReduceVoidPanicInReducer(t *testing.T) { func TestMapReduceVoidPanicInReducer(t *testing.T) {
defer goleak.VerifyNone(t)
const message = "foo" const message = "foo"
var done syncx.AtomicBool var done syncx.AtomicBool
err := MapReduceVoid(func(source chan<- interface{}) { err := MapReduceVoid(func(source chan<- interface{}) {
@@ -431,6 +525,8 @@ func TestMapReduceVoidPanicInReducer(t *testing.T) {
} }
func TestMapReduceWithContext(t *testing.T) { func TestMapReduceWithContext(t *testing.T) {
defer goleak.VerifyNone(t)
var done syncx.AtomicBool var done syncx.AtomicBool
var result []int var result []int
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
@@ -452,7 +548,7 @@ func TestMapReduceWithContext(t *testing.T) {
} }
}, WithContext(ctx)) }, WithContext(ctx))
assert.NotNil(t, err) assert.NotNil(t, err)
assert.Equal(t, ErrReduceNoOutput, err) assert.Equal(t, context.DeadlineExceeded, err)
} }
func BenchmarkMapReduce(b *testing.B) { func BenchmarkMapReduce(b *testing.B) {

View File

@@ -93,8 +93,8 @@ func New(addr string, opts ...Option) *Redis {
return r return r
} }
// Deprecated: use New instead, will be removed in v2.
// NewRedis returns a Redis. // NewRedis returns a Redis.
// Deprecated: use New instead, will be removed in v2.
func NewRedis(redisAddr, redisType string, redisPass ...string) *Redis { func NewRedis(redisAddr, redisType string, redisPass ...string) *Redis {
var opts []Option var opts []Option
if redisType == ClusterType { if redisType == ClusterType {
@@ -880,6 +880,18 @@ func (s *Redis) Lrem(key string, count int, value string) (val int, err error) {
return return
} }
// Ltrim is the implementation of redis ltrim command.
func (s *Redis) Ltrim(key string, start, stop int64) error {
return s.brk.DoWithAcceptable(func() error {
conn, err := getRedis(s)
if err != nil {
return err
}
return conn.LTrim(key, start, stop).Err()
}, acceptable)
}
// Mget is the implementation of redis mget command. // Mget is the implementation of redis mget command.
func (s *Redis) Mget(keys ...string) (val []string, err error) { func (s *Redis) Mget(keys ...string) (val []string, err error) {
err = s.brk.DoWithAcceptable(func() error { err = s.brk.DoWithAcceptable(func() error {

View File

@@ -361,6 +361,11 @@ func TestRedis_List(t *testing.T) {
vals, err = client.Lrange("key", 0, 10) vals, err = client.Lrange("key", 0, 10)
assert.Nil(t, err) assert.Nil(t, err)
assert.EqualValues(t, []string{"value2", "value3", "value4"}, vals) assert.EqualValues(t, []string{"value2", "value3", "value4"}, vals)
err = client.Ltrim("key", 0, 1)
assert.Nil(t, err)
vals, err = client.Lrange("key", 0, 10)
assert.Nil(t, err)
assert.EqualValues(t, []string{"value2", "value3"}, vals)
}) })
} }

View File

@@ -2,6 +2,8 @@ package stringx
type node struct { type node struct {
children map[rune]*node children map[rune]*node
fail *node
depth int
end bool end bool
} }
@@ -12,17 +14,19 @@ func (n *node) add(word string) {
} }
nd := n nd := n
for _, char := range chars { var depth int
for i, char := range chars {
if nd.children == nil { if nd.children == nil {
child := new(node) child := new(node)
nd.children = map[rune]*node{ child.depth = i + 1
char: child, nd.children = map[rune]*node{char: child}
}
nd = child nd = child
} else if child, ok := nd.children[char]; ok { } else if child, ok := nd.children[char]; ok {
nd = child nd = child
depth++
} else { } else {
child := new(node) child := new(node)
child.depth = i + 1
nd.children[char] = child nd.children[char] = child
nd = child nd = child
} }
@@ -30,3 +34,67 @@ func (n *node) add(word string) {
nd.end = true nd.end = true
} }
func (n *node) build() {
var nodes []*node
for _, child := range n.children {
child.fail = n
nodes = append(nodes, child)
}
for len(nodes) > 0 {
nd := nodes[0]
nodes = nodes[1:]
for key, child := range nd.children {
nodes = append(nodes, child)
cur := nd
for cur != nil {
if cur.fail == nil {
child.fail = n
break
}
if fail, ok := cur.fail.children[key]; ok {
child.fail = fail
break
}
cur = cur.fail
}
}
}
}
func (n *node) find(chars []rune) []scope {
var scopes []scope
size := len(chars)
cur := n
for i := 0; i < size; i++ {
child, ok := cur.children[chars[i]]
if ok {
cur = child
} else {
for cur != n {
cur = cur.fail
if child, ok = cur.children[chars[i]]; ok {
cur = child
break
}
}
if child == nil {
continue
}
}
for child != n {
if child.end {
scopes = append(scopes, scope{
start: i + 1 - child.depth,
stop: i + 1,
})
}
child = child.fail
}
}
return scopes
}

View File

@@ -0,0 +1,87 @@
//go:build go1.18
// +build go1.18
package stringx
import (
"fmt"
"math/rand"
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func FuzzNodeFind(f *testing.F) {
rand.Seed(time.Now().UnixNano())
f.Add(10)
f.Fuzz(func(t *testing.T, keys int) {
str := Randn(rand.Intn(100) + 50)
keywords := make(map[string]struct{})
for i := 0; i < keys; i++ {
keyword := Randn(rand.Intn(10) + 5)
if !strings.Contains(str, keyword) {
keywords[keyword] = struct{}{}
}
}
size := len(str)
var scopes []scope
var n node
for i := 0; i < size%20; i++ {
start := rand.Intn(size)
stop := start + rand.Intn(20) + 1
if stop > size {
stop = size
}
if start == stop {
continue
}
keyword := str[start:stop]
if _, ok := keywords[keyword]; ok {
continue
}
keywords[keyword] = struct{}{}
var pos int
for pos <= len(str)-len(keyword) {
val := str[pos:]
p := strings.Index(val, keyword)
if p < 0 {
break
}
scopes = append(scopes, scope{
start: pos + p,
stop: pos + p + len(keyword),
})
pos += p + 1
}
}
for keyword := range keywords {
n.add(keyword)
}
n.build()
var buf strings.Builder
buf.WriteString("keywords:\n")
for key := range keywords {
fmt.Fprintf(&buf, "\t%q,\n", key)
}
buf.WriteString("scopes:\n")
for _, scp := range scopes {
fmt.Fprintf(&buf, "\t{%d, %d},\n", scp.start, scp.stop)
}
fmt.Fprintf(&buf, "text:\n\t%s\n", str)
defer func() {
if r := recover(); r != nil {
t.Errorf(buf.String())
}
}()
assert.ElementsMatchf(t, scopes, n.find([]rune(str)), buf.String())
})
}

195
core/stringx/node_test.go Normal file
View File

@@ -0,0 +1,195 @@
package stringx
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestFuzzNodeCase1(t *testing.T) {
keywords := []string{
"cs8Zh",
"G1OihlVuBz",
"K6azS2FBHjI",
"DQKvghI4",
"l7bA86Sze",
"tjBLZhCao",
"nEsXmVzP",
"cbRh8UE1nO3s",
"Wta3R2WcbGP",
"jpOIcA",
"TtkRr4k9hI",
"OKbSo0clAYTtk",
"uJs1WToEanlKV",
"05Y02iFD2",
"x2uJs1WToEanlK",
"ieaSWe",
"Kg",
"FD2bCKFazH",
}
scopes := []scope{
{62, 72},
{52, 65},
{21, 34},
{1, 10},
{19, 33},
{36, 42},
{42, 44},
{7, 17},
}
n := new(node)
for _, key := range keywords {
n.add(key)
}
n.build()
assert.ElementsMatch(t, scopes, n.find([]rune("Z05Y02iFD2bCKFazHtrx2uJs1WToEanlKVWKieaSWeKgmnUXV0ZjOKbSo0clAYTtkRr4k9hI")))
}
func TestFuzzNodeCase2(t *testing.T) {
keywords := []string{
"IP1NPsJKIvt",
"Iw7hQARwSTw",
"SmZIcA",
"OyxHPYkoQzFO",
"3suCnuSAS5d",
"HUMpbi",
"HPdvbGGpY",
"49qjMtR8bEt",
"a0zrrGKVTJ2",
"WbOBcszeo1FfZ",
"8tHUi5PJI",
"Oa2Di",
"6ZWa5nr1tU",
"o0LJRfmeXB9bF9",
"veF0ehKxH",
"Qp73r",
"B6Rmds4ELY8",
"uNpGybQZG",
"Ogm3JqicRZlA4n",
"FL6LVErKomc84H",
"qv2Pi0xJj3cR1",
"bPWLBg4",
"hYN8Q4M1sw",
"ExkTgNklmlIx",
"eVgHHDOxOUEj",
"5WPEVv0tR",
"CPjnOAqUZgV",
"oR3Ogtz",
"jwk1Zbg",
"DYqguyk8h",
"rieroDmpvYFK",
"MQ9hZnMjDqrNQe",
"EhM4KqkCBd",
"m9xalj6q",
"d5CTL5mzK",
"XJOoTvFtI8U",
"iFAwspJ",
"iGv8ErnRZIuSWX",
"i8C1BqsYX",
"vXN1KOaOgU",
"GHJFB",
"Y6OlAqbZxYG8",
"dzd4QscSih4u",
"SsLYMkKvB9APx",
"gi0huB3",
"CMICHDCSvSrgiACXVkN",
"MwOvyHbaxdaqpZpU",
"wOvyHbaxdaqpZpUbI",
"2TT5WEy",
"eoCq0T2MC",
"ZpUbI7",
"oCq0T2MCp",
"CpLFgLg0g",
"FgLg0gh",
"w5awC5HeoCq",
"1c",
}
scopes := []scope{
{0, 19},
{57, 73},
{58, 75},
{47, 54},
{29, 38},
{70, 76},
{30, 39},
{37, 46},
{40, 47},
{22, 33},
{92, 94},
}
n := new(node)
for _, key := range keywords {
n.add(key)
}
n.build()
assert.ElementsMatch(t, scopes, n.find([]rune("CMICHDCSvSrgiACXVkNF9lw5awC5HeoCq0T2MCpLFgLg0gh2TT5WEyINrMwOvyHbaxdaqpZpUbI7SpIY5yVWf33MuX7K1c")))
}
func TestFuzzNodeCase3(t *testing.T) {
keywords := []string{
"QAraACKOftI4",
"unRmd2EO0",
"s25OtuoU",
"aGlmn7KnbE4HCX",
"kuK6Uh",
"ckuK6Uh",
"uK6Uh",
"Iy",
"h",
"PMSSUNvyi",
"ahz0i",
"Lhs4XZ1e",
"shPp1Va7aQNVme",
"yIUckuK6Uh",
"pKjIyI",
"jIyIUckuK6Uh",
"UckuK6Uh",
"Uh",
"JPAULjQgHJ",
"Wp",
"sbkZxXurrI",
"pKjIyIUckuK6Uh",
}
scopes := []scope{
{9, 15},
{8, 15},
{5, 15},
{1, 7},
{10, 15},
{3, 15},
{0, 2},
{1, 15},
{7, 15},
{13, 15},
{4, 6},
{14, 15},
}
n := new(node)
for _, key := range keywords {
n.add(key)
}
n.build()
assert.ElementsMatch(t, scopes, n.find([]rune("WpKjIyIUckuK6Uh")))
}
func BenchmarkNodeFind(b *testing.B) {
b.ReportAllocs()
keywords := []string{
"A",
"AV",
"AV演员",
"无名氏",
"AV演员色情",
"日本AV女优",
}
trie := new(node)
for _, keyword := range keywords {
trie.add(keyword)
}
trie.build()
for i := 0; i < b.N; i++ {
trie.find([]rune("日本AV演员兼电视、电影演员。无名氏AV女优是xx出道, 日本AV女优们最精彩的表演是AV演员色情表演"))
}
}

View File

@@ -9,7 +9,7 @@ type (
} }
replacer struct { replacer struct {
node *node
mapping map[string]string mapping map[string]string
} }
) )
@@ -17,58 +17,81 @@ type (
// NewReplacer returns a Replacer. // NewReplacer returns a Replacer.
func NewReplacer(mapping map[string]string) Replacer { func NewReplacer(mapping map[string]string) Replacer {
rep := &replacer{ rep := &replacer{
node: new(node),
mapping: mapping, mapping: mapping,
} }
for k := range mapping { for k := range mapping {
rep.add(k) rep.add(k)
} }
rep.build()
return rep return rep
} }
// Replace replaces text with given substitutes.
func (r *replacer) Replace(text string) string { func (r *replacer) Replace(text string) string {
var builder strings.Builder var builder strings.Builder
var start int
chars := []rune(text) chars := []rune(text)
size := len(chars) size := len(chars)
start := -1
for i := 0; i < size; i++ { for start < size {
child, ok := r.children[chars[i]] cur := r.node
if !ok {
builder.WriteRune(chars[i]) if start > 0 {
continue builder.WriteString(string(chars[:start]))
} }
if start < 0 { for i := start; i < size; i++ {
start = i child, ok := cur.children[chars[i]]
} if ok {
end := -1 cur = child
if child.end { } else if cur == r.node {
end = i + 1 builder.WriteRune(chars[i])
} // cur already points to root, set start only
start = i + 1
continue
} else {
curDepth := cur.depth
cur = cur.fail
child, ok = cur.children[chars[i]]
if !ok {
// write this path
builder.WriteString(string(chars[i-curDepth : i+1]))
// go to root
cur = r.node
start = i + 1
continue
}
j := i + 1 failDepth := cur.depth
for ; j < size; j++ { // write path before jump
grandchild, ok := child.children[chars[j]] builder.WriteString(string(chars[start : start+curDepth-failDepth]))
if !ok { start += curDepth - failDepth
cur = child
}
if cur.end {
val := string(chars[i+1-cur.depth : i+1])
builder.WriteString(r.mapping[val])
builder.WriteString(string(chars[i+1:]))
// only matching this path, all previous paths are done
if start >= i+1-cur.depth && i+1 >= size {
return builder.String()
}
chars = []rune(builder.String())
size = len(chars)
builder.Reset()
break break
} }
child = grandchild
if child.end {
end = j + 1
i = j
}
} }
if end > 0 { if !cur.end {
i = j - 1 builder.WriteString(string(chars[start:]))
builder.WriteString(r.mapping[string(chars[start:end])]) return builder.String()
} else {
builder.WriteRune(chars[i])
} }
start = -1
} }
return builder.String() return string(chars)
} }

View File

@@ -0,0 +1,42 @@
//go:build go1.18
// +build go1.18
package stringx
import (
"fmt"
"math/rand"
"strings"
"testing"
)
func FuzzReplacerReplace(f *testing.F) {
keywords := make(map[string]string)
for i := 0; i < 20; i++ {
keywords[Randn(rand.Intn(10)+5)] = Randn(rand.Intn(5) + 1)
}
rep := NewReplacer(keywords)
printableKeywords := func() string {
var buf strings.Builder
for k, v := range keywords {
fmt.Fprintf(&buf, "%q: %q,\n", k, v)
}
return buf.String()
}
f.Add(50)
f.Fuzz(func(t *testing.T, n int) {
text := Randn(rand.Intn(n%50+50) + 1)
defer func() {
if r := recover(); r != nil {
t.Errorf("mapping: %s\ntext: %s", printableKeywords(), text)
}
}()
val := rep.Replace(text)
keys := rep.(*replacer).node.find([]rune(val))
if len(keys) > 0 {
t.Errorf("mapping: %s\ntext: %s\nresult: %s\nmatch: %v",
printableKeywords(), text, val, keys)
}
})
}

View File

@@ -15,6 +15,14 @@ func TestReplacer_Replace(t *testing.T) {
assert.Equal(t, "零1234五", NewReplacer(mapping).Replace("零一二三四五")) assert.Equal(t, "零1234五", NewReplacer(mapping).Replace("零一二三四五"))
} }
func TestReplacer_ReplaceOverlap(t *testing.T) {
mapping := map[string]string{
"3d": "34",
"bc": "23",
}
assert.Equal(t, "a234e", NewReplacer(mapping).Replace("abcde"))
}
func TestReplacer_ReplaceSingleChar(t *testing.T) { func TestReplacer_ReplaceSingleChar(t *testing.T) {
mapping := map[string]string{ mapping := map[string]string{
"二": "2", "二": "2",
@@ -42,3 +50,99 @@ func TestReplacer_ReplaceMultiMatches(t *testing.T) {
} }
assert.Equal(t, "零一23四五一23四五", NewReplacer(mapping).Replace("零一二三四五一二三四五")) assert.Equal(t, "零一23四五一23四五", NewReplacer(mapping).Replace("零一二三四五一二三四五"))
} }
func TestReplacer_ReplaceJumpToFail(t *testing.T) {
mapping := map[string]string{
"bcdf": "1235",
"cde": "234",
}
assert.Equal(t, "ab234fg", NewReplacer(mapping).Replace("abcdefg"))
}
func TestReplacer_ReplaceJumpToFailDup(t *testing.T) {
mapping := map[string]string{
"bcdf": "1235",
"ccde": "2234",
}
assert.Equal(t, "ab2234fg", NewReplacer(mapping).Replace("abccdefg"))
}
func TestReplacer_ReplaceJumpToFailEnding(t *testing.T) {
mapping := map[string]string{
"bcdf": "1235",
"cdef": "2345",
}
assert.Equal(t, "ab2345", NewReplacer(mapping).Replace("abcdef"))
}
func TestReplacer_ReplaceEmpty(t *testing.T) {
mapping := map[string]string{
"bcdf": "1235",
"cdef": "2345",
}
assert.Equal(t, "", NewReplacer(mapping).Replace(""))
}
func TestFuzzReplacerCase1(t *testing.T) {
keywords := map[string]string{
"yQyJykiqoh": "xw",
"tgN70z": "Q2P",
"tXKhEn": "w1G8",
"5nfOW1XZO": "GN",
"f4Ov9i9nHD": "cT",
"1ov9Q": "Y",
"7IrC9n": "400i",
"JQLxonpHkOjv": "XI",
"DyHQ3c7": "Ygxux",
"ffyqJi": "u",
"UHuvXrbD8pni": "dN",
"LIDzNbUlTX": "g",
"yN9WZh2rkc8Q": "3U",
"Vhk11rz8CObceC": "jf",
"R0Rt4H2qChUQf": "7U5M",
"MGQzzPCVKjV9": "yYz",
"B5jUUl0u1XOY": "l4PZ",
"pdvp2qfLgG8X": "BM562",
"ZKl9qdApXJ2": "T",
"37jnugkSevU66": "aOHFX",
}
rep := NewReplacer(keywords)
text := "yjF8fyqJiiqrczOCVyoYbLvrMpnkj"
val := rep.Replace(text)
keys := rep.(*replacer).node.find([]rune(val))
if len(keys) > 0 {
t.Errorf("result: %s, match: %v", val, keys)
}
}
func TestFuzzReplacerCase2(t *testing.T) {
keywords := map[string]string{
"dmv2SGZvq9Yz": "TE",
"rCL5DRI9uFP8": "hvsc8",
"7pSA2jaomgg": "v",
"kWSQvjVOIAxR": "Oje",
"hgU5bYYkD3r6": "qCXu",
"0eh6uI": "MMlt",
"3USZSl85EKeMzw": "Pc",
"JONmQSuXa": "dX",
"EO1WIF": "G",
"uUmFJGVmacjF": "1N",
"DHpw7": "M",
"NYB2bm": "CPya",
"9FiNvBAHHNku5": "7FlDE",
"tJi3I4WxcY": "q5",
"sNJ8Z1ToBV0O": "tl",
"0iOg72QcPo": "RP",
"pSEqeL": "5KZ",
"GOyYqTgmvQ": "9",
"Qv4qCsj": "nl52E",
"wNQ5tOutYu5s8": "6iGa",
}
rep := NewReplacer(keywords)
text := "AoRxrdKWsGhFpXwVqMLWRL74OukwjBuBh0g7pSrk"
val := rep.Replace(text)
keys := rep.(*replacer).node.find([]rune(val))
if len(keys) > 0 {
t.Errorf("result: %s, match: %v", val, keys)
}
}

View File

@@ -39,6 +39,8 @@ func NewTrie(words []string, opts ...TrieOption) Trie {
n.add(word) n.add(word)
} }
n.build()
return n return n
} }
@@ -48,7 +50,7 @@ func (n *trieNode) Filter(text string) (sentence string, keywords []string, foun
return text, nil, false return text, nil, false
} }
scopes := n.findKeywordScopes(chars) scopes := n.find(chars)
keywords = n.collectKeywords(chars, scopes) keywords = n.collectKeywords(chars, scopes)
for _, match := range scopes { for _, match := range scopes {
@@ -65,7 +67,7 @@ func (n *trieNode) FindKeywords(text string) []string {
return nil return nil
} }
scopes := n.findKeywordScopes(chars) scopes := n.find(chars)
return n.collectKeywords(chars, scopes) return n.collectKeywords(chars, scopes)
} }
@@ -85,48 +87,6 @@ func (n *trieNode) collectKeywords(chars []rune, scopes []scope) []string {
return keywords return keywords
} }
func (n *trieNode) findKeywordScopes(chars []rune) []scope {
var scopes []scope
size := len(chars)
start := -1
for i := 0; i < size; i++ {
child, ok := n.children[chars[i]]
if !ok {
continue
}
if start < 0 {
start = i
}
if child.end {
scopes = append(scopes, scope{
start: start,
stop: i + 1,
})
}
for j := i + 1; j < size; j++ {
grandchild, ok := child.children[chars[j]]
if !ok {
break
}
child = grandchild
if child.end {
scopes = append(scopes, scope{
start: start,
stop: j + 1,
})
}
}
start = -1
}
return scopes
}
func (n *trieNode) replaceWithAsterisk(chars []rune, start, stop int) { func (n *trieNode) replaceWithAsterisk(chars []rune, start, stop int) {
for i := start; i < stop; i++ { for i := start; i < stop; i++ {
chars[i] = n.mask chars[i] = n.mask

View File

@@ -6,6 +6,17 @@ import (
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
func TestTrieSimple(t *testing.T) {
trie := NewTrie([]string{
"bc",
"cd",
})
output, keywords, found := trie.Filter("abcd")
assert.True(t, found)
assert.Equal(t, "a***", output)
assert.ElementsMatch(t, []string{"bc", "cd"}, keywords)
}
func TestTrie(t *testing.T) { func TestTrie(t *testing.T) {
tests := []struct { tests := []struct {
input string input string
@@ -14,11 +25,11 @@ func TestTrie(t *testing.T) {
found bool found bool
}{ }{
{ {
input: "日本AV演员兼电视、电影演员。苍井空AV女优是xx出道, 日本AV女优们最精彩的表演是AV演员色情表演", input: "日本AV演员兼电视、电影演员。无名氏AV女优是xx出道, 日本AV女优们最精彩的表演是AV演员色情表演",
output: "日本****兼电视、电影演员。*****女优是xx出道, ******们最精彩的表演是******表演", output: "日本****兼电视、电影演员。*****女优是xx出道, ******们最精彩的表演是******表演",
keywords: []string{ keywords: []string{
"AV演员", "AV演员",
"苍井空", "无名氏",
"AV", "AV",
"日本AV女优", "日本AV女优",
"AV演员色情", "AV演员色情",
@@ -89,7 +100,7 @@ func TestTrie(t *testing.T) {
"一不", "一不",
"AV", "AV",
"AV演员", "AV演员",
"苍井空", "无名氏",
"AV演员色情", "AV演员色情",
"日本AV女优", "日本AV女优",
}) })
@@ -145,20 +156,3 @@ func TestTrieNested(t *testing.T) {
assert.True(t, ok) assert.True(t, ok)
assert.Equal(t, "零########九十", output) assert.Equal(t, "零########九十", output)
} }
func BenchmarkTrie(b *testing.B) {
b.ReportAllocs()
trie := NewTrie([]string{
"A",
"AV",
"AV演员",
"苍井空",
"AV演员色情",
"日本AV女优",
})
for i := 0; i < b.N; i++ {
trie.Filter("日本AV演员兼电视、电影演员。苍井空AV女优是xx出道, 日本AV女优们最精彩的表演是AV演员色情表演")
}
}

View File

@@ -3,10 +3,6 @@ package syncx
import "sync" import "sync"
type ( type (
// SharedCalls is an alias of SingleFlight.
// Deprecated: use SingleFlight.
SharedCalls = SingleFlight
// SingleFlight lets the concurrent calls with the same key to share the call result. // SingleFlight lets the concurrent calls with the same key to share the call result.
// For example, A called F, before it's done, B called F. Then B would not execute F, // For example, A called F, before it's done, B called F. Then B would not execute F,
// and shared the result returned by F which called by A. // and shared the result returned by F which called by A.
@@ -37,12 +33,6 @@ func NewSingleFlight() SingleFlight {
} }
} }
// NewSharedCalls returns a SingleFlight.
// Deprecated: use NewSingleFlight.
func NewSharedCalls() SingleFlight {
return NewSingleFlight()
}
func (g *flightGroup) Do(key string, fn func() (interface{}, error)) (interface{}, error) { func (g *flightGroup) Do(key string, fn func() (interface{}, error)) (interface{}, error) {
c, done := g.createCall(key) c, done := g.createCall(key)
if done { if done {

View File

@@ -10,7 +10,7 @@ import (
) )
// assert that metadataSupplier implements the TextMapCarrier interface // assert that metadataSupplier implements the TextMapCarrier interface
var _ propagation.TextMapCarrier = new(metadataSupplier) var _ propagation.TextMapCarrier = (*metadataSupplier)(nil)
type metadataSupplier struct { type metadataSupplier struct {
metadata *metadata.MD metadata *metadata.MD

40
go.mod
View File

@@ -1,39 +1,34 @@
module github.com/zeromicro/go-zero module github.com/zeromicro/go-zero
go 1.14 go 1.15
require ( require (
github.com/ClickHouse/clickhouse-go v1.5.1 github.com/ClickHouse/clickhouse-go v1.5.1
github.com/DATA-DOG/go-sqlmock v1.5.0 github.com/DATA-DOG/go-sqlmock v1.5.0
github.com/alicebob/miniredis/v2 v2.16.0 github.com/alicebob/miniredis/v2 v2.17.0
github.com/fatih/color v1.9.0 // indirect
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8 github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8
github.com/go-redis/redis v6.15.9+incompatible github.com/go-redis/redis v6.15.9+incompatible
github.com/go-sql-driver/mysql v1.6.0 github.com/go-sql-driver/mysql v1.6.0
github.com/golang-jwt/jwt v3.2.1+incompatible github.com/golang-jwt/jwt/v4 v4.2.0
github.com/golang/mock v1.6.0 github.com/golang/mock v1.6.0
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
github.com/justinas/alice v1.2.0 github.com/justinas/alice v1.2.0
github.com/lib/pq v1.10.3 github.com/lib/pq v1.10.4
github.com/mattn/go-colorable v0.1.6 // indirect
github.com/olekukonko/tablewriter v0.0.5 github.com/olekukonko/tablewriter v0.0.5
github.com/openzipkin/zipkin-go v0.3.0 // indirect
github.com/prometheus/client_golang v1.11.0 github.com/prometheus/client_golang v1.11.0
github.com/spaolacci/murmur3 v1.1.0 github.com/spaolacci/murmur3 v1.1.0
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
go.etcd.io/etcd/api/v3 v3.5.1 go.etcd.io/etcd/api/v3 v3.5.1
go.etcd.io/etcd/client/v3 v3.5.1 go.etcd.io/etcd/client/v3 v3.5.1
go.opentelemetry.io/otel v1.1.0 go.opentelemetry.io/otel v1.3.0
go.opentelemetry.io/otel/exporters/jaeger v1.1.0 go.opentelemetry.io/otel/exporters/jaeger v1.3.0
go.opentelemetry.io/otel/exporters/zipkin v1.1.0 go.opentelemetry.io/otel/exporters/zipkin v1.3.0
go.opentelemetry.io/otel/sdk v1.1.0 go.opentelemetry.io/otel/sdk v1.3.0
go.opentelemetry.io/otel/trace v1.1.0 go.opentelemetry.io/otel/trace v1.3.0
go.uber.org/automaxprocs v1.4.0 go.uber.org/automaxprocs v1.4.0
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b // indirect go.uber.org/goleak v1.1.12
golang.org/x/sys v0.0.0-20211106132015-ebca88c72f68 // indirect golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac google.golang.org/grpc v1.43.0
google.golang.org/genproto v0.0.0-20210928142010-c7af6a1a74c9 // indirect
google.golang.org/grpc v1.42.0
google.golang.org/protobuf v1.27.1 google.golang.org/protobuf v1.27.1
gopkg.in/cheggaaa/pb.v1 v1.0.28 gopkg.in/cheggaaa/pb.v1 v1.0.28
gopkg.in/h2non/gock.v1 v1.1.2 gopkg.in/h2non/gock.v1 v1.1.2
@@ -43,3 +38,14 @@ require (
k8s.io/client-go v0.20.12 k8s.io/client-go v0.20.12
k8s.io/utils v0.0.0-20201110183641-67b214c5f920 k8s.io/utils v0.0.0-20201110183641-67b214c5f920
) )
require (
github.com/fatih/color v1.10.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/openzipkin/zipkin-go v0.4.0 // indirect
golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d // indirect
golang.org/x/sys v0.0.0-20220111092808-5a964db01320 // indirect
google.golang.org/genproto v0.0.0-20220112215332-a9c7c0acf9f2 // indirect
k8s.io/klog/v2 v2.40.1 // indirect
)

103
go.sum
View File

@@ -40,9 +40,7 @@ github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb0
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
github.com/Shopify/sarama v1.30.0/go.mod h1:zujlQQx1kzHsh4jfV1USnptCQrHAEZ2Hk8fTKCulPVs= github.com/Shopify/sarama v1.30.0/go.mod h1:zujlQQx1kzHsh4jfV1USnptCQrHAEZ2Hk8fTKCulPVs=
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0= github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
@@ -51,8 +49,8 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk=
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
github.com/alicebob/miniredis/v2 v2.16.0 h1:ALkyFg7bSTEd1Mkrb4ppq4fnwjklA59dVtIehXCUZkU= github.com/alicebob/miniredis/v2 v2.17.0 h1:EwLdrIS50uczw71Jc7iVSxZluTKj5nfSP8n7ARRnJy0=
github.com/alicebob/miniredis/v2 v2.16.0/go.mod h1:gquAfGbzn92jvtrSC69+6zZnwSODVXVpYDRaGhWaL6I= github.com/alicebob/miniredis/v2 v2.17.0/go.mod h1:gquAfGbzn92jvtrSC69+6zZnwSODVXVpYDRaGhWaL6I=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -92,7 +90,6 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
@@ -107,8 +104,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.m
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY= github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY=
@@ -130,8 +127,14 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0 h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.1/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.2 h1:ahHml/yUpnlb96Rp8HCvtYVPY8ZYpxq3g7UYchIYwbs=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.0/go.mod h1:YkVgnZu1ZjjL7xTxrfm/LLZBfkhTqSR1ydtm6jTKKwI=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
@@ -150,8 +153,8 @@ github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= github.com/golang-jwt/jwt/v4 v4.2.0 h1:besgBTC8w8HjP6NzQdxwKH9Z5oQMZ24ThTrHp3cZ8eU=
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -180,7 +183,6 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@@ -212,8 +214,6 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I= github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I=
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
@@ -263,19 +263,17 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg= github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
@@ -299,24 +297,21 @@ github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c=
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE=
github.com/openzipkin/zipkin-go v0.3.0 h1:XtuXmOLIXLjiU2XduuWREDT0LOKtSgos/g7i7RYyoZQ=
github.com/openzipkin/zipkin-go v0.3.0/go.mod h1:4c3sLeE8xjNqehmF5RpAFLPLJxXscc0R4l6Zg0P1tTQ= github.com/openzipkin/zipkin-go v0.3.0/go.mod h1:4c3sLeE8xjNqehmF5RpAFLPLJxXscc0R4l6Zg0P1tTQ=
github.com/openzipkin/zipkin-go v0.4.0 h1:CtfRrOVZtbDj8rt1WXjklw0kqqJQwICrCKmlfUuBUUw=
github.com/openzipkin/zipkin-go v0.4.0/go.mod h1:4c3sLeE8xjNqehmF5RpAFLPLJxXscc0R4l6Zg0P1tTQ=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM=
github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
@@ -324,7 +319,6 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -347,8 +341,9 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O
github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4= github.com/prometheus/procfs v0.6.0 h1:mxy4L2jP6qMonqmq+aTtOx1ifVWUgG/TAmntgbh3xv4=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/rabbitmq/amqp091-go v1.1.0/go.mod h1:ogQDLSOACsLPsIq0NpbtiifNZi2YOz0VTJ0kHRghqbM= github.com/rabbitmq/amqp091-go v1.1.0/go.mod h1:ogQDLSOACsLPsIq0NpbtiifNZi2YOz0VTJ0kHRghqbM=
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -364,7 +359,6 @@ github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTd
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
@@ -395,21 +389,23 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opentelemetry.io/otel v1.1.0 h1:8p0uMLcyyIx0KHNTgO8o3CW8A1aA+dJZJW6PvnMz0Wc= go.opentelemetry.io/otel v1.3.0 h1:APxLf0eiBwLl+SOXiJJCVYzA1OOJNyAoV8C5RNRyy7Y=
go.opentelemetry.io/otel v1.1.0/go.mod h1:7cww0OW51jQ8IaZChIEdqLwgh+44+7uiTdWsAL0wQpA= go.opentelemetry.io/otel v1.3.0/go.mod h1:PWIKzi6JCp7sM0k9yZ43VX+T345uNbAkDKwHVjb2PTs=
go.opentelemetry.io/otel/exporters/jaeger v1.1.0 h1:VRF+Hf3EePFO6ab7/wfPoyWzSY4z5X0tTvQtV9/Mq8Y= go.opentelemetry.io/otel/exporters/jaeger v1.3.0 h1:HfydzioALdtcB26H5WHc4K47iTETJCdloL7VN579/L0=
go.opentelemetry.io/otel/exporters/jaeger v1.1.0/go.mod h1:D/GIBwAdrFTTqCy1iITpC9nh5rgJpIbFVgkhlz2vCXk= go.opentelemetry.io/otel/exporters/jaeger v1.3.0/go.mod h1:KoYHi1BtkUPncGSRtCe/eh1ijsnePhSkxwzz07vU0Fc=
go.opentelemetry.io/otel/exporters/zipkin v1.1.0 h1:NfP5auMWoVOYnAeQPY+fxNG8UMAu94heSL4rtOL8Bsg= go.opentelemetry.io/otel/exporters/zipkin v1.3.0 h1:uOD28dZ7yIKITTcUS6MeAGNHYy3uhP7DTkhcJM6onlQ=
go.opentelemetry.io/otel/exporters/zipkin v1.1.0/go.mod h1:LZwDnf1mVGTPMq9hdRUHfFBH30SuQvZ1BJaVywpg0VI= go.opentelemetry.io/otel/exporters/zipkin v1.3.0/go.mod h1:LxGGfHIYbvsFnrJtBcazb0yG24xHdDGrT/H6RB9r3+8=
go.opentelemetry.io/otel/sdk v1.1.0 h1:j/1PngUJIDOddkCILQYTevrTIbWd494djgGkSsMit+U= go.opentelemetry.io/otel/sdk v1.3.0 h1:3278edCoH89MEJ0Ky8WQXVmDQv3FX4ZJ3Pp+9fJreAI=
go.opentelemetry.io/otel/sdk v1.1.0/go.mod h1:3aQvM6uLm6C4wJpHtT8Od3vNzeZ34Pqc6bps8MywWzo= go.opentelemetry.io/otel/sdk v1.3.0/go.mod h1:rIo4suHNhQwBIPg9axF8V9CA72Wz2mKF1teNrup8yzs=
go.opentelemetry.io/otel/trace v1.1.0 h1:N25T9qCL0+7IpOT8RrRy0WYlL7y6U0WiUJzXcVdXY/o= go.opentelemetry.io/otel/trace v1.3.0 h1:doy8Hzb1RJ+I3yFhtDmwNc7tIyw1tNMOIsyPzp1NOGY=
go.opentelemetry.io/otel/trace v1.1.0/go.mod h1:i47XtdcBQiktu5IsrPqOHe8w+sBmnLwwHt8wiUsWGTI= go.opentelemetry.io/otel/trace v1.3.0/go.mod h1:c/VDhno8888bvQYmbYLqe41/Ldmr/KKunbvWM4/fEjk=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/automaxprocs v1.4.0 h1:CpDZl6aOlLhReez+8S3eEotD7Jx0Os++lemPlMULQP0= go.uber.org/automaxprocs v1.4.0 h1:CpDZl6aOlLhReez+8S3eEotD7Jx0Os++lemPlMULQP0=
go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q= go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q=
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U=
@@ -447,6 +443,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@@ -456,6 +453,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -488,8 +486,8 @@ 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-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b h1:eB48h3HiRycXNy8E0Gf5e0hv7YT6Kt14L/D73G1fuwo= golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d h1:1n1fc535VhN8SYtD4cDUyNlfpAF2ROMM9+11equK3hs=
golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -511,7 +509,6 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -551,8 +548,8 @@ golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211106132015-ebca88c72f68 h1:Ywe/f3fNleF8I6F6qv3MeFoSZ6CTf2zBMMa/7qVML8M= golang.org/x/sys v0.0.0-20220111092808-5a964db01320 h1:0jf+tOCoZ3LyutmCOWpVni1chK4VfFLhRsDK7MhqGRY=
golang.org/x/sys v0.0.0-20211106132015-ebca88c72f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -568,8 +565,8 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11 h1:GZokNIeuVkl3aZHJchRrr13WCsols02MLUcz1U9is6M=
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
@@ -606,6 +603,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -648,8 +647,8 @@ google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210928142010-c7af6a1a74c9 h1:XTH066D35LyHehRwlYhoK3qA+Hcgvg5xREG4kFQEW1Y= google.golang.org/genproto v0.0.0-20220112215332-a9c7c0acf9f2 h1:z+R4M/SuyaRsj1zu3WC+nIQyfSrSIpuDcY01/R3uCtg=
google.golang.org/genproto v0.0.0-20210928142010-c7af6a1a74c9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220112215332-a9c7c0acf9f2/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
@@ -658,14 +657,13 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k=
google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= google.golang.org/grpc v1.43.0 h1:Eeu7bZtDZ2DpRCsLhUlcrLnvYaMK1Gz86a+hMVvELmM=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -721,8 +719,9 @@ k8s.io/client-go v0.20.12 h1:U75SxTC31BHT9i7CbX/hL4v+U1Wkzy/E1vt5ClDPp3I=
k8s.io/client-go v0.20.12/go.mod h1:NBJj6Evp73Xy/4v/O/RDRaH0+3JoxNfjRxkyRgrdbsA= k8s.io/client-go v0.20.12/go.mod h1:NBJj6Evp73Xy/4v/O/RDRaH0+3JoxNfjRxkyRgrdbsA=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ=
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.40.1 h1:P4RRucWk/lFOlDdkAr3mc7iWFkgKrZY9qZMAgek06S4=
k8s.io/klog/v2 v2.40.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw= k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw=
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=

View File

@@ -87,7 +87,7 @@ go-zero 是一个集成了各种工程实践的包含 web 和 rpc 框架,有
在项目目录下通过如下命令安装: 在项目目录下通过如下命令安装:
```shell ```shell
GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/zeromicro/go-zero GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/tal-tech/go-zero
``` ```
## 5. Quick Start ## 5. Quick Start
@@ -104,10 +104,10 @@ GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/zeromicro
```shell ```shell
# Go 1.15 及之前版本 # Go 1.15 及之前版本
GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/zeromicro/go-zero/tools/goctl@latest GO111MODULE=on GOPROXY=https://goproxy.cn/,direct go get -u github.com/tal-tech/go-zero/tools/goctl@latest
# Go 1.16 及以后版本 # Go 1.16 及以后版本
GOPROXY=https://goproxy.cn/,direct go install github.com/zeromicro/go-zero/tools/goctl@latest GOPROXY=https://goproxy.cn/,direct go install github.com/tal-tech/go-zero/tools/goctl@latest
``` ```
确保 goctl 可执行 确保 goctl 可执行
@@ -235,6 +235,9 @@ go-zero 已被许多公司用于生产部署,接入场景如在线教育、电
>48. ECLOUDVALLEY TECHNOLOGY (HK) LIMITED >48. ECLOUDVALLEY TECHNOLOGY (HK) LIMITED
>48. 馨科智(深圳)科技有限公司 >48. 馨科智(深圳)科技有限公司
>48. 成都松珀科技有限公司 >48. 成都松珀科技有限公司
>48. 亿景智联
>48. 上海扩博智能技术有限公司
>48. 一犀科技成都有限公司
如果贵公司也已使用 go-zero欢迎在 [登记地址](https://github.com/zeromicro/go-zero/issues/602) 登记,仅仅为了推广,不做其它用途。 如果贵公司也已使用 go-zero欢迎在 [登记地址](https://github.com/zeromicro/go-zero/issues/602) 登记,仅仅为了推广,不做其它用途。

View File

@@ -14,7 +14,7 @@ English | [简体中文](readme-cn.md)
## 0. what is go-zero ## 0. what is go-zero
go-zero (listed in CNCF Landscape: [https://landscape.cncf.io/?selected=go-zero](https://landscape.cncf.io/?selected=go-zero)) is a web and rpc framework with lots of builtin engineering practices. Its born to ensure the stability of the busy services with resilience design, and has been serving sites with tens of millions users for years. go-zero (listed in CNCF Landscape: [https://landscape.cncf.io/?selected=go-zero](https://landscape.cncf.io/?selected=go-zero)) is a web and rpc framework with lots of builtin engineering practices. Its born to ensure the stability of the busy services with resilience design and has been serving sites with tens of millions of users for years.
go-zero contains simple API description syntax and code generation tool called `goctl`. You can generate Go, iOS, Android, Kotlin, Dart, TypeScript, JavaScript from .api files with `goctl`. go-zero contains simple API description syntax and code generation tool called `goctl`. You can generate Go, iOS, Android, Kotlin, Dart, TypeScript, JavaScript from .api files with `goctl`.
@@ -23,7 +23,7 @@ Advantages of go-zero:
* improve the stability of the services with tens of millions of daily active users * improve the stability of the services with tens of millions of daily active users
* builtin chained timeout control, concurrency control, rate limit, adaptive circuit breaker, adaptive load shedding, even no configuration needed * builtin chained timeout control, concurrency control, rate limit, adaptive circuit breaker, adaptive load shedding, even no configuration needed
* builtin middlewares also can be integrated into your frameworks * builtin middlewares also can be integrated into your frameworks
* simple API syntax, one command to generate couple of different languages * simple API syntax, one command to generate a couple of different languages
* auto validate the request parameters from clients * auto validate the request parameters from clients
* plenty of builtin microservice management and concurrent toolkits * plenty of builtin microservice management and concurrent toolkits
@@ -31,7 +31,7 @@ Advantages of go-zero:
## 1. Backgrounds of go-zero ## 1. Backgrounds of go-zero
At the beginning of 2018, we decided to re-design our system, from monolithic architecture with Java+MongoDB to microservice architecture. After researches and comparison, we chose to: At the beginning of 2018, we decided to re-design our system, from monolithic architecture with Java+MongoDB to microservice architecture. After research and comparison, we chose to:
* Golang based * Golang based
* great performance * great performance
@@ -40,13 +40,13 @@ At the beginning of 2018, we decided to re-design our system, from monolithic ar
* extreme deployment experience * extreme deployment experience
* less server resource consumption * less server resource consumption
* Self-designed microservice architecture * Self-designed microservice architecture
* I have rich experience on designing microservice architectures * I have rich experience in designing microservice architectures
* easy to location the problems * easy to locate the problems
* easy to extend the features * easy to extend the features
## 2. Design considerations on go-zero ## 2. Design considerations on go-zero
By designing the microservice architecture, we expected to ensure the stability, as well as the productivity. And from just the beginning, we have the following design principles: By designing the microservice architecture, we expected to ensure stability, as well as productivity. And from just the beginning, we have the following design principles:
* keep it simple * keep it simple
* high availability * high availability
@@ -56,7 +56,7 @@ By designing the microservice architecture, we expected to ensure the stability,
* try best to be friendly to the business logic development, encapsulate the complexity * try best to be friendly to the business logic development, encapsulate the complexity
* one thing, one way * one thing, one way
After almost half a year, we finished the transfer from monolithic system to microservice system, and deployed on August 2018. The new system guaranteed the business growth, and the system stability. After almost half a year, we finished the transfer from a monolithic system to microservice system and deployed on August 2018. The new system guaranteed business growth and system stability.
## 3. The implementation and features of go-zero ## 3. The implementation and features of go-zero
@@ -69,28 +69,28 @@ go-zero is a web and rpc framework that integrates lots of engineering practices
* high performance * high performance
* failure-oriented programming, resilience design * failure-oriented programming, resilience design
* builtin service discovery, load balancing * builtin service discovery, load balancing
* builtin concurrency control, adaptive circuit breaker, adaptive load shedding, auto trigger, auto recover * builtin concurrency control, adaptive circuit breaker, adaptive load shedding, auto-trigger, auto recover
* auto validation of API request parameters * auto validation of API request parameters
* chained timeout control * chained timeout control
* auto management of data caching * auto management of data caching
* call tracing, metrics and monitoring * call tracing, metrics, and monitoring
* high concurrency protected * high concurrency protected
As below, go-zero protects the system with couple layers and mechanisms: As below, go-zero protects the system with a couple of layers and mechanisms:
![Resilience](https://raw.githubusercontent.com/zeromicro/zero-doc/main/doc/images/resilience-en.png) ![Resilience](https://raw.githubusercontent.com/zeromicro/zero-doc/main/doc/images/resilience-en.png)
## 4. Future development plans of go-zero ## 4. Future development plans of go-zero
* auto generate API mock server, make the client debugging easier * auto-generate API mock server, make the client debugging easier
* auto generate the simple integration test for the server side just from the .api files * auto-generate the simple integration test for the server-side just from the .api files
## 5. Installation ## 5. Installation
Run the following command under your project: Run the following command under your project:
```shell ```shell
go get -u github.com/zeromicro/go-zero go get -u github.com/tal-tech/go-zero
``` ```
## 6. Quick Start ## 6. Quick Start
@@ -103,14 +103,14 @@ go get -u github.com/zeromicro/go-zero
1. install goctl 1. install goctl
`goctl`can be read as `go control`. `goctl` means not to be controlled by code, instead, we control it. The inside `go` is not `golang`. At the very beginning, I was expecting it to help us improve the productivity, and make our lives easier. `goctl`can be read as `go control`. `goctl` means not to be controlled by code, instead, we control it. The inside `go` is not `golang`. At the very beginning, I was expecting it to help us improve productivity, and make our lives easier.
```shell ```shell
# for Go 1.15 and earlier # for Go 1.15 and earlier
GO111MODULE=on go get -u github.com/zeromicro/go-zero/tools/goctl@latest GO111MODULE=on go get -u github.com/tal-tech/go-zero/tools/goctl@latest
# for Go 1.16 and later # for Go 1.16 and later
go install github.com/zeromicro/go-zero/tools/goctl@latest go install github.com/tal-tech/go-zero/tools/goctl@latest
``` ```
make sure goctl is executable. make sure goctl is executable.
@@ -134,13 +134,13 @@ go get -u github.com/zeromicro/go-zero
} }
``` ```
the .api files also can be generate by goctl, like below: the .api files also can be generated by goctl, like below:
```shell ```shell
goctl api -o greet.api goctl api -o greet.api
``` ```
3. generate the go server side code 3. generate the go server-side code
```shell ```shell
goctl api go -api greet.api -dir greet goctl api go -api greet.api -dir greet
@@ -177,7 +177,7 @@ go get -u github.com/zeromicro/go-zero
go run greet.go -f etc/greet-api.yaml go run greet.go -f etc/greet-api.yaml
``` ```
by default, its listening on port 8888, while it can be changed in configuration file. by default, its listening on port 8888, while it can be changed in the configuration file.
you can check it by curl: you can check it by curl:
@@ -185,7 +185,7 @@ go get -u github.com/zeromicro/go-zero
curl -i http://localhost:8888/greet/from/you curl -i http://localhost:8888/greet/from/you
``` ```
the response looks like: the response looks like below:
```http ```http
HTTP/1.1 200 OK HTTP/1.1 200 OK
@@ -195,10 +195,10 @@ go get -u github.com/zeromicro/go-zero
4. Write the business logic code 4. Write the business logic code
* the dependencies can be passed into the logic within servicecontext.go, like mysql, reds etc. * the dependencies can be passed into the logic within servicecontext.go, like mysql, reds, etc.
* add the logic code in logic package according to .api file * add the logic code in a logic package according to .api file
5. Generate code like Java, TypeScript, Dart, JavaScript etc. just from the api file 5. Generate code like Java, TypeScript, Dart, JavaScript, etc. just from the api file
```shell ```shell
goctl api java -api greet.api -dir greet goctl api java -api greet.api -dir greet

View File

@@ -8,7 +8,7 @@ import (
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
"github.com/golang-jwt/jwt" "github.com/golang-jwt/jwt/v4"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/rest/token" "github.com/zeromicro/go-zero/rest/token"
) )
@@ -113,11 +113,13 @@ func unauthorized(w http.ResponseWriter, r *http.Request, err error, callback Un
detailAuthLog(r, noDetailReason) detailAuthLog(r, noDetailReason)
} }
writer.WriteHeader(http.StatusUnauthorized) // let callback go first, to make sure we respond with user-defined HTTP header
if callback != nil { if callback != nil {
callback(writer, r, err) callback(writer, r, err)
} }
// if user not setting HTTP header, we set header with 401
writer.WriteHeader(http.StatusUnauthorized)
} }
type guardedResponseWriter struct { type guardedResponseWriter struct {

View File

@@ -8,7 +8,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/golang-jwt/jwt" "github.com/golang-jwt/jwt/v4"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@@ -160,9 +160,9 @@ func dumpRequest(r *http.Request) string {
func logBrief(r *http.Request, code int, timer *utils.ElapsedTimer, logs *internal.LogCollector) { func logBrief(r *http.Request, code int, timer *utils.ElapsedTimer, logs *internal.LogCollector) {
var buf bytes.Buffer var buf bytes.Buffer
duration := timer.Duration() duration := timer.Duration()
logger := logx.WithContext(r.Context()) logger := logx.WithContext(r.Context()).WithDuration(duration)
buf.WriteString(fmt.Sprintf("[HTTP] %s - %d - %s - %s - %s - %s", buf.WriteString(fmt.Sprintf("[HTTP] %s - %d - %s - %s - %s",
r.Method, code, r.RequestURI, httpx.GetRemoteAddr(r), r.UserAgent(), timex.ReprOfDuration(duration))) r.Method, code, r.RequestURI, httpx.GetRemoteAddr(r), r.UserAgent()))
if duration > slowThreshold.Load() { if duration > slowThreshold.Load() {
logger.Slowf("[HTTP] %s - %d - %s - %s - %s - slowcall(%s)", logger.Slowf("[HTTP] %s - %d - %s - %s - %s - slowcall(%s)",
r.Method, code, r.RequestURI, httpx.GetRemoteAddr(r), r.UserAgent(), timex.ReprOfDuration(duration)) r.Method, code, r.RequestURI, httpx.GetRemoteAddr(r), r.UserAgent(), timex.ReprOfDuration(duration))

View File

@@ -6,8 +6,8 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"github.com/golang-jwt/jwt" "github.com/golang-jwt/jwt/v4"
"github.com/golang-jwt/jwt/request" "github.com/golang-jwt/jwt/v4/request"
"github.com/zeromicro/go-zero/core/timex" "github.com/zeromicro/go-zero/core/timex"
) )
@@ -120,7 +120,5 @@ func WithResetDuration(duration time.Duration) ParseOption {
} }
func newParser() *jwt.Parser { func newParser() *jwt.Parser {
return &jwt.Parser{ return jwt.NewParser(jwt.WithJSONNumber())
UseJSONNumber: true,
}
} }

View File

@@ -6,7 +6,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/golang-jwt/jwt" "github.com/golang-jwt/jwt/v4"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/zeromicro/go-zero/core/timex" "github.com/zeromicro/go-zero/core/timex"
) )

View File

@@ -8,8 +8,8 @@ import (
"text/template" "text/template"
"github.com/logrusorgru/aurora" "github.com/logrusorgru/aurora"
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/urfave/cli" "github.com/urfave/cli"
) )

View File

@@ -3,7 +3,7 @@ package apigen
import ( import (
"fmt" "fmt"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/urfave/cli" "github.com/urfave/cli"
) )

View File

@@ -4,8 +4,8 @@ import (
"errors" "errors"
"strings" "strings"
"github.com/tal-tech/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"github.com/tal-tech/go-zero/tools/goctl/api/parser" "github.com/zeromicro/go-zero/tools/goctl/api/parser"
"github.com/urfave/cli" "github.com/urfave/cli"
) )

View File

@@ -4,7 +4,7 @@ import (
"os" "os"
"text/template" "text/template"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
) )
const apiTemplate = `import 'api.dart'; const apiTemplate = `import 'api.dart';

View File

@@ -4,7 +4,7 @@ import (
"os" "os"
"text/template" "text/template"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
) )
const dataTemplate = `// --{{with .Info}}{{.Title}}{{end}}-- const dataTemplate = `// --{{with .Info}}{{.Title}}{{end}}--

View File

@@ -6,8 +6,8 @@ import (
"os" "os"
"strings" "strings"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
"github.com/tal-tech/go-zero/tools/goctl/api/util" "github.com/zeromicro/go-zero/tools/goctl/api/util"
) )
func lowCamelCase(s string) string { func lowCamelCase(s string) string {

View File

@@ -7,10 +7,10 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/tal-tech/go-zero/core/stringx" "github.com/zeromicro/go-zero/core/stringx"
"github.com/tal-tech/go-zero/tools/goctl/api/gogen" "github.com/zeromicro/go-zero/tools/goctl/api/gogen"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
"github.com/tal-tech/go-zero/tools/goctl/api/util" "github.com/zeromicro/go-zero/tools/goctl/api/util"
) )
const ( const (

View File

@@ -7,8 +7,8 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/tal-tech/go-zero/tools/goctl/api/parser" "github.com/zeromicro/go-zero/tools/goctl/api/parser"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/urfave/cli" "github.com/urfave/cli"
) )

View File

@@ -11,10 +11,10 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/tal-tech/go-zero/core/errorx" "github.com/zeromicro/go-zero/core/errorx"
"github.com/tal-tech/go-zero/tools/goctl/api/parser" "github.com/zeromicro/go-zero/tools/goctl/api/parser"
"github.com/tal-tech/go-zero/tools/goctl/api/util" "github.com/zeromicro/go-zero/tools/goctl/api/util"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/urfave/cli" "github.com/urfave/cli"
) )

View File

@@ -12,13 +12,13 @@ import (
"time" "time"
"github.com/logrusorgru/aurora" "github.com/logrusorgru/aurora"
"github.com/tal-tech/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
apiformat "github.com/tal-tech/go-zero/tools/goctl/api/format" apiformat "github.com/zeromicro/go-zero/tools/goctl/api/format"
"github.com/tal-tech/go-zero/tools/goctl/api/parser" "github.com/zeromicro/go-zero/tools/goctl/api/parser"
apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util" apiutil "github.com/zeromicro/go-zero/tools/goctl/api/util"
"github.com/tal-tech/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/urfave/cli" "github.com/urfave/cli"
) )

View File

@@ -9,8 +9,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/tools/goctl/api/parser" "github.com/zeromicro/go-zero/tools/goctl/api/parser"
"github.com/tal-tech/go-zero/tools/goctl/rpc/execx"
) )
const testApiTemplate = ` const testApiTemplate = `
@@ -179,6 +178,7 @@ type Response struct {
@server( @server(
jwt: Auth jwt: Auth
jwtTransition: Trans
middleware: TokenValidate middleware: TokenValidate
) )
service A-api { service A-api {
@@ -537,10 +537,8 @@ func validate(t *testing.T, api string) {
} }
func validateWithCamel(t *testing.T, api, camel string) { func validateWithCamel(t *testing.T, api, camel string) {
dir := "_go" dir := t.TempDir()
os.RemoveAll(dir)
err := DoGenProject(api, dir, camel) err := DoGenProject(api, dir, camel)
defer os.RemoveAll(dir)
assert.Nil(t, err) assert.Nil(t, err)
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if strings.HasSuffix(path, ".go") { if strings.HasSuffix(path, ".go") {
@@ -550,9 +548,6 @@ func validateWithCamel(t *testing.T, api, camel string) {
} }
return nil return nil
}) })
_, err = execx.Run("go test ./...", dir)
assert.Nil(t, err)
} }
func validateCode(code string) error { func validateCode(code string) error {

View File

@@ -4,10 +4,10 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
"github.com/tal-tech/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/tal-tech/go-zero/tools/goctl/util/format" "github.com/zeromicro/go-zero/tools/goctl/util/format"
"github.com/tal-tech/go-zero/tools/goctl/vars" "github.com/zeromicro/go-zero/tools/goctl/vars"
) )
const ( const (
@@ -19,6 +19,7 @@ import {{.authImport}}
type Config struct { type Config struct {
rest.RestConf rest.RestConf
{{.auth}} {{.auth}}
{{.jwtTrans}}
} }
` `
@@ -26,6 +27,11 @@ type Config struct {
AccessSecret string AccessSecret string
AccessExpire int64 AccessExpire int64
} }
`
jwtTransTemplate = ` struct {
Secret string
PrevSecret string
}
` `
) )
@@ -40,6 +46,12 @@ func genConfig(dir string, cfg *config.Config, api *spec.ApiSpec) error {
for _, item := range authNames { for _, item := range authNames {
auths = append(auths, fmt.Sprintf("%s %s", item, jwtTemplate)) auths = append(auths, fmt.Sprintf("%s %s", item, jwtTemplate))
} }
jwtTransNames := getJwtTrans(api)
var jwtTransList []string
for _, item := range jwtTransNames {
jwtTransList = append(jwtTransList, fmt.Sprintf("%s %s", item, jwtTransTemplate))
}
authImportStr := fmt.Sprintf("\"%s/rest\"", vars.ProjectOpenSourceURL) authImportStr := fmt.Sprintf("\"%s/rest\"", vars.ProjectOpenSourceURL)
return genFile(fileGenConfig{ return genFile(fileGenConfig{
@@ -53,6 +65,7 @@ func genConfig(dir string, cfg *config.Config, api *spec.ApiSpec) error {
data: map[string]string{ data: map[string]string{
"authImport": authImportStr, "authImport": authImportStr,
"auth": strings.Join(auths, "\n"), "auth": strings.Join(auths, "\n"),
"jwtTrans": strings.Join(jwtTransList, "\n"),
}, },
}) })
} }

View File

@@ -4,9 +4,9 @@ import (
"fmt" "fmt"
"strconv" "strconv"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
"github.com/tal-tech/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/tal-tech/go-zero/tools/goctl/util/format" "github.com/zeromicro/go-zero/tools/goctl/util/format"
) )
const ( const (

View File

@@ -5,13 +5,13 @@ import (
"path" "path"
"strings" "strings"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
"github.com/tal-tech/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/tal-tech/go-zero/tools/goctl/internal/version" "github.com/zeromicro/go-zero/tools/goctl/internal/version"
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util"
"github.com/tal-tech/go-zero/tools/goctl/util/format" "github.com/zeromicro/go-zero/tools/goctl/util/format"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/tal-tech/go-zero/tools/goctl/vars" "github.com/zeromicro/go-zero/tools/goctl/vars"
) )
const ( const (

View File

@@ -6,12 +6,12 @@ import (
"strconv" "strconv"
"strings" "strings"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
"github.com/tal-tech/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/tal-tech/go-zero/tools/goctl/util/format" "github.com/zeromicro/go-zero/tools/goctl/util/format"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/tal-tech/go-zero/tools/goctl/vars" "github.com/zeromicro/go-zero/tools/goctl/vars"
) )
const logicTemplate = `package {{.pkgName}} const logicTemplate = `package {{.pkgName}}

View File

@@ -4,11 +4,11 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
"github.com/tal-tech/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/tal-tech/go-zero/tools/goctl/util/format" "github.com/zeromicro/go-zero/tools/goctl/util/format"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/tal-tech/go-zero/tools/goctl/vars" "github.com/zeromicro/go-zero/tools/goctl/vars"
) )
const mainTemplate = `package main const mainTemplate = `package main

View File

@@ -3,9 +3,9 @@ package gogen
import ( import (
"strings" "strings"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
"github.com/tal-tech/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/tal-tech/go-zero/tools/goctl/util/format" "github.com/zeromicro/go-zero/tools/goctl/util/format"
) )
var middlewareImplementCode = ` var middlewareImplementCode = `
@@ -45,6 +45,8 @@ func genMiddleware(dir string, cfg *config.Config, api *spec.ApiSpec) error {
subdir: middlewareDir, subdir: middlewareDir,
filename: filename + ".go", filename: filename + ".go",
templateName: "contextTemplate", templateName: "contextTemplate",
category: category,
templateFile: middlewareImplementCodeFile,
builtinTemplate: middlewareImplementCode, builtinTemplate: middlewareImplementCode,
data: map[string]string{ data: map[string]string{
"name": strings.Title(name), "name": strings.Title(name),

View File

@@ -8,15 +8,16 @@ import (
"strings" "strings"
"text/template" "text/template"
"github.com/tal-tech/go-zero/core/collection" "github.com/zeromicro/go-zero/core/collection"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
"github.com/tal-tech/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/tal-tech/go-zero/tools/goctl/util/format" "github.com/zeromicro/go-zero/tools/goctl/util/format"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/tal-tech/go-zero/tools/goctl/vars" "github.com/zeromicro/go-zero/tools/goctl/vars"
) )
const ( const (
jwtTransKey = "jwtTransition"
routesFilename = "routes" routesFilename = "routes"
routesTemplate = `// Code generated by goctl. DO NOT EDIT. routesTemplate = `// Code generated by goctl. DO NOT EDIT.
package handler package handler
@@ -58,6 +59,7 @@ type (
authName string authName string
middlewares []string middlewares []string
prefix string prefix string
jwtTrans string
} }
route struct { route struct {
method string method string
@@ -73,7 +75,12 @@ func genRoutes(dir, rootPkg string, cfg *config.Config, api *spec.ApiSpec) error
return err return err
} }
gt := template.Must(template.New("groupTemplate").Parse(routesAdditionTemplate)) templateText, err := pathx.LoadTemplate(category, routesAdditionTemplateFile, routesAdditionTemplate)
if err != nil {
return err
}
gt := template.Must(template.New("groupTemplate").Parse(templateText))
for _, g := range groups { for _, g := range groups {
var gbuilder strings.Builder var gbuilder strings.Builder
gbuilder.WriteString("[]rest.Route{") gbuilder.WriteString("[]rest.Route{")
@@ -91,6 +98,9 @@ func genRoutes(dir, rootPkg string, cfg *config.Config, api *spec.ApiSpec) error
if g.jwtEnabled { if g.jwtEnabled {
jwt = fmt.Sprintf("\n rest.WithJwt(serverCtx.Config.%s.AccessSecret),", g.authName) jwt = fmt.Sprintf("\n rest.WithJwt(serverCtx.Config.%s.AccessSecret),", g.authName)
} }
if len(g.jwtTrans) > 0 {
jwt = jwt + fmt.Sprintf("\n rest.WithJwtTransition(serverCtx.Config.%s.PrevSecret,serverCtx.Config.%s.Secret),", g.jwtTrans, g.jwtTrans)
}
var signature, prefix string var signature, prefix string
if g.signatureEnabled { if g.signatureEnabled {
signature = "\n rest.WithSignature(serverCtx.Config.Signature)," signature = "\n rest.WithSignature(serverCtx.Config.Signature),"
@@ -139,8 +149,8 @@ rest.WithPrefix("%s"),`, g.prefix)
subdir: handlerDir, subdir: handlerDir,
filename: routeFilename, filename: routeFilename,
templateName: "routesTemplate", templateName: "routesTemplate",
category: "", category: category,
templateFile: "", templateFile: routesTemplateFile,
builtinTemplate: routesTemplate, builtinTemplate: routesTemplate,
data: map[string]string{ data: map[string]string{
"importPackages": genRouteImports(rootPkg, api), "importPackages": genRouteImports(rootPkg, api),
@@ -200,6 +210,11 @@ func getRoutes(api *spec.ApiSpec) ([]group, error) {
groupedRoutes.authName = jwt groupedRoutes.authName = jwt
groupedRoutes.jwtEnabled = true groupedRoutes.jwtEnabled = true
} }
jwtTrans := g.GetAnnotation(jwtTransKey)
if len(jwtTrans) > 0 {
groupedRoutes.jwtTrans = jwtTrans
}
signature := g.GetAnnotation("signature") signature := g.GetAnnotation("signature")
if signature == "true" { if signature == "true" {
groupedRoutes.signatureEnabled = true groupedRoutes.signatureEnabled = true

View File

@@ -4,11 +4,11 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
"github.com/tal-tech/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/tal-tech/go-zero/tools/goctl/util/format" "github.com/zeromicro/go-zero/tools/goctl/util/format"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/tal-tech/go-zero/tools/goctl/vars" "github.com/zeromicro/go-zero/tools/goctl/vars"
) )
const ( const (

View File

@@ -7,11 +7,11 @@ import (
"path" "path"
"strings" "strings"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util" apiutil "github.com/zeromicro/go-zero/tools/goctl/api/util"
"github.com/tal-tech/go-zero/tools/goctl/config" "github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util"
"github.com/tal-tech/go-zero/tools/goctl/util/format" "github.com/zeromicro/go-zero/tools/goctl/util/format"
) )
const ( const (
@@ -63,8 +63,8 @@ func genTypes(dir string, cfg *config.Config, api *spec.ApiSpec) error {
subdir: typesDir, subdir: typesDir,
filename: typeFilename, filename: typeFilename,
templateName: "typesTemplate", templateName: "typesTemplate",
category: "", category: category,
templateFile: "", templateFile: typesTemplateFile,
builtinTemplate: typesTemplate, builtinTemplate: typesTemplate,
data: map[string]interface{}{ data: map[string]interface{}{
"types": val, "types": val,

View File

@@ -3,27 +3,35 @@ package gogen
import ( import (
"fmt" "fmt"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/urfave/cli" "github.com/urfave/cli"
) )
const ( const (
category = "api" category = "api"
configTemplateFile = "config.tpl" configTemplateFile = "config.tpl"
contextTemplateFile = "context.tpl" contextTemplateFile = "context.tpl"
etcTemplateFile = "etc.tpl" etcTemplateFile = "etc.tpl"
handlerTemplateFile = "handler.tpl" handlerTemplateFile = "handler.tpl"
logicTemplateFile = "logic.tpl" logicTemplateFile = "logic.tpl"
mainTemplateFile = "main.tpl" mainTemplateFile = "main.tpl"
middlewareImplementCodeFile = "middleware.tpl"
routesTemplateFile = "routes.tpl"
routesAdditionTemplateFile = "route-addition.tpl"
typesTemplateFile = "types.tpl"
) )
var templates = map[string]string{ var templates = map[string]string{
configTemplateFile: configTemplate, configTemplateFile: configTemplate,
contextTemplateFile: contextTemplate, contextTemplateFile: contextTemplate,
etcTemplateFile: etcTemplate, etcTemplateFile: etcTemplate,
handlerTemplateFile: handlerTemplate, handlerTemplateFile: handlerTemplate,
logicTemplateFile: logicTemplate, logicTemplateFile: logicTemplate,
mainTemplateFile: mainTemplate, mainTemplateFile: mainTemplate,
middlewareImplementCodeFile: middlewareImplementCode,
routesTemplateFile: routesTemplate,
routesAdditionTemplateFile: routesAdditionTemplate,
typesTemplateFile: typesTemplate,
} }
// Category returns the category of the api files. // Category returns the category of the api files.

View File

@@ -6,7 +6,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
) )
func TestGenTemplates(t *testing.T) { func TestGenTemplates(t *testing.T) {

View File

@@ -9,11 +9,11 @@ import (
"strings" "strings"
"text/template" "text/template"
"github.com/tal-tech/go-zero/core/collection" "github.com/zeromicro/go-zero/core/collection"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
"github.com/tal-tech/go-zero/tools/goctl/api/util" "github.com/zeromicro/go-zero/tools/goctl/api/util"
"github.com/tal-tech/go-zero/tools/goctl/util/ctx" "github.com/zeromicro/go-zero/tools/goctl/util/ctx"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
) )
type fileGenConfig struct { type fileGenConfig struct {
@@ -111,6 +111,17 @@ func getAuths(api *spec.ApiSpec) []string {
return authNames.KeysStr() return authNames.KeysStr()
} }
func getJwtTrans(api *spec.ApiSpec) []string {
jwtTransList := collection.NewSet()
for _, g := range api.Service.Groups {
jt := g.GetAnnotation(jwtTransKey)
if len(jt) > 0 {
jwtTransList.Add(jt)
}
}
return jwtTransList.KeysStr()
}
func getMiddleware(api *spec.ApiSpec) []string { func getMiddleware(api *spec.ApiSpec) []string {
result := collection.NewSet() result := collection.NewSet()
for _, g := range api.Service.Groups { for _, g := range api.Service.Groups {

View File

@@ -6,9 +6,9 @@ import (
"strings" "strings"
"github.com/logrusorgru/aurora" "github.com/logrusorgru/aurora"
"github.com/tal-tech/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"github.com/tal-tech/go-zero/tools/goctl/api/parser" "github.com/zeromicro/go-zero/tools/goctl/api/parser"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/urfave/cli" "github.com/urfave/cli"
) )

View File

@@ -10,11 +10,11 @@ import (
"strings" "strings"
"text/template" "text/template"
"github.com/tal-tech/go-zero/core/stringx" "github.com/zeromicro/go-zero/core/stringx"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util" apiutil "github.com/zeromicro/go-zero/tools/goctl/api/util"
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
) )
const ( const (

View File

@@ -6,10 +6,10 @@ import (
"strings" "strings"
"text/template" "text/template"
"github.com/tal-tech/go-zero/core/stringx" "github.com/zeromicro/go-zero/core/stringx"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util" apiutil "github.com/zeromicro/go-zero/tools/goctl/api/util"
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util"
) )
const packetTemplate = `package com.xhb.logic.http.packet.{{.packet}}; const packetTemplate = `package com.xhb.logic.http.packet.{{.packet}};

View File

@@ -6,9 +6,9 @@ import (
"io" "io"
"strings" "strings"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
) )
func writeProperty(writer io.Writer, member spec.Member, indent int) error { func writeProperty(writer io.Writer, member spec.Member, indent int) error {

View File

@@ -3,7 +3,7 @@ package ktgen
import ( import (
"errors" "errors"
"github.com/tal-tech/go-zero/tools/goctl/api/parser" "github.com/zeromicro/go-zero/tools/goctl/api/parser"
"github.com/urfave/cli" "github.com/urfave/cli"
) )

View File

@@ -7,7 +7,7 @@ import (
"text/template" "text/template"
"github.com/iancoleman/strcase" "github.com/iancoleman/strcase"
"github.com/tal-tech/go-zero/tools/goctl/api/util" "github.com/zeromicro/go-zero/tools/goctl/api/util"
) )
var funcsMap = template.FuncMap{ var funcsMap = template.FuncMap{

View File

@@ -7,7 +7,7 @@ import (
"text/template" "text/template"
"github.com/iancoleman/strcase" "github.com/iancoleman/strcase"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
) )
const ( const (

View File

@@ -7,10 +7,10 @@ import (
"strings" "strings"
"text/template" "text/template"
"github.com/tal-tech/go-zero/tools/goctl/api/gogen" "github.com/zeromicro/go-zero/tools/goctl/api/gogen"
conf "github.com/tal-tech/go-zero/tools/goctl/config" conf "github.com/zeromicro/go-zero/tools/goctl/config"
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/urfave/cli" "github.com/urfave/cli"
) )

View File

@@ -3,7 +3,7 @@ package new
import ( import (
"fmt" "fmt"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/urfave/cli" "github.com/urfave/cli"
) )

View File

@@ -5,10 +5,11 @@ import (
"path" "path"
"sort" "sort"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
) )
const prefixKey = "prefix" const prefixKey = "prefix"
const groupKey = "group"
// Api describes syntax for api // Api describes syntax for api
type Api struct { type Api struct {
@@ -52,12 +53,16 @@ func (v *ApiVisitor) acceptService(root, final *Api) {
} }
v.duplicateServerItemCheck(service) v.duplicateServerItemCheck(service)
var prefix string var prefix, group string
if service.AtServer != nil { if service.AtServer != nil {
p := service.AtServer.Kv.Get(prefixKey) p := service.AtServer.Kv.Get(prefixKey)
if p != nil { if p != nil {
prefix = p.Text() prefix = p.Text()
} }
g := service.AtServer.Kv.Get(groupKey)
if g != nil {
group = g.Text()
}
} }
for _, route := range service.ServiceApi.ServiceRoute { for _, route := range service.ServiceApi.ServiceRoute {
uniqueRoute := fmt.Sprintf("%s %s", route.Route.Method.Text(), path.Join(prefix, route.Route.Path.Text())) uniqueRoute := fmt.Sprintf("%s %s", route.Route.Method.Text(), path.Join(prefix, route.Route.Path.Text()))
@@ -92,10 +97,14 @@ func (v *ApiVisitor) acceptService(root, final *Api) {
v.panic(handlerExpr, "mismatched handler") v.panic(handlerExpr, "mismatched handler")
} }
if _, ok := final.handlerM[handlerExpr.Text()]; ok { handlerKey := handlerExpr.Text()
if len(group) > 0 {
handlerKey = fmt.Sprintf("%s/%s", group, handlerExpr.Text())
}
if _, ok := final.handlerM[handlerKey]; ok {
v.panic(handlerExpr, fmt.Sprintf("duplicate handler '%s'", handlerExpr.Text())) v.panic(handlerExpr, fmt.Sprintf("duplicate handler '%s'", handlerExpr.Text()))
} }
final.handlerM[handlerExpr.Text()] = Holder final.handlerM[handlerKey] = Holder
} }
final.Service = append(final.Service, service) final.Service = append(final.Service, service)
} }

View File

@@ -7,8 +7,8 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
"github.com/tal-tech/go-zero/tools/goctl/util/console" "github.com/zeromicro/go-zero/tools/goctl/util/console"
"github.com/zeromicro/antlr" "github.com/zeromicro/antlr"
) )
@@ -240,12 +240,16 @@ func (p *Parser) valid(mainApi, nestedApi *Api) error {
func (p *Parser) duplicateRouteCheck(nestedApi *Api, mainHandlerMap, mainRouteMap map[string]PlaceHolder) error { func (p *Parser) duplicateRouteCheck(nestedApi *Api, mainHandlerMap, mainRouteMap map[string]PlaceHolder) error {
for _, each := range nestedApi.Service { for _, each := range nestedApi.Service {
var prefix string var prefix, group string
if each.AtServer != nil { if each.AtServer != nil {
p := each.AtServer.Kv.Get(prefixKey) p := each.AtServer.Kv.Get(prefixKey)
if p != nil { if p != nil {
prefix = p.Text() prefix = p.Text()
} }
g := each.AtServer.Kv.Get(groupKey)
if p != nil {
group = g.Text()
}
} }
for _, r := range each.ServiceApi.ServiceRoute { for _, r := range each.ServiceApi.ServiceRoute {
handler := r.GetHandler() handler := r.GetHandler()
@@ -253,9 +257,13 @@ func (p *Parser) duplicateRouteCheck(nestedApi *Api, mainHandlerMap, mainRouteMa
return fmt.Errorf("%s handler not exist near line %d", nestedApi.LinePrefix, r.Route.Method.Line()) return fmt.Errorf("%s handler not exist near line %d", nestedApi.LinePrefix, r.Route.Method.Line())
} }
if _, ok := mainHandlerMap[handler.Text()]; ok { handlerKey := handler.Text()
if len(group) > 0 {
handlerKey = fmt.Sprintf("%s/%s", group, handler.Text())
}
if _, ok := mainHandlerMap[handlerKey]; ok {
return fmt.Errorf("%s line %d:%d duplicate handler '%s'", return fmt.Errorf("%s line %d:%d duplicate handler '%s'",
nestedApi.LinePrefix, handler.Line(), handler.Column(), handler.Text()) nestedApi.LinePrefix, handler.Line(), handler.Column(), handlerKey)
} }
p := fmt.Sprintf("%s://%s", r.Route.Method.Text(), path.Join(prefix, r.Route.Path.Text())) p := fmt.Sprintf("%s://%s", r.Route.Method.Text(), path.Join(prefix, r.Route.Path.Text()))

View File

@@ -5,8 +5,8 @@ import (
"sort" "sort"
"strings" "strings"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
"github.com/tal-tech/go-zero/tools/goctl/util/console" "github.com/zeromicro/go-zero/tools/goctl/util/console"
"github.com/zeromicro/antlr" "github.com/zeromicro/antlr"
) )

View File

@@ -1,7 +1,7 @@
package ast package ast
import ( import (
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
) )
// ImportExpr defines import syntax for api // ImportExpr defines import syntax for api

View File

@@ -1,7 +1,7 @@
package ast package ast
import ( import (
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
) )
// InfoExpr defines info syntax for api // InfoExpr defines info syntax for api

View File

@@ -3,7 +3,7 @@ package ast
import ( import (
"strings" "strings"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
) )
// KvExpr describes key-value for api // KvExpr describes key-value for api

View File

@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"sort" "sort"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
) )
// Service describes service for api syntax // Service describes service for api syntax

View File

@@ -1,7 +1,7 @@
package ast package ast
import ( import (
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
) )
// SyntaxExpr describes syntax for api // SyntaxExpr describes syntax for api

View File

@@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"sort" "sort"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
) )
type ( type (

2
tools/goctl/api/parser/g4/gen/api/apiparser_parser.go Normal file → Executable file
View File

@@ -634,3 +634,5 @@ func NewSyntaxLitContext(parser antlr.Parser, parent antlr.ParserRuleContext, in
return p return p
} }

View File

@@ -8,8 +8,8 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/ast" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/ast"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
) )
var ( var (

View File

@@ -5,8 +5,8 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/ast" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/ast"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
) )
var parser = ast.NewParser(ast.WithParserPrefix("test.api"), ast.WithParserDebug()) var parser = ast.NewParser(ast.WithParserPrefix("test.api"), ast.WithParserDebug())

View File

@@ -5,8 +5,8 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/ast" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/ast"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
) )
var importAccept = func(p *api.ApiParserParser, visitor *ast.ApiVisitor) interface{} { var importAccept = func(p *api.ApiParserParser, visitor *ast.ApiVisitor) interface{} {

View File

@@ -4,8 +4,8 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/ast" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/ast"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
) )
var infoAccept = func(p *api.ApiParserParser, visitor *ast.ApiVisitor) interface{} { var infoAccept = func(p *api.ApiParserParser, visitor *ast.ApiVisitor) interface{} {

View File

@@ -4,8 +4,8 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/ast" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/ast"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
) )
func TestBody(t *testing.T) { func TestBody(t *testing.T) {

View File

@@ -4,8 +4,8 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/ast" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/ast"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
) )
var syntaxAccept = func(p *api.ApiParserParser, visitor *ast.ApiVisitor) interface{} { var syntaxAccept = func(p *api.ApiParserParser, visitor *ast.ApiVisitor) interface{} {

View File

@@ -4,8 +4,8 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/ast" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/ast"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
) )
var fieldAccept = func(p *api.ApiParserParser, visitor *ast.ApiVisitor) interface{} { var fieldAccept = func(p *api.ApiParserParser, visitor *ast.ApiVisitor) interface{} {

View File

@@ -5,9 +5,9 @@ import (
"path/filepath" "path/filepath"
"unicode" "unicode"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/ast" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/ast"
"github.com/tal-tech/go-zero/tools/goctl/api/parser/g4/gen/api" "github.com/zeromicro/go-zero/tools/goctl/api/parser/g4/gen/api"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
) )
type parser struct { type parser struct {

View File

@@ -4,7 +4,7 @@ import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
) )
var testApi = "// syntax doc\nsyntax = \"v1\" // syntax comment\n\n// type doc\ntype Request {\n\tName string `path:\"name,options=you|me\"`\n}\n\ntype Response {\n\tMessage string `json:\"message\"`\n}\n\n// service doc\nservice greet-api {\n\t// handler doc\n\t@handler GreetHandler // handler comment\n\tget /from/:name(Request) returns (Response);\n}" var testApi = "// syntax doc\nsyntax = \"v1\" // syntax comment\n\n// type doc\ntype Request {\n\tName string `path:\"name,options=you|me\"`\n}\n\ntype Response {\n\tMessage string `json:\"message\"`\n}\n\n// service doc\nservice greet-api {\n\t// handler doc\n\t@handler GreetHandler // handler comment\n\tget /from/:name(Request) returns (Response);\n}"

View File

@@ -5,8 +5,8 @@ import (
"path" "path"
"strings" "strings"
"github.com/tal-tech/go-zero/core/stringx" "github.com/zeromicro/go-zero/core/stringx"
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util"
) )
const ( const (

View File

@@ -5,9 +5,9 @@ import (
"fmt" "fmt"
"github.com/logrusorgru/aurora" "github.com/logrusorgru/aurora"
"github.com/tal-tech/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"github.com/tal-tech/go-zero/tools/goctl/api/parser" "github.com/zeromicro/go-zero/tools/goctl/api/parser"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/urfave/cli" "github.com/urfave/cli"
) )

View File

@@ -5,9 +5,9 @@ import (
"strings" "strings"
"text/template" "text/template"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util" apiutil "github.com/zeromicro/go-zero/tools/goctl/api/util"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
) )
const ( const (

View File

@@ -6,10 +6,10 @@ import (
"strings" "strings"
"text/template" "text/template"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util" apiutil "github.com/zeromicro/go-zero/tools/goctl/api/util"
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
) )
const ( const (

View File

@@ -6,9 +6,9 @@ import (
"io" "io"
"strings" "strings"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
apiutil "github.com/tal-tech/go-zero/tools/goctl/api/util" apiutil "github.com/zeromicro/go-zero/tools/goctl/api/util"
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util"
) )
func writeProperty(writer io.Writer, member spec.Member, indent int) error { func writeProperty(writer io.Writer, member spec.Member, indent int) error {

View File

@@ -8,9 +8,9 @@ import (
"path" "path"
"strings" "strings"
"github.com/tal-tech/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"github.com/tal-tech/go-zero/tools/goctl/api/spec" "github.com/zeromicro/go-zero/tools/goctl/api/spec"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
) )
// MaybeCreateFile creates file if not exists // MaybeCreateFile creates file if not exists

View File

@@ -5,7 +5,7 @@ import (
"fmt" "fmt"
"github.com/logrusorgru/aurora" "github.com/logrusorgru/aurora"
"github.com/tal-tech/go-zero/tools/goctl/api/parser" "github.com/zeromicro/go-zero/tools/goctl/api/parser"
"github.com/urfave/cli" "github.com/urfave/cli"
) )

View File

@@ -6,7 +6,7 @@ import (
"os/exec" "os/exec"
"runtime" "runtime"
"github.com/tal-tech/go-zero/tools/goctl/internal/version" "github.com/zeromicro/go-zero/tools/goctl/internal/version"
"github.com/urfave/cli" "github.com/urfave/cli"
) )

View File

@@ -6,7 +6,7 @@ import (
"runtime" "runtime"
"strings" "strings"
"github.com/tal-tech/go-zero/tools/goctl/internal/version" "github.com/zeromicro/go-zero/tools/goctl/internal/version"
) )
type env map[string]string type env map[string]string

View File

@@ -10,8 +10,8 @@ import (
"time" "time"
"github.com/logrusorgru/aurora" "github.com/logrusorgru/aurora"
"github.com/tal-tech/go-zero/tools/goctl/util" "github.com/zeromicro/go-zero/tools/goctl/util"
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/urfave/cli" "github.com/urfave/cli"
) )

View File

@@ -1,7 +1,7 @@
package docker package docker
import ( import (
"github.com/tal-tech/go-zero/tools/goctl/util/pathx" "github.com/zeromicro/go-zero/tools/goctl/util/pathx"
"github.com/urfave/cli" "github.com/urfave/cli"
) )

View File

@@ -1,6 +1,6 @@
module github.com/tal-tech/go-zero/tools/goctl module github.com/zeromicro/go-zero/tools/goctl
go 1.17 go 1.15
require ( require (
github.com/DATA-DOG/go-sqlmock v1.5.0 github.com/DATA-DOG/go-sqlmock v1.5.0
@@ -10,28 +10,8 @@ require (
github.com/iancoleman/strcase v0.2.0 github.com/iancoleman/strcase v0.2.0
github.com/logrusorgru/aurora v2.0.3+incompatible github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
github.com/tal-tech/go-zero v1.2.5
github.com/urfave/cli v1.22.5 github.com/urfave/cli v1.22.5
github.com/zeromicro/antlr v0.0.1 github.com/zeromicro/antlr v0.0.1
github.com/zeromicro/ddl-parser v0.0.0-20210712021150-63520aca7348 github.com/zeromicro/ddl-parser v0.0.0-20210712021150-63520aca7348
) github.com/zeromicro/go-zero v1.3.0-beta
require (
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a // indirect
github.com/alicebob/miniredis/v2 v2.16.0 // indirect
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210521184019-c5ad59b459ec // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-redis/redis v6.15.9+incompatible // indirect
github.com/lib/pq v1.10.3 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.0.1 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da // indirect
go.opentelemetry.io/otel v1.1.0 // indirect
go.opentelemetry.io/otel/trace v1.1.0 // indirect
go.uber.org/automaxprocs v1.4.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
) )

Some files were not shown because too many files have changed in this diff Show More