32 changed files with 1691 additions and 38 deletions
@ -0,0 +1,37 @@
|
||||
|
||||
[app] |
||||
|
||||
[grpc] |
||||
address = ":7010" |
||||
maxSendMsgSize = "8Mi" |
||||
maxRecvMsgSize = "8Mi" |
||||
readBufferSize = "8Ki" |
||||
writeBufferSize = "8Ki" |
||||
|
||||
[grpc.register.attrs] |
||||
weight = 100 |
||||
|
||||
[etcd] |
||||
endpoints = ["124.222.131.236:3279"] |
||||
username = "root" |
||||
password = "sopod@etcd" |
||||
|
||||
[redis] |
||||
Addr = "124.222.131.236:3379" |
||||
Password = "sopod@redis#" |
||||
DB = 1 |
||||
MinIdleConns = 3 |
||||
|
||||
[nats] |
||||
Url = "nats://nats.sopod@124.222.131.236:3222" |
||||
|
||||
[gorm] |
||||
logMode=true |
||||
|
||||
[gorm.mysql] |
||||
# https://gorm.io/zh_CN/docs/connecting_to_the_database.html |
||||
DSN = "root:sopod_mysql2347-@tcp(124.222.131.236:3666)/groups?charset=utf8&parseTime=True&loc=Local" |
||||
|
||||
[prometheus] |
||||
enable = false |
||||
port = 7019 |
||||
@ -1,6 +1,36 @@
|
||||
package main |
||||
|
||||
import ( |
||||
clientv3 "go.etcd.io/etcd/client/v3" |
||||
"google.golang.org/grpc/grpclog" |
||||
"sonet/internal/postal/logic" |
||||
"sonet/pkg/config" |
||||
"sonet/pkg/grpc/discovery" |
||||
"sonet/pkg/utils/logger" |
||||
"sonet/pkg/utils/shutdown" |
||||
) |
||||
|
||||
// websocket server with postalService
|
||||
func main() { |
||||
grpclog.SetLoggerV2(logger.Logger) |
||||
|
||||
conf := config.LoadConfig(nil, "cmd/gateway_ws") |
||||
postalServer := logic.NewPostalServer() |
||||
|
||||
// registry and run...
|
||||
etcdClient, err := clientv3.New(conf.Etcd) |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
postalRegistry := discovery.NewRegister(etcdClient) |
||||
shutdown.AddShutdownHook(postalRegistry.Stop) |
||||
|
||||
go func() { |
||||
err = postalServer.Run(conf.Grpc, postalRegistry) |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
}() |
||||
|
||||
shutdown.Await() |
||||
} |
||||
|
||||
@ -1,3 +1,7 @@
|
||||
package sonet |
||||
|
||||
//go:generate protoc --go_out=./api/gen --go-grpc_out=./api/gen ./api/*.proto
|
||||
//go:generate pbjs -t static-module -w es6 -o api/genjs/postal.js api/postal.proto --no-service
|
||||
//go:generate pbjs -t static-module -w es6 -o api/genjs/auth.js api/auth.proto --no-service
|
||||
//go:generate pbjs -t static-module -w es6 -o api/genjs/chat.js api/chat.proto --no-service
|
||||
//go:generate pbjs -t static-module -w es6 -o api/genjs/mahjong.js api/mahjong.proto --no-service
|
||||
|
||||
@ -1,20 +1,192 @@
|
||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= |
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= |
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= |
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= |
||||
github.com/bufbuild/protocompile v0.7.1 h1:Kd8fb6EshOHXNNRtYAmLAwy/PotlyFoN0iMbuwGNh0M= |
||||
github.com/bufbuild/protocompile v0.7.1/go.mod h1:+Etjg4guZoAqzVk2czwEQP12yaxLJ8DxuqCJ9qHdH94= |
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= |
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= |
||||
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= |
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= |
||||
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= |
||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= |
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= |
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= |
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= |
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= |
||||
github.com/dsnet/golib/unitconv v1.0.2 h1:45gXng3Op1vTrnX1PdM9Bla4mEpBFYA5aC8dlqacmwM= |
||||
github.com/dsnet/golib/unitconv v1.0.2/go.mod h1:86KTUtTJFLreKjc4sS9xE0rhj4lR44Ox0rEQSEXSWwM= |
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= |
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= |
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= |
||||
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= |
||||
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= |
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= |
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= |
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= |
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= |
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= |
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= |
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= |
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= |
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= |
||||
golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos= |
||||
golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= |
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= |
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= |
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= |
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= |
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= |
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= |
||||
github.com/jhump/protoreflect v1.15.4 h1:mrwJhfQGGljwvR/jPEocli8KA6G9afbQpH8NY2wORcI= |
||||
github.com/jhump/protoreflect v1.15.4/go.mod h1:2B+zwrnMY3TTIqEK01OG/d3pyUycQBfDf+bx8fE2DNg= |
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= |
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= |
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= |
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= |
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= |
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= |
||||
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= |
||||
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= |
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= |
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= |
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= |
||||
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/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= |
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= |
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= |
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= |
||||
github.com/nats-io/nats.go v1.31.0 h1:/WFBHEc/dOKBF6qf1TZhrdEfTmOZ5JzdJ+Y3m6Y/p7E= |
||||
github.com/nats-io/nats.go v1.31.0/go.mod h1:di3Bm5MLsoB4Bx61CBTsxuarI36WbhAwOm8QrW39+i8= |
||||
github.com/nats-io/nkeys v0.4.6 h1:IzVe95ru2CT6ta874rt9saQRkWfe2nFj1NtvYSLqMzY= |
||||
github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADymtkpts= |
||||
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= |
||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= |
||||
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= |
||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= |
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= |
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= |
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= |
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= |
||||
github.com/redis/go-redis/v9 v9.4.0 h1:Yzoz33UZw9I/mFhx4MNrB6Fk+XHO1VukNcCa1+lwyKk= |
||||
github.com/redis/go-redis/v9 v9.4.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= |
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= |
||||
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= |
||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= |
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= |
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= |
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= |
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= |
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= |
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= |
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= |
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= |
||||
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= |
||||
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= |
||||
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/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ= |
||||
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk= |
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= |
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= |
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= |
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= |
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= |
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= |
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= |
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= |
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= |
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= |
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= |
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= |
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= |
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= |
||||
go.etcd.io/etcd/api/v3 v3.5.11 h1:B54KwXbWDHyD3XYAwprxNzTe7vlhR69LuBgZnMVvS7E= |
||||
go.etcd.io/etcd/api/v3 v3.5.11/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4= |
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.11 h1:bT2xVspdiCj2910T0V+/KHcVKjkUrCZVtk8J2JF2z1A= |
||||
go.etcd.io/etcd/client/pkg/v3 v3.5.11/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4= |
||||
go.etcd.io/etcd/client/v3 v3.5.11 h1:ajWtgoNSZJ1gmS8k+icvPtqsqEav+iUorF7b0qozgUU= |
||||
go.etcd.io/etcd/client/v3 v3.5.11/go.mod h1:a6xQUEqFJ8vztO1agJh/KQKOMfFI8og52ZconzcDJwE= |
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= |
||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= |
||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= |
||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= |
||||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= |
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= |
||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= |
||||
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= |
||||
go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8= |
||||
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= |
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= |
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= |
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= |
||||
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY= |
||||
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= |
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= |
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= |
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= |
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= |
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= |
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= |
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= |
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= |
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= |
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= |
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= |
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= |
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= |
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= |
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= |
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= |
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= |
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= |
||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= |
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= |
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= |
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= |
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= |
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= |
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= |
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= |
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= |
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= |
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= |
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= |
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= |
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= |
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= |
||||
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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97 h1:6GQBEOdGkX6MMTLT9V+TjtIRZCw9VPD5Z+yHY9wMgS0= |
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231002182017-d307bd883b97/go.mod h1:v7nGkzlmW8P3n/bKmWBn2WpBjpOEx8Q6gMueudAmKfY= |
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= |
||||
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ= |
||||
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY= |
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo= |
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4= |
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= |
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= |
||||
google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= |
||||
google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= |
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= |
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= |
||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= |
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= |
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= |
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= |
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= |
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= |
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= |
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= |
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= |
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
||||
gorm.io/driver/mysql v1.5.2 h1:QC2HRskSE75wBuOxe0+iCkyJZ+RqpudsQtqkp+IMuXs= |
||||
gorm.io/driver/mysql v1.5.2/go.mod h1:pQLhh1Ut/WUAySdTHwBpBv6+JKcj+ua4ZFx1QQTBzb8= |
||||
gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= |
||||
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls= |
||||
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8= |
||||
|
||||
@ -0,0 +1,23 @@
|
||||
package logic |
||||
|
||||
import ( |
||||
"context" |
||||
"sonet/api/gen/auth" |
||||
) |
||||
|
||||
type AuthServer struct { |
||||
auth.UnimplementedAuthServer |
||||
} |
||||
|
||||
func (s *AuthServer) Login(ctx context.Context, req *auth.ReqLogin) (*auth.ResLogin, error) { |
||||
return nil, nil |
||||
} |
||||
func (s *AuthServer) Verify(ctx context.Context, req *auth.ReqVerify) (*auth.Subject, error) { |
||||
return nil, nil |
||||
} |
||||
func (s *AuthServer) Registry(ctx context.Context, req *auth.ReqRegistry) (*auth.Subject, error) { |
||||
return nil, nil |
||||
} |
||||
func (s *AuthServer) FindByUid(ctx context.Context, req *auth.ReqFindByUid) (*auth.Subject, error) { |
||||
return nil, nil |
||||
} |
||||
@ -0,0 +1,43 @@
|
||||
package logic |
||||
|
||||
import ( |
||||
"context" |
||||
"google.golang.org/protobuf/types/known/emptypb" |
||||
"sonet/api/gen/chat" |
||||
) |
||||
|
||||
type ChatServer struct { |
||||
chat.UnimplementedChatServer |
||||
} |
||||
|
||||
func (s *ChatServer) Send(ctx context.Context, send *chat.ReqSend) (*chat.ResSend, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *ChatServer) RoomSend(ctx context.Context, send *chat.ReqRoomSend) (*chat.ResSend, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *ChatServer) RoomCreate(ctx context.Context, create *chat.ReqRoomCreate) (*chat.ResRoomCreate, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *ChatServer) RoomJoin(ctx context.Context, join *chat.ReqRoomJoin) (*emptypb.Empty, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *ChatServer) RoomLeave(ctx context.Context, leave *chat.ReqRoomLeave) (*emptypb.Empty, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *ChatServer) RoomKickOut(ctx context.Context, out *chat.ReqRoomKickOut) (*emptypb.Empty, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *ChatServer) RoomInfo(ctx context.Context, info *chat.ReqRoomInfo) (*chat.ResRoomInfo, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *ChatServer) RoomList(ctx context.Context, list *chat.ReqRoomList) (*chat.ResRoomList, error) { |
||||
return nil, nil |
||||
} |
||||
@ -0,0 +1,59 @@
|
||||
package logic |
||||
|
||||
import ( |
||||
"context" |
||||
"google.golang.org/protobuf/types/known/emptypb" |
||||
"sonet/api/gen/mahjong" |
||||
) |
||||
|
||||
type MahjongServer struct { |
||||
mahjong.UnimplementedMahjongServer |
||||
} |
||||
|
||||
func (s *MahjongServer) PlayerOnline(ctx context.Context, empty *emptypb.Empty) (*mahjong.ResPlayerOnline, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *MahjongServer) PlayerOffline(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *MahjongServer) LobbyView(ctx context.Context, empty *emptypb.Empty) (*mahjong.Lobby, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *MahjongServer) CreateTable(ctx context.Context, empty *emptypb.Empty) (*mahjong.MjTable, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *MahjongServer) JoinTable(ctx context.Context, table *mahjong.ReqJoinTable) (*mahjong.MjTable, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *MahjongServer) LeaveTable(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *MahjongServer) KickoutTable(ctx context.Context, table *mahjong.ReqKickoutTable) (*emptypb.Empty, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *MahjongServer) ReadyStart(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *MahjongServer) CancelReady(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *MahjongServer) DismissTable(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *MahjongServer) GameStart(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empty, error) { |
||||
return nil, nil |
||||
} |
||||
|
||||
func (s *MahjongServer) PlayerAction(ctx context.Context, action *mahjong.ReqPlayerAction) (*emptypb.Empty, error) { |
||||
return nil, nil |
||||
} |
||||
@ -0,0 +1,4 @@
|
||||
package ws |
||||
|
||||
type WebsocketServer struct { |
||||
} |
||||
@ -0,0 +1,55 @@
|
||||
package config |
||||
|
||||
import ( |
||||
nats "github.com/nats-io/nats.go" |
||||
redis "github.com/redis/go-redis/v9" |
||||
clientv3 "go.etcd.io/etcd/client/v3" |
||||
"gorm.io/driver/mysql" |
||||
"gorm.io/gorm" |
||||
"sonet/pkg/grpc/discovery" |
||||
) |
||||
|
||||
// Configuration 服务配置
|
||||
type Configuration struct { |
||||
App map[string]any |
||||
Grpc GrpcConfig |
||||
GrpcClient GrpcClientConfig |
||||
Gorm GormConfig |
||||
Snowflake SnowflakeConfig |
||||
Etcd clientv3.Config |
||||
Redis redis.Options |
||||
Nats nats.Options |
||||
Prometheus PrometheusConfig |
||||
} |
||||
|
||||
type GrpcConfig struct { |
||||
Address string |
||||
NoReflection bool |
||||
MaxSendMsgSize string |
||||
MaxRecvMsgSize string |
||||
ReadBufferSize string |
||||
WriteBufferSize string |
||||
Register discovery.Server |
||||
} |
||||
|
||||
type GrpcKeepaliveConfig struct { |
||||
// todo...
|
||||
} |
||||
|
||||
type GrpcClientConfig struct { |
||||
} |
||||
|
||||
type GormConfig struct { |
||||
LogMode bool // default false
|
||||
gorm.Config |
||||
Mysql mysql.Config |
||||
} |
||||
|
||||
type SnowflakeConfig struct { |
||||
NodeId int64 // 0-1023, 相同服务每个部署实例不重复
|
||||
} |
||||
|
||||
type PrometheusConfig struct { |
||||
Enable bool |
||||
Port int |
||||
} |
||||
@ -0,0 +1,18 @@
|
||||
package config |
||||
|
||||
import ( |
||||
"gorm.io/driver/mysql" |
||||
"gorm.io/gorm" |
||||
"gorm.io/gorm/logger" |
||||
) |
||||
|
||||
func NewGorm(conf GormConfig) *gorm.DB { |
||||
if conf.LogMode { |
||||
conf.Logger = logger.Default.LogMode(logger.Info) |
||||
} |
||||
db, err := gorm.Open(mysql.New(conf.Mysql), &conf) |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
return db |
||||
} |
||||
@ -0,0 +1,23 @@
|
||||
package config |
||||
|
||||
import ( |
||||
"google.golang.org/grpc" |
||||
"sonet/pkg/utils/conver" |
||||
) |
||||
|
||||
func GetGrpcOptions(config GrpcConfig) (opts []grpc.ServerOption) { |
||||
if config.MaxSendMsgSize != "" { |
||||
opts = append(opts, grpc.MaxSendMsgSize(conver.MustParseDataUnitInt(config.MaxSendMsgSize))) |
||||
} |
||||
if config.MaxRecvMsgSize != "" { |
||||
opts = append(opts, grpc.MaxSendMsgSize(conver.MustParseDataUnitInt(config.MaxRecvMsgSize))) |
||||
} |
||||
if config.ReadBufferSize != "" { |
||||
opts = append(opts, grpc.MaxSendMsgSize(conver.MustParseDataUnitInt(config.ReadBufferSize))) |
||||
} |
||||
if config.WriteBufferSize != "" { |
||||
opts = append(opts, grpc.MaxSendMsgSize(conver.MustParseDataUnitInt(config.WriteBufferSize))) |
||||
} |
||||
|
||||
return |
||||
} |
||||
@ -0,0 +1,80 @@
|
||||
package config |
||||
|
||||
import ( |
||||
"errors" |
||||
"flag" |
||||
"github.com/spf13/viper" |
||||
"os" |
||||
"sonet/pkg/utils/logger" |
||||
"strings" |
||||
) |
||||
|
||||
func parseConfPathFlag(confPath string) (filePath, fileName, confName, confType string) { |
||||
idx := strings.LastIndex(confPath, "/") |
||||
filePath = confPath[:idx+1] |
||||
fileName = confPath[idx+1:] |
||||
idx2 := strings.LastIndex(fileName, ".") |
||||
confName = fileName[:idx2] |
||||
confType = fileName[idx2+1:] |
||||
return |
||||
} |
||||
|
||||
// LoadConfig load config.toml
|
||||
// appConf service custom config
|
||||
// return common service configuration
|
||||
func LoadConfig(appConf any, confPathArg ...string) *Configuration { |
||||
confPath := "" |
||||
confName := "config" |
||||
confType := "toml" |
||||
envPrefix := "SO" |
||||
|
||||
if len(confPathArg) > 0 { |
||||
confPath = confPathArg[0] |
||||
} |
||||
|
||||
// go run xx -conf=config/xx.toml
|
||||
confPathFlag := flag.String("conf", "", "config file path.") |
||||
envPrefixFlag := flag.String("envPrefix", "", "env config key prefix.") |
||||
flag.Parse() |
||||
if *confPathFlag != "" { |
||||
confPath, _, confName, confType = parseConfPathFlag(*confPathFlag) |
||||
} |
||||
if *envPrefixFlag != "" { |
||||
envPrefix = *envPrefixFlag |
||||
} |
||||
if confPath == "" { |
||||
confPath = "./" |
||||
} |
||||
logger.Infof("use config file: %s%s.%s, env prefix=%s\n", confPath, confName, confType, envPrefix) |
||||
|
||||
viper.AddConfigPath(confPath) |
||||
viper.SetConfigName(confName) |
||||
viper.SetConfigType(confType) |
||||
viper.SetEnvPrefix(envPrefix) |
||||
viper.AutomaticEnv() |
||||
viper.AllowEmptyEnv(true) |
||||
|
||||
conf := &Configuration{} |
||||
|
||||
if err := viper.ReadInConfig(); err != nil { |
||||
panic(errors.New("viper read config fail: " + err.Error())) |
||||
} |
||||
if err := viper.Unmarshal(conf); err != nil { |
||||
panic(errors.New("viper unmarshal config failed: " + err.Error())) |
||||
} |
||||
if appConf != nil && len(conf.App) > 0 { |
||||
if err := viper.UnmarshalKey("app", appConf); err != nil { |
||||
panic(errors.New("viper unmarshal app config failed: " + err.Error())) |
||||
} |
||||
} |
||||
|
||||
return conf |
||||
} |
||||
|
||||
func LoadIdlPath(idlPath string) (string, error) { |
||||
idl, err := os.ReadFile(idlPath) |
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
return string(idl), nil |
||||
} |
||||
@ -0,0 +1,72 @@
|
||||
package discovery |
||||
|
||||
import ( |
||||
"encoding/json" |
||||
"errors" |
||||
"fmt" |
||||
"strings" |
||||
|
||||
"google.golang.org/grpc/resolver" |
||||
) |
||||
|
||||
type Server struct { |
||||
Name string `json:"name"` |
||||
Addr string `json:"addr"` // 地址
|
||||
Attrs map[string]string `json:"attrs"` // attributes
|
||||
Ttl int64 `json:"-"` |
||||
} |
||||
|
||||
func BuildPrefix(server Server) string { |
||||
return fmt.Sprintf("/%s/", server.Name) |
||||
} |
||||
|
||||
func BuildRegisterPath(server Server) string { |
||||
return fmt.Sprintf("%s%s", BuildPrefix(server), server.Addr) |
||||
} |
||||
|
||||
func ParseValue(value []byte) (Server, error) { |
||||
server := Server{} |
||||
if err := json.Unmarshal(value, &server); err != nil { |
||||
return server, err |
||||
} |
||||
|
||||
return server, nil |
||||
} |
||||
|
||||
func SplitPath(path string) (Server, error) { |
||||
server := Server{} |
||||
strs := strings.Split(path, "/") |
||||
if len(strs) == 0 { |
||||
return server, errors.New("invalid path") |
||||
} |
||||
|
||||
server.Addr = strs[len(strs)-1] |
||||
|
||||
return server, nil |
||||
} |
||||
|
||||
// Exist helper function
|
||||
func Exist(l []resolver.Address, addr resolver.Address) bool { |
||||
for i := range l { |
||||
if l[i].Addr == addr.Addr { |
||||
return true |
||||
} |
||||
} |
||||
|
||||
return false |
||||
} |
||||
|
||||
// Remove helper function
|
||||
func Remove(s []resolver.Address, addr resolver.Address) ([]resolver.Address, bool) { |
||||
for i := range s { |
||||
if s[i].Addr == addr.Addr { |
||||
s[i] = s[len(s)-1] |
||||
return s[:len(s)-1], true |
||||
} |
||||
} |
||||
return nil, false |
||||
} |
||||
|
||||
func BuildResolverUrl(app string) string { |
||||
return schema + ":///" + app |
||||
} |
||||
@ -0,0 +1,166 @@
|
||||
package discovery |
||||
|
||||
import ( |
||||
"context" |
||||
"encoding/json" |
||||
"errors" |
||||
"fmt" |
||||
"google.golang.org/grpc/grpclog" |
||||
"net" |
||||
"sonet/pkg/utils/nets" |
||||
"strings" |
||||
"time" |
||||
|
||||
clientv3 "go.etcd.io/etcd/client/v3" |
||||
) |
||||
|
||||
var DefaultRegisterTTL int64 = 10 |
||||
|
||||
func RegisterAddress(listener net.Listener) (addr string, err error) { |
||||
port := listener.Addr().(*net.TCPAddr).Port |
||||
ipv4, err := nets.GetHostIpv4() |
||||
if err != nil { |
||||
return |
||||
} |
||||
addr = fmt.Sprintf("%s:%d", ipv4, port) |
||||
return |
||||
} |
||||
func MustGetRegisterAddr(listener net.Listener) (addr string) { |
||||
port := listener.Addr().(*net.TCPAddr).Port |
||||
ipv4, err := nets.GetHostIpv4() |
||||
if err != nil { |
||||
panic(err) |
||||
} |
||||
addr = fmt.Sprintf("%s:%s", ipv4, port) |
||||
return |
||||
} |
||||
|
||||
type Register struct { |
||||
DialTimeout int |
||||
|
||||
closeCh chan struct{} |
||||
leasesID clientv3.LeaseID |
||||
keepAliveCh <-chan *clientv3.LeaseKeepAliveResponse |
||||
|
||||
srvInfo Server |
||||
srvTTL int64 |
||||
cli *clientv3.Client |
||||
} |
||||
|
||||
// NewRegister create a register based on etcd
|
||||
func NewRegister(client *clientv3.Client) *Register { |
||||
return &Register{ |
||||
cli: client, |
||||
DialTimeout: 3, |
||||
} |
||||
} |
||||
|
||||
// Register a user
|
||||
func (r *Register) Register(srvInfo Server, ttl int64) (err error) { |
||||
if strings.Split(srvInfo.Addr, ":")[0] == "" { |
||||
return errors.New("invalid ip address") |
||||
} |
||||
|
||||
r.srvInfo = srvInfo |
||||
r.srvTTL = ttl |
||||
|
||||
if err = r.register(); err != nil { |
||||
return err |
||||
} |
||||
|
||||
if r.closeCh == nil { |
||||
r.closeCh = make(chan struct{}) |
||||
} |
||||
|
||||
go r.keepAlive() |
||||
|
||||
return nil |
||||
} |
||||
|
||||
func (r *Register) register() error { |
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(r.DialTimeout)*time.Second) |
||||
defer cancel() |
||||
|
||||
leaseResp, err := r.cli.Grant(ctx, r.srvTTL) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
r.leasesID = leaseResp.ID |
||||
|
||||
if r.keepAliveCh, err = r.cli.KeepAlive(context.Background(), r.leasesID); err != nil { |
||||
return err |
||||
} |
||||
|
||||
data, err := json.Marshal(r.srvInfo) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
|
||||
_, err = r.cli.Put(context.Background(), BuildRegisterPath(r.srvInfo), string(data), clientv3.WithLease(r.leasesID)) |
||||
|
||||
return err |
||||
} |
||||
|
||||
// Stop stop register
|
||||
func (r *Register) Stop() { |
||||
if r.closeCh == nil { |
||||
return |
||||
} |
||||
r.closeCh <- struct{}{} |
||||
<-r.closeCh // 阻塞到关闭
|
||||
close(r.closeCh) |
||||
} |
||||
|
||||
// unregister 删除节点
|
||||
func (r *Register) unregister() error { |
||||
_, err := r.cli.Delete(context.Background(), BuildRegisterPath(r.srvInfo)) |
||||
return err |
||||
} |
||||
|
||||
func (r *Register) keepAlive() { |
||||
ticker := time.NewTicker(time.Duration(r.srvTTL) * time.Second) |
||||
defer ticker.Stop() |
||||
|
||||
for { |
||||
select { |
||||
case <-r.closeCh: |
||||
if err := r.unregister(); err != nil { |
||||
grpclog.Error("unregister failed, error: ", err) |
||||
} |
||||
if _, err := r.cli.Revoke(context.Background(), r.leasesID); err != nil { |
||||
grpclog.Error("revoke failed, error: ", err) |
||||
} |
||||
r.closeCh <- struct{}{} |
||||
return |
||||
case res := <-r.keepAliveCh: |
||||
if res == nil { |
||||
if err := r.register(); err != nil { |
||||
grpclog.Error("register failed, error: ", err) |
||||
} |
||||
} |
||||
case <-ticker.C: |
||||
if r.keepAliveCh == nil { |
||||
if err := r.register(); err != nil { |
||||
grpclog.Error("register failed, error: ", err) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
func (r *Register) GetServerInfo() (Server, error) { |
||||
resp, err := r.cli.Get(context.Background(), BuildRegisterPath(r.srvInfo)) |
||||
if err != nil { |
||||
return r.srvInfo, err |
||||
} |
||||
|
||||
server := Server{} |
||||
if resp.Count >= 1 { |
||||
if err := json.Unmarshal(resp.Kvs[0].Value, &server); err != nil { |
||||
return server, err |
||||
} |
||||
} |
||||
|
||||
return server, err |
||||
} |
||||
@ -0,0 +1,168 @@
|
||||
package discovery |
||||
|
||||
import ( |
||||
"context" |
||||
"time" |
||||
|
||||
"github.com/sirupsen/logrus" |
||||
clientv3 "go.etcd.io/etcd/client/v3" |
||||
"google.golang.org/grpc/resolver" |
||||
) |
||||
|
||||
const ( |
||||
schema = "etcd" |
||||
) |
||||
|
||||
// Resolver for grpc client
|
||||
type Resolver struct { |
||||
schema string |
||||
EtcdAddrs []string |
||||
DialTimeout int |
||||
|
||||
closeCh chan struct{} |
||||
watchCh clientv3.WatchChan |
||||
cli *clientv3.Client |
||||
keyPrifix string |
||||
srvAddrsList []resolver.Address |
||||
|
||||
cc resolver.ClientConn |
||||
logger *logrus.Logger |
||||
} |
||||
|
||||
// NewResolver create a new resolver.Builder base on etcd
|
||||
func NewResolver(etcdAddrs []string, logger *logrus.Logger) *Resolver { |
||||
return &Resolver{ |
||||
schema: schema, |
||||
EtcdAddrs: etcdAddrs, |
||||
DialTimeout: 3, |
||||
logger: logger, |
||||
} |
||||
} |
||||
|
||||
// Scheme returns the scheme supported by this resolver.
|
||||
func (r *Resolver) Scheme() string { |
||||
return r.schema |
||||
} |
||||
|
||||
// Build creates a new resolver.Resolver for the given target
|
||||
func (r *Resolver) Build(target resolver.Target, cc resolver.ClientConn, opts resolver.BuildOptions) (rr resolver.Resolver, err error) { |
||||
r.cc = cc |
||||
r.keyPrifix = BuildPrefix(Server{Name: target.Endpoint()}) |
||||
if _, err := r.start(); err != nil { |
||||
return nil, err |
||||
} |
||||
return r, nil |
||||
} |
||||
|
||||
// ResolveNow resolver.Resolver interface
|
||||
func (r *Resolver) ResolveNow(o resolver.ResolveNowOptions) {} |
||||
|
||||
// Close resolver.Resolver interface
|
||||
func (r *Resolver) Close() { |
||||
r.closeCh <- struct{}{} |
||||
} |
||||
|
||||
// start
|
||||
func (r *Resolver) start() (chan<- struct{}, error) { |
||||
var err error |
||||
r.cli, err = clientv3.New(clientv3.Config{ |
||||
Endpoints: r.EtcdAddrs, |
||||
Username: "root", |
||||
Password: "sopod@etcd", |
||||
DialTimeout: time.Duration(r.DialTimeout) * time.Second, |
||||
}) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
resolver.Register(r) |
||||
|
||||
r.closeCh = make(chan struct{}) |
||||
|
||||
if err = r.sync(); err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
go r.watch() |
||||
|
||||
return r.closeCh, nil |
||||
} |
||||
|
||||
// watch update events
|
||||
func (r *Resolver) watch() { |
||||
ticker := time.NewTicker(time.Minute) |
||||
r.watchCh = r.cli.Watch(context.Background(), r.keyPrifix, clientv3.WithPrefix()) |
||||
|
||||
for { |
||||
select { |
||||
case <-r.closeCh: |
||||
return |
||||
case res, ok := <-r.watchCh: |
||||
if ok { |
||||
r.update(res.Events) |
||||
} |
||||
case <-ticker.C: |
||||
if err := r.sync(); err != nil { |
||||
r.logger.Error("sync failed", err) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// update
|
||||
func (r *Resolver) update(events []*clientv3.Event) { |
||||
for _, ev := range events { |
||||
var info Server |
||||
var err error |
||||
|
||||
switch ev.Type { |
||||
case clientv3.EventTypePut: |
||||
info, err = ParseValue(ev.Kv.Value) |
||||
if err != nil { |
||||
continue |
||||
} |
||||
addr := resolver.Address{Addr: info.Addr} |
||||
for k, v := range info.Attrs { |
||||
addr.Attributes = addr.Attributes.WithValue(k, v) |
||||
} |
||||
if !Exist(r.srvAddrsList, addr) { |
||||
r.srvAddrsList = append(r.srvAddrsList, addr) |
||||
r.cc.UpdateState(resolver.State{Addresses: r.srvAddrsList}) |
||||
} |
||||
case clientv3.EventTypeDelete: |
||||
info, err = SplitPath(string(ev.Kv.Key)) |
||||
if err != nil { |
||||
continue |
||||
} |
||||
addr := resolver.Address{Addr: info.Addr} |
||||
if s, ok := Remove(r.srvAddrsList, addr); ok { |
||||
r.srvAddrsList = s |
||||
r.cc.UpdateState(resolver.State{Addresses: r.srvAddrsList}) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
// sync 同步获取所有地址信息
|
||||
func (r *Resolver) sync() (err error) { |
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) |
||||
defer cancel() |
||||
res, err := r.cli.Get(ctx, r.keyPrifix, clientv3.WithPrefix()) |
||||
if err != nil { |
||||
return |
||||
} |
||||
r.srvAddrsList = []resolver.Address{} |
||||
|
||||
for _, v := range res.Kvs { |
||||
info, err := ParseValue(v.Value) |
||||
if err != nil { |
||||
continue |
||||
} |
||||
addr := resolver.Address{Addr: info.Addr} |
||||
for k, v := range info.Attrs { |
||||
addr.Attributes = addr.Attributes.WithValue(k, v) |
||||
} |
||||
r.srvAddrsList = append(r.srvAddrsList, addr) |
||||
} |
||||
err = r.cc.UpdateState(resolver.State{Addresses: r.srvAddrsList}) |
||||
return |
||||
} |
||||
@ -0,0 +1,289 @@
|
||||
package desc_source |
||||
|
||||
import ( |
||||
"context" |
||||
"errors" |
||||
"fmt" |
||||
"io/ioutil" |
||||
"sync" |
||||
|
||||
"github.com/golang/protobuf/proto" |
||||
descpb "github.com/golang/protobuf/protoc-gen-go/descriptor" |
||||
"github.com/jhump/protoreflect/desc" |
||||
"github.com/jhump/protoreflect/desc/protoparse" |
||||
"github.com/jhump/protoreflect/dynamic" |
||||
"github.com/jhump/protoreflect/grpcreflect" |
||||
"google.golang.org/grpc/codes" |
||||
"google.golang.org/grpc/status" |
||||
) |
||||
|
||||
// ErrReflectionNotSupported is returned by DescriptorSource operations that
|
||||
// rely on interacting with the reflection service when the source does not
|
||||
// actually expose the reflection service. When this occurs, an alternate source
|
||||
// (like file descriptor sets) must be used.
|
||||
var ErrReflectionNotSupported = errors.New("server does not support the reflection API") |
||||
|
||||
// DescriptorSource is a source of protobuf descriptor information. It can be backed by a FileDescriptorSet
|
||||
// proto (like a file generated by protoc) or a remote server that supports the reflection API.
|
||||
type DescriptorSource interface { |
||||
// ListServices returns a list of fully-qualified service names. It will be all services in a set of
|
||||
// descriptor files or the set of all services exposed by a gRPC server.
|
||||
ListServices() ([]string, error) |
||||
// FindSymbol returns a descriptor for the given fully-qualified symbol name.
|
||||
FindSymbol(fullyQualifiedName string) (desc.Descriptor, error) |
||||
// AllExtensionsForType returns all known extension fields that extend the given message type name.
|
||||
AllExtensionsForType(typeName string) ([]*desc.FieldDescriptor, error) |
||||
} |
||||
|
||||
// DescriptorSourceFromProtoSets creates a DescriptorSource that is backed by the named files, whose contents
|
||||
// are encoded FileDescriptorSet protos.
|
||||
func DescriptorSourceFromProtoSets(fileNames ...string) (DescriptorSource, error) { |
||||
files := &descpb.FileDescriptorSet{} |
||||
for _, fileName := range fileNames { |
||||
b, err := ioutil.ReadFile(fileName) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("could not load protoset file %q: %v", fileName, err) |
||||
} |
||||
|
||||
var fs descpb.FileDescriptorSet |
||||
err = proto.Unmarshal(b, &fs) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("could not parse contents of protoset file %q: %v", fileName, err) |
||||
} |
||||
|
||||
files.File = append(files.File, fs.File...) |
||||
} |
||||
return DescriptorSourceFromFileDescriptorSet(files) |
||||
} |
||||
|
||||
// DescriptorSourceFromProtoFiles creates a DescriptorSource that is backed by the named files,
|
||||
// whose contents are Protocol Buffer source files. The given importPaths are used to locate
|
||||
// any imported files.
|
||||
func DescriptorSourceFromProtoFiles(importPaths []string, fileNames ...string) (DescriptorSource, error) { |
||||
p := protoparse.Parser{ |
||||
ImportPaths: importPaths, |
||||
InferImportPaths: len(importPaths) == 0, |
||||
} |
||||
fds, err := p.ParseFiles(fileNames...) |
||||
if err != nil { |
||||
return nil, fmt.Errorf("could not parse given files: %v", err) |
||||
} |
||||
|
||||
return DescriptorSourceFromFileDescriptors(fds...) |
||||
} |
||||
|
||||
// DescriptorSourceFromFileDescriptorSet creates a DescriptorSource that is backed by the FileDescriptorSet.
|
||||
func DescriptorSourceFromFileDescriptorSet(files *descpb.FileDescriptorSet) (DescriptorSource, error) { |
||||
unresolved := map[string]*descpb.FileDescriptorProto{} |
||||
for _, fd := range files.File { |
||||
unresolved[fd.GetName()] = fd |
||||
} |
||||
|
||||
resolved := map[string]*desc.FileDescriptor{} |
||||
for _, fd := range files.File { |
||||
_, err := resolveFileDescriptor(unresolved, resolved, fd.GetName()) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
} |
||||
|
||||
return &fileSource{files: resolved}, nil |
||||
} |
||||
|
||||
func resolveFileDescriptor(unresolved map[string]*descpb.FileDescriptorProto, resolved map[string]*desc.FileDescriptor, filename string) (*desc.FileDescriptor, error) { |
||||
if r, ok := resolved[filename]; ok { |
||||
return r, nil |
||||
} |
||||
|
||||
fd, ok := unresolved[filename] |
||||
if !ok { |
||||
return nil, fmt.Errorf("no descriptor found for %q", filename) |
||||
} |
||||
|
||||
deps := make([]*desc.FileDescriptor, 0, len(fd.GetDependency())) |
||||
for _, dep := range fd.GetDependency() { |
||||
depFd, err := resolveFileDescriptor(unresolved, resolved, dep) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
deps = append(deps, depFd) |
||||
} |
||||
|
||||
result, err := desc.CreateFileDescriptor(fd, deps...) |
||||
if err != nil { |
||||
return nil, err |
||||
} |
||||
|
||||
resolved[filename] = result |
||||
return result, nil |
||||
} |
||||
|
||||
// DescriptorSourceFromFileDescriptors creates a DescriptorSource that is backed by the given
|
||||
// file descriptors
|
||||
func DescriptorSourceFromFileDescriptors(files ...*desc.FileDescriptor) (DescriptorSource, error) { |
||||
fds := map[string]*desc.FileDescriptor{} |
||||
for _, fd := range files { |
||||
if err := addFile(fd, fds); err != nil { |
||||
return nil, err |
||||
} |
||||
} |
||||
|
||||
return &fileSource{files: fds}, nil |
||||
} |
||||
|
||||
func addFile(fd *desc.FileDescriptor, fds map[string]*desc.FileDescriptor) error { |
||||
name := fd.GetName() |
||||
if existing, ok := fds[name]; ok { |
||||
// already added this file
|
||||
if existing != fd { |
||||
// doh! duplicate files provided
|
||||
return fmt.Errorf("given files include multiple copies of %q", name) |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
fds[name] = fd |
||||
for _, dep := range fd.GetDependencies() { |
||||
if err := addFile(dep, fds); err != nil { |
||||
return err |
||||
} |
||||
} |
||||
|
||||
return nil |
||||
} |
||||
|
||||
type fileSource struct { |
||||
files map[string]*desc.FileDescriptor |
||||
er *dynamic.ExtensionRegistry |
||||
erInit sync.Once |
||||
} |
||||
|
||||
func (fs *fileSource) ListServices() ([]string, error) { |
||||
set := map[string]bool{} |
||||
for _, fd := range fs.files { |
||||
for _, svc := range fd.GetServices() { |
||||
set[svc.GetFullyQualifiedName()] = true |
||||
} |
||||
} |
||||
sl := make([]string, 0, len(set)) |
||||
for svc := range set { |
||||
sl = append(sl, svc) |
||||
} |
||||
|
||||
return sl, nil |
||||
} |
||||
|
||||
func (fs *fileSource) ListMethods() (map[string][]string, error) { |
||||
set := map[string][]string{} |
||||
for _, fd := range fs.files { |
||||
for _, svc := range fd.GetServices() { |
||||
m, ok := set[svc.GetFullyQualifiedName()] |
||||
if !ok { |
||||
m = []string{} |
||||
} |
||||
for _, v := range svc.GetMethods() { |
||||
m = append(m, v.GetName()) |
||||
// m = append(.GetFullyQualifiedName()], v.GetName())
|
||||
} |
||||
|
||||
set[svc.GetFullyQualifiedName()] = m |
||||
} |
||||
} |
||||
|
||||
return set, nil |
||||
} |
||||
|
||||
// GetAllFiles returns all of the underlying file descriptors. This is
|
||||
// more thorough and more efficient than the fallback strategy used by
|
||||
// the GetAllFiles package method, for enumerating all files from a
|
||||
// descriptor source.
|
||||
func (fs *fileSource) GetAllFiles() ([]*desc.FileDescriptor, error) { |
||||
files := make([]*desc.FileDescriptor, len(fs.files)) |
||||
i := 0 |
||||
for _, fd := range fs.files { |
||||
files[i] = fd |
||||
i++ |
||||
} |
||||
|
||||
return files, nil |
||||
} |
||||
|
||||
func (fs *fileSource) FindSymbol(fullyQualifiedName string) (desc.Descriptor, error) { |
||||
for _, fd := range fs.files { |
||||
if dsc := fd.FindSymbol(fullyQualifiedName); dsc != nil { |
||||
return dsc, nil |
||||
} |
||||
} |
||||
|
||||
return nil, notFound("Symbol", fullyQualifiedName) |
||||
} |
||||
|
||||
func (fs *fileSource) AllExtensionsForType(typeName string) ([]*desc.FieldDescriptor, error) { |
||||
fs.erInit.Do(func() { |
||||
fs.er = &dynamic.ExtensionRegistry{} |
||||
for _, fd := range fs.files { |
||||
fs.er.AddExtensionsFromFile(fd) |
||||
} |
||||
}) |
||||
return fs.er.AllExtensionsForType(typeName), nil |
||||
} |
||||
|
||||
// DescriptorSourceFromServer creates a DescriptorSource that uses the given gRPC reflection client
|
||||
// to interrogate a server for descriptor information. If the server does not support the reflection
|
||||
// API then the various DescriptorSource methods will return ErrReflectionNotSupported
|
||||
func DescriptorSourceFromServer(_ context.Context, refClient *grpcreflect.Client) DescriptorSource { |
||||
return serverSource{client: refClient} |
||||
} |
||||
|
||||
type serverSource struct { |
||||
client *grpcreflect.Client |
||||
} |
||||
|
||||
func (ss serverSource) ListServices() ([]string, error) { |
||||
svcs, err := ss.client.ListServices() |
||||
return svcs, reflectionSupport(err) |
||||
} |
||||
|
||||
func (ss serverSource) FindSymbol(fullyQualifiedName string) (desc.Descriptor, error) { |
||||
file, err := ss.client.FileContainingSymbol(fullyQualifiedName) |
||||
if err != nil { |
||||
return nil, reflectionSupport(err) |
||||
} |
||||
|
||||
d := file.FindSymbol(fullyQualifiedName) |
||||
if d == nil { |
||||
return nil, notFound("Symbol", fullyQualifiedName) |
||||
} |
||||
|
||||
return d, nil |
||||
} |
||||
|
||||
func (ss serverSource) AllExtensionsForType(typeName string) ([]*desc.FieldDescriptor, error) { |
||||
var exts []*desc.FieldDescriptor |
||||
nums, err := ss.client.AllExtensionNumbersForType(typeName) |
||||
if err != nil { |
||||
return nil, reflectionSupport(err) |
||||
} |
||||
|
||||
for _, fieldNum := range nums { |
||||
ext, err := ss.client.ResolveExtension(typeName, fieldNum) |
||||
if err != nil { |
||||
return nil, reflectionSupport(err) |
||||
} |
||||
exts = append(exts, ext) |
||||
} |
||||
|
||||
return exts, nil |
||||
} |
||||
|
||||
func reflectionSupport(err error) error { |
||||
if err == nil { |
||||
return nil |
||||
} |
||||
|
||||
if stat, ok := status.FromError(err); ok && stat.Code() == codes.Unimplemented { |
||||
return ErrReflectionNotSupported |
||||
} |
||||
|
||||
return err |
||||
} |
||||
@ -0,0 +1,25 @@
|
||||
package desc_source |
||||
|
||||
import ( |
||||
"fmt" |
||||
"github.com/jhump/protoreflect/grpcreflect" |
||||
) |
||||
|
||||
type notFoundError string |
||||
|
||||
func notFound(kind, name string) error { |
||||
return notFoundError(fmt.Sprintf("%s not found: %s", kind, name)) |
||||
} |
||||
|
||||
func (e notFoundError) Error() string { |
||||
return string(e) |
||||
} |
||||
|
||||
func IsNotFoundError(err error) bool { |
||||
if grpcreflect.IsElementNotFoundError(err) { |
||||
return true |
||||
} |
||||
|
||||
_, ok := err.(notFoundError) |
||||
return ok |
||||
} |
||||
@ -0,0 +1,38 @@
|
||||
package protocol |
||||
|
||||
// protocol
|
||||
// 1byte: magic: 99
|
||||
// 1byte: 1 request, 2 response, 3 event, 4 error
|
||||
// 1byte: status: 20-OK, 30-CLIENT_TIMEOUT, 31-SERVER_TIMEOUT, 40-BAD_REQUEST, 41-BAD_RESPONSE, 44-SERVICE_NOT_FOUND, 50-CLIENT_ERROR, 51-SERVER_ERROR, 52-SERVICE_ERROR
|
||||
// 4bit: svc,method url desc: 1 name, 2 number
|
||||
// 4bit: serialize: 1proto, 2json
|
||||
// 4byte: seqId
|
||||
// string: service, method / 4byte svc, 4byte method/4byte notice
|
||||
// proto bytes / json bytes
|
||||
|
||||
const ( |
||||
Magic int8 = 99 |
||||
|
||||
TypeRequest int8 = 1 |
||||
TypeResponse int8 = 2 |
||||
TypeNotice int8 = 3 |
||||
TypeError int8 = 4 |
||||
) |
||||
|
||||
type Header struct { |
||||
Magic int8 |
||||
Type int8 // 1 request, 2 response, 3 event, 4 error
|
||||
Status int8 |
||||
UrlType int8 |
||||
SerializeType int8 |
||||
SeqId int32 |
||||
SvcNo int32 |
||||
MethodNo int32 |
||||
Svc string |
||||
Method string |
||||
} |
||||
|
||||
type Payload struct { |
||||
Header Header |
||||
Body []byte |
||||
} |
||||
@ -0,0 +1,30 @@
|
||||
package conver |
||||
|
||||
import ( |
||||
"fmt" |
||||
"github.com/dsnet/golib/unitconv" |
||||
) |
||||
|
||||
// ParseDataUnit parse 1Ki -> 1024, 1K -> 1000
|
||||
func ParseDataUnit(unit string) (val float64, err error) { |
||||
val, err = unitconv.ParsePrefix(unit, unitconv.AutoParse) |
||||
return |
||||
} |
||||
|
||||
func ParseDataUnitInt(unit string) (val int, err error) { |
||||
v, err := ParseDataUnit(unit) |
||||
val = int(v) |
||||
return |
||||
} |
||||
|
||||
func MustParseDataUnit(unit string) (val float64) { |
||||
val, err := unitconv.ParsePrefix(unit, unitconv.AutoParse) |
||||
if err != nil { |
||||
panic(fmt.Errorf("error parse data unit %s, %s", unit, err.Error())) |
||||
} |
||||
return |
||||
} |
||||
|
||||
func MustParseDataUnitInt(unit string) (val int) { |
||||
return int(MustParseDataUnit(unit)) |
||||
} |
||||
@ -0,0 +1,49 @@
|
||||
package logger |
||||
|
||||
func Info(args ...any) { |
||||
Logger.Info(args...) |
||||
} |
||||
|
||||
func Infoln(args ...any) { |
||||
Logger.Infoln(args...) |
||||
} |
||||
|
||||
func Infof(format string, args ...any) { |
||||
Logger.Infof(format, args...) |
||||
} |
||||
|
||||
func Warning(args ...any) { |
||||
Logger.Warning(args...) |
||||
} |
||||
|
||||
func Warningln(args ...any) { |
||||
Logger.Warningln(args...) |
||||
} |
||||
|
||||
func Warningf(format string, args ...any) { |
||||
Logger.Warningf(format, args...) |
||||
} |
||||
|
||||
func Error(args ...any) { |
||||
Logger.Error(args...) |
||||
} |
||||
|
||||
func Errorln(args ...any) { |
||||
Logger.Errorln(args...) |
||||
} |
||||
|
||||
func Errorf(format string, args ...any) { |
||||
Logger.Errorf(format, args...) |
||||
} |
||||
|
||||
func Fatal(args ...any) { |
||||
Logger.Fatal(args...) |
||||
} |
||||
|
||||
func Fatalln(args ...any) { |
||||
Logger.Fatalln(args...) |
||||
} |
||||
|
||||
func Fatalf(format string, args ...any) { |
||||
Logger.Fatalf(format, args...) |
||||
} |
||||
@ -0,0 +1,78 @@
|
||||
package logger |
||||
|
||||
import ( |
||||
"github.com/sirupsen/logrus" |
||||
) |
||||
|
||||
var Logger *SoLogger |
||||
|
||||
func init() { |
||||
Logger = &SoLogger{logger: logrus.New()} |
||||
} |
||||
|
||||
type SoLogger struct { |
||||
logger *logrus.Logger |
||||
} |
||||
|
||||
func (l *SoLogger) Info(args ...any) { |
||||
l.logger.Info(args...) |
||||
} |
||||
|
||||
func (l *SoLogger) Infoln(args ...any) { |
||||
l.logger.Infoln(args...) |
||||
} |
||||
|
||||
func (l *SoLogger) Infof(format string, args ...any) { |
||||
l.logger.Infof(format, args...) |
||||
} |
||||
|
||||
func (l *SoLogger) Warning(args ...any) { |
||||
l.logger.Warning(args...) |
||||
} |
||||
|
||||
func (l *SoLogger) Warningln(args ...any) { |
||||
l.logger.Warningln(args...) |
||||
} |
||||
|
||||
func (l *SoLogger) Warningf(format string, args ...any) { |
||||
l.logger.Warningf(format, args...) |
||||
} |
||||
|
||||
func (l *SoLogger) Error(args ...any) { |
||||
l.logger.Error(args...) |
||||
} |
||||
|
||||
func (l *SoLogger) Errorln(args ...any) { |
||||
l.logger.Errorln(args...) |
||||
} |
||||
|
||||
func (l *SoLogger) Errorf(format string, args ...any) { |
||||
l.logger.Errorf(format, args...) |
||||
} |
||||
|
||||
func (l *SoLogger) Fatal(args ...any) { |
||||
l.logger.Fatal(args...) |
||||
} |
||||
|
||||
func (l *SoLogger) Fatalln(args ...any) { |
||||
l.logger.Fatalln(args...) |
||||
} |
||||
|
||||
func (l *SoLogger) Fatalf(format string, args ...any) { |
||||
l.logger.Fatalf(format, args...) |
||||
} |
||||
|
||||
var ( |
||||
logrusLevels = []logrus.Level{logrus.TraceLevel, logrus.DebugLevel, logrus.InfoLevel, logrus.WarnLevel, logrus.ErrorLevel, logrus.FatalLevel, logrus.PanicLevel} |
||||
logrusLevelsLen = len(logrusLevels) |
||||
) |
||||
|
||||
// V enable level
|
||||
// grpclog:info=2,warn=3...
|
||||
// logrus: warn=3,info=4...
|
||||
func (l *SoLogger) V(level int) bool { |
||||
if level >= logrusLevelsLen { |
||||
return true |
||||
} |
||||
return logrusLevels[level] <= l.logger.Level |
||||
} |
||||
@ -0,0 +1,42 @@
|
||||
package nets |
||||
|
||||
import ( |
||||
"errors" |
||||
"net" |
||||
) |
||||
|
||||
// GetHostIpv4 获取本地内网IP
|
||||
func GetHostIpv4() (string, error) { |
||||
privates, err := getAllIPV4(func(ip net.IP) bool { |
||||
return ip.IsPrivate() |
||||
}) |
||||
if err != nil { |
||||
return "", err |
||||
} |
||||
if len(privates) == 0 { |
||||
return "", errors.New("no private ip") |
||||
} |
||||
return privates[0], nil |
||||
} |
||||
|
||||
func getAllIPV4(filter func(net.IP) bool) (ips []string, err error) { |
||||
// 获取所有网卡
|
||||
addrs, err := net.InterfaceAddrs() |
||||
if err != nil { |
||||
return |
||||
} |
||||
|
||||
for _, addr := range addrs { |
||||
// 这个网络地址是IP地址: ipv4, ipv6
|
||||
ipNet, isIpNet := addr.(*net.IPNet) |
||||
if isIpNet && !ipNet.IP.IsLoopback() { |
||||
// 跳过IPV6
|
||||
if ipNet.IP.To4() != nil { |
||||
if filter(ipNet.IP) { |
||||
ips = append(ips, ipNet.IP.String()) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
return |
||||
} |
||||
@ -0,0 +1,52 @@
|
||||
package shutdown |
||||
|
||||
import ( |
||||
"log" |
||||
"os" |
||||
"os/signal" |
||||
"sync" |
||||
"sync/atomic" |
||||
"syscall" |
||||
) |
||||
|
||||
var ( |
||||
shutdownHooks []func() |
||||
lock = &sync.Mutex{} |
||||
sigChan = make(chan os.Signal, 1) |
||||
) |
||||
|
||||
func AddShutdownHook(hook func()) { |
||||
lock.Lock() |
||||
defer lock.Unlock() |
||||
shutdownHooks = append(shutdownHooks, hook) |
||||
} |
||||
|
||||
func Await() { |
||||
// 监听两个信号: TERM信号(kill + 进程号)触发, 中断信号(ctrl + c)触发
|
||||
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP) |
||||
s := <-sigChan |
||||
// 监听到关闭信号
|
||||
log.Println("catch exit signal: ", s) |
||||
|
||||
var success, fail int32 |
||||
for _, hook := range shutdownHooks { |
||||
func() { |
||||
defer func() { |
||||
if err := recover(); err != nil { |
||||
log.Println("exec shutdown hook panic: ", err) |
||||
atomic.AddInt32(&fail, 1) |
||||
return |
||||
} |
||||
atomic.AddInt32(&success, 1) |
||||
}() |
||||
|
||||
hook() |
||||
}() |
||||
} |
||||
|
||||
log.Printf("execute shutdown hook %d success, %d failed\n", success, fail) |
||||
} |
||||
|
||||
//func Shutdown() {
|
||||
// sigChan <- syscall.SIGQUIT
|
||||
//}
|
||||
Loading…
Reference in new issue