Skip to content
Snippets Groups Projects
Commit 617e00e3 authored by Pavel Antonov's avatar Pavel Antonov :asterisk:
Browse files

Merge branch 'feature/PRXS-1005-PerxisGoSpaces' into 'master'

Добавлены spaces

See merge request perxis/perxis-go!8
parents 33567314 d91c84c5
Branches
Tags v0.0.4
No related merge requests found
Showing
with 1241 additions and 9 deletions
......@@ -32,3 +32,23 @@ ifeq (,$(wildcard $(GOPATH)/bin/protoc-gen-go))
Run \"go get -u google.golang.org/protobuf/cmd/protoc-gen-go google.golang.org/grpc/cmd/protoc-gen-go-grpc\" \
or visit \"https://github.com/golang/protobuf/tree/v1.3.2#installation\" for more.\n")
endif
#MICROGENFILES?=$(shell find $(SERVICESDIR) -name "service.go" -exec grep -Ril "microgen" {} \;)
#SERVICEDIRS?=$(shell find $(SERVICESDIR) -name "service" -type d -exec dirname {} \;)
#SERVICEFILES?=$(shell find $(SERVICESDIR) -name "service.go" -exec grep -Ril "go:generate" {} \;)
# Генерация моков для всех интерфейсов, найденных в директории. Выходные файлы с моками сохраняются в `./mocks`
MOCKSDIRS?=$(shell find . -name "service.go" -exec dirname {} \;)
MOCKS=$(MOCKSDIRS:=/mocks)
mocks: $(MOCKS)
@echo "Generate mocks $<"
%/mocks: %
@echo "$@ - $<"
@mockery --log-level="error" --all --dir "$<" --output="$@"
mocks-clean:
@rm -rf $(MOCKS)
......@@ -3,14 +3,26 @@ module git.perx.ru/perxis/perxis-go
go 1.18
require (
github.com/go-kit/kit v0.12.0
github.com/golang/protobuf v1.5.2
github.com/hashicorp/go-multierror v1.1.1
github.com/pkg/errors v0.9.1
github.com/rs/xid v1.4.0
github.com/stretchr/testify v1.7.0
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf
google.golang.org/grpc v1.45.0
google.golang.org/protobuf v1.28.0
)
require (
github.com/golang/protobuf v1.5.2 // indirect
golang.org/x/net v0.0.0-20200822124328-c89045814202 // indirect
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd // indirect
golang.org/x/text v0.3.0 // indirect
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/go-kit/log v0.2.0 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/objx v0.1.0 // indirect
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 // indirect
golang.org/x/text v0.3.7 // indirect
google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect
)
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
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/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4=
github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs=
github.com/go-kit/log v0.2.0 h1:7i2K3eKTos3Vc0enKCfnVcgHh2olr/MyfboYq7cAcFw=
github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
......@@ -44,44 +55,79 @@ github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rs/xid v1.4.0 h1:qd7wPTDkN6KQx2VmMBLrpHkiyQwgFXRnkOLacUiaSNY=
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
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/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
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-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
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-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf h1:R150MpwJIv1MpS0N/pc+NhTM8ajzvlmxlY5OYsrevXQ=
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/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-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
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-20210917161153-d61c044b1678 h1:J27LZFQBFoihqXoegpscI10HpjZ7B5WQLLKL2FZXQKw=
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
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-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
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=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
......@@ -90,14 +136,16 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4 h1:ysnBoUyeL/H6RCvNRhWHjKoDEmguI+mPU+qHgK8qv/w=
google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
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.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.45.0 h1:NEpgUqV3Z+ZjkqMsxMg11IaDrXY4RY6CQukSGK0uI1M=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
......@@ -111,11 +159,14 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
package errors
import (
"fmt"
"io"
"sync"
)
var codeErrors sync.Map
type CodeError interface {
Code() uint64
}
type codeError struct {
code uint64
err error
}
func (e *codeError) Error() string { return fmt.Sprintf("(%d) %s", e.code, e.err.Error()) }
func (e *codeError) Code() uint64 { return e.code }
func (w *codeError) Unwrap() error { return w.err }
func (e *codeError) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "\n(%d): %s", e.code, e.Error())
return
}
fallthrough
case 's':
io.WriteString(s, e.Error())
case 'q':
fmt.Fprintf(s, "%q", e.Error())
}
}
func (e *codeError) Is(err error) bool {
if ce, ok := err.(CodeError); ok {
return e.code == ce.Code()
}
return false
}
func WithCode(err error, code uint64) error {
err = &codeError{code: code, err: err}
v, _ := codeErrors.LoadOrStore(code, err)
return v.(error)
}
func GetCode(err error) uint64 {
for e := err; e != nil; e = Unwrap(e) {
if errCode, ok := e.(CodeError); ok {
return errCode.Code()
}
}
return 0
}
package errors
type ErrContext interface{ Context() []interface{} }
type withContext struct {
err error
kv []interface{}
}
func (w *withContext) Context() []interface{} { return w.kv }
func (w *withContext) Error() string { return w.err.Error() }
func (w *withContext) Cause() error { return w.err }
func (w *withContext) Unwrap() error { return w.err }
// WithContext добавляет контекст к ошибке
func WithContext(err error, kv ...interface{}) error {
for e := err; e != nil; e = Unwrap(e) {
if wc, ok := e.(*withContext); ok {
wc.kv = append(wc.kv, kv...)
return err
}
}
return &withContext{
err: err,
kv: kv,
}
}
// Context возвращает контекст из ошибки
func Context(err error) []interface{} {
for e := err; e != nil; e = Unwrap(e) {
if errContext, ok := e.(ErrContext); ok {
return errContext.Context()
}
}
return nil
}
// ContextKey возвращает значение ключа из контекста ошибки
func ContextKey(err error, key interface{}) (interface{}, bool) {
if kv := Context(err); kv != nil {
var i int
for {
if i >= len(kv) {
return nil, false
}
v := kv[i]
if v == key {
return kv[i+1], true
}
i += 2
}
}
return nil, false
}
package errors
import (
"fmt"
"io"
)
type ErrDetail interface{ Detail() string }
type withDetail struct {
err error
detail string
}
func (w *withDetail) Detail() string { return w.detail }
func (w *withDetail) Error() string { return w.err.Error() }
func (w *withDetail) Cause() error { return w.err }
func (w *withDetail) Unwrap() error { return w.err }
func (w *withDetail) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "%+v", w.Cause())
fmt.Fprintf(s, "\nerror detail: %s", w.detail)
return
}
fallthrough
case 's':
io.WriteString(s, w.Error())
case 'q':
fmt.Fprintf(s, "%q", w.Error())
}
}
func WithDetail(err error, detail string) error {
if err == nil {
return nil
}
return &withDetail{err: err, detail: detail}
}
func WithDetailf(err error, format string, args ...interface{}) error {
if err == nil {
return nil
}
return &withDetail{err: err, detail: fmt.Sprintf(format, args...)}
}
func GetDetail(err error) string {
for e := err; e != nil; e = Unwrap(e) {
if errDetail, ok := e.(ErrDetail); ok {
return errDetail.Detail()
}
}
return ""
}
package errors
import (
"fmt"
"io"
)
const (
NoDomain = ""
GlobalDomain = "global"
)
type ErrDomain interface{ Domain() string }
type withDomain struct {
err error
domain string
}
func (w *withDomain) Domain() string { return w.domain }
func (w *withDomain) Error() string { return w.err.Error() }
func (w *withDomain) Unwrap() error { return w.err }
func (w *withDomain) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "%+v", w.Unwrap())
fmt.Fprintf(s, "\nerror domain: %s", w.domain)
return
}
fallthrough
case 's':
io.WriteString(s, w.Error())
case 'q':
fmt.Fprintf(s, "%q", w.Error())
}
}
func WithDomain(err error, domain string) error {
if err == nil {
return nil
}
return &withDomain{err: err, domain: domain}
}
func Global(err error) error {
return WithDomain(err, GlobalDomain)
}
func GetDomain(err error) string {
for e := err; e != nil; e = Unwrap(e) {
if errDomain, ok := e.(ErrDomain); ok {
return errDomain.Domain()
}
}
return NoDomain
}
package errors
//import (
// "errors"
//)
//var (
// ErrSpaceRequired = errors.New("space required")
// ErrSpaceHostRequired = errors.New("space host required")
// ErrSpaceNotFound = errors.New("space not found")
// ErrSpaceAlreadyExists = errors.New("space already exists")
//)
//
//var errs = []error{
// ErrSpaceRequired,
// ErrSpaceHostRequired,
// ErrSpaceNotFound,
// ErrSpaceAlreadyExists,
//}
//
//var errMap map[string]error
//
////func New(text string) error {
//// if errMap == nil {
//// errMap = make(map[string]error)
//// for _, e := range errs {
//// errMap[e.Error()] = e
//// }
//// }
////
//// if e, ok := errMap[text]; ok {
//// return e
//// }
////
//// return errors.New(text)
////}
//
//func IsAny(err error, targets ...error) bool {
// for _, t := range targets {
// if errors.Is(err, t) {
// return true
// }
// }
// return false
//}
//
//var (
// Is = errors.Is
// As = errors.As
// Unwrap = errors.Unwrap
//)
package errors
import (
stderr "errors"
"github.com/pkg/errors"
)
var (
Is = stderr.Is
As = stderr.As
New = stderr.New
Unwrap = stderr.Unwrap
Errorf = errors.Errorf
Wrap = errors.Wrap
Wrapf = errors.Wrapf
//Wrap = errors.Wrap
//Wrapf = errors.Wrapf
//WithMessage = errors.WithMessage
//CombineErrors = errors.CombineErrors
////Detail = errors.Detail
////WithDetailf = errors.WithDetailf
////WithHint = errors.WithHint
//Mark = errors.Mark
//Tags = errors.WithContextTags
//
//CoreDomain = errors.Domain("core")
//StorageDomain = errors.Domain("storage")
//ServiceDomain = errors.Domain("service")
//TransportDomain = errors.Domain("transport")
//EventsDomain = errors.Domain("events")
)
//func New(msg string) error {
// return &Error{Message: msg}
//}
//func Trace(err error) error {
// return WithStack(WithID(err))
//}
//
//func Wrap(err error, msg string) error {
// return WithID(errors.Wrap(err, msg))
//}
//
//func ErrorBuilder(domain string) func(string) error {
// return func(msg string) error {
// return WithDomain(WithID(New(msg)), domain)
// }
//}
//
//func ErrorfBuilder(domain string) func(format string, args ...interface{}) error {
// return func(format string, args ...interface{}) error {
// return WithDomain(WithID(Errorf(format, args...)), domain)
// }
//}
//
//type Error struct {
// Message string
//}
//
//func (e *Error) Error() string { return e.Message }
//func (e *Error) Is(err error) bool {
// if errr, ok := err.(*Error); ok {
// if e.Message == errr.Message {
// return true
// }
// }
// return false
//}
package errors
//
//import (
// "fmt"
// "testing"
//
// jsoniter "github.com/json-iterator/go"
// "github.com/perxteam/hoop4/yaml"
// "github.com/stretchr/testify/assert"
// "github.com/stretchr/testify/require"
//)
//
//func TestErrors_OmitemptyError(t *testing.T) {
// type Struct struct {
// Some string `json:"some"`
// Error error `json:"error,omitempty"`
// }
//
// s := &Struct{Some: "Some"}
// b, err := jsoniter.Marshal(s)
// require.NoError(t, err)
//
// var ss Struct
// err = jsoniter.Unmarshal(b, &ss)
// require.NoError(t, err)
//}
//
//func TestErrors_EmptyError(t *testing.T) {
// type Struct struct {
// Some string `json:"some"`
// Error error `json:"error"`
// }
//
// s := &Struct{Some: "Some"}
// b, err := jsoniter.Marshal(s)
// require.NoError(t, err)
//
// var ss Struct
// err = jsoniter.Unmarshal(b, &ss)
// require.NoError(t, err)
//}
//
//func TestErrors_MarshalYAML(t *testing.T) {
// type S struct {
// Error error
// }
// l1 := &S{New("test")}
//
// _, err := yaml.Marshal(l1)
// require.NoError(t, err)
//}
//
//func TestErrors_Encode(t *testing.T) {
// e := Global(WithID(New("test")))
// e = WithStack(e)
// e = NotFound(e)
// e = fmt.Errorf("Got error %w", e)
// e = WithDetail(WithHint(e, "Hint"), "Detail")
// e = WithErrors(e, New("add1"), New("add2"))
// enc := EncodeError(e)
// err := DecodeError(enc)
//
// assert.True(t, IsNotFound(err))
// assert.Equal(t, "Got error test", err.Error())
// assert.True(t, Is(err, New("Got error test")))
// assert.Equal(t, "Hint", GetHint(err))
// assert.Equal(t, "Detail", GetDetail(err))
// assert.NotEmpty(t, GetID(err))
// assert.Equal(t, GetID(e), GetID(err))
// assert.Equal(t, GlobalDomain, GetDomain(err))
// errs := GetErrors(err)
// require.Len(t, errs, 2)
// assert.True(t, Is(errs[0], New("add1")))
// assert.True(t, Is(errs[1], New("add2")))
//}
//
//func TestErrors_JSONEncode(t *testing.T) {
// type Struct struct {
// Some string `json:"some"`
// Error error `json:"error,omitempty"`
// }
//
// s := &Struct{Some: "Some"}
// e := Global(WithID(New("test")))
// e = WithStack(e)
// e = NotFound(e)
// e = fmt.Errorf("Got error %w", e)
// e = WithDetail(WithHint(e, "Hint"), "Detail")
// e = WithErrors(e, New("add1"), New("add2"))
// s.Error = e
//
// b, jerr := jsoniter.Marshal(s)
// require.NoError(t, jerr)
//
// var st Struct
// jerr = jsoniter.Unmarshal(b, &st)
// require.NoError(t, jerr)
// err := st.Error
//
// assert.True(t, IsNotFound(err))
// assert.Equal(t, "Got error test", err.Error())
// assert.True(t, Is(err, New("Got error test")))
// assert.Equal(t, "Hint", GetHint(err))
// assert.Equal(t, "Detail", GetDetail(err))
// assert.NotEmpty(t, GetID(err))
// assert.Equal(t, GetID(e), GetID(err))
// assert.Equal(t, GlobalDomain, GetDomain(err))
// errs := GetErrors(err)
// require.Len(t, errs, 2)
// assert.True(t, Is(errs[0], New("add1")))
// assert.True(t, Is(errs[1], New("add2")))
//}
//
//func TestErrors_MultiErrors(t *testing.T) {
// err := WithErrors(New("main"), New("add1"), New("add2"))
// errs := GetErrors(err)
// require.Len(t, errs, 2)
// assert.True(t, Is(errs[0], New("add1")))
// assert.True(t, Is(errs[1], New("add2")))
// assert.Equal(t, "main", err.Error())
//}
//
////func TestErrors_NotFound(t *testing.T) {
//// e := NotFound(New("test"))
//// fmt.Println(IsNotFound(e))
//// enc := EncodeError(e)
//// fmt.Printf("%#v", enc)
//// //require.NoError(t, e)
////}
//
package errors
import (
"fmt"
"io"
"github.com/hashicorp/go-multierror"
)
type FieldError interface {
Field() string
Error() string
}
type withField struct {
err error
field string
}
func (w *withField) Field() string { return w.field }
func (w *withField) Error() string { return fmt.Sprintf("field '%s': %s", w.field, w.err.Error()) }
func (w *withField) Unwrap() error { return w.err }
func (w *withField) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "%+v", w.Unwrap())
fmt.Fprintf(s, "\nfield: %s", w.field)
return
}
fallthrough
case 's':
io.WriteString(s, w.Error())
case 'q':
fmt.Fprintf(s, "%q", w.Error())
}
}
func WithField(err error, field string) error {
if err == nil {
return nil
}
var merr *multierror.Error
if As(err, &merr) {
for i, e := range merr.Errors {
merr.Errors[i] = WithField(e, field)
}
return err
}
var ferr *withField
if As(err, &ferr) {
if ferr.field != "" {
ferr.field = field + "." + ferr.field
} else {
ferr.field = field
}
return err
}
return &withField{
field: field,
err: err,
}
}
func GetField(err error) string {
for e := err; e != nil; e = Unwrap(e) {
if errField, ok := e.(FieldError); ok {
return errField.Field()
}
}
return ""
}
package grpc
import (
"context"
"github.com/go-kit/kit/endpoint"
"google.golang.org/grpc/status"
)
func ServerMiddleware(ep endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
response, err = ep(ctx, request)
if err != nil {
if st := StatusFromError(err); st != nil {
err = st.Err()
}
}
return response, err
}
}
func ClientMiddleware(ep endpoint.Endpoint) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
response, err = ep(ctx, request)
if err != nil {
st, _ := status.FromError(err)
err = ErrorFromStatus(st)
}
return response, err
}
}
package grpc
import (
"context"
"testing"
"git.perx.ru/perxis/perxis-go/pkg/errors"
"git.perx.ru/perxis/perxis-go/proto/common"
"github.com/go-kit/kit/endpoint"
"github.com/hashicorp/go-multierror"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func testEndopoint(e error) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
return nil, e
}
}
func TestMiddleware(t *testing.T) {
merr := multierror.Append(errors.WithField(errors.New("err1"), "fld1"), errors.WithField(errors.New("err2"), "fld2"))
err := errors.WrapErr(errors.New("test"), merr)
err = errors.WithID(err)
err = errors.NotFound(err)
err = errors.Wrap(err, "wrapped")
errID := errors.GetID(err)
serverEp := ServerMiddleware(testEndopoint(err))
_, grpcErr := serverEp(context.Background(), nil)
st, _ := status.FromError(grpcErr)
assert.Equal(t, "wrapped: test", st.Message())
assert.Equal(t, codes.NotFound, st.Code())
dt := st.Details()
require.Len(t, dt, 1)
require.IsType(t, (*common.Error)(nil), dt[0])
clientEp := ClientMiddleware(testEndopoint(grpcErr))
_, cliErr := clientEp(context.Background(), nil)
assert.Equal(t, "wrapped: test", cliErr.Error(), "ожидается то же строковое значние, что и у изначальной ошибки")
assert.Equal(t, errID, errors.GetID(cliErr))
assert.Equal(t, codes.NotFound, errors.GetStatusCode(cliErr))
assert.ErrorAs(t, err, &merr)
assert.Len(t, merr.Errors, 2)
}
package grpc
import (
"fmt"
"git.perx.ru/perxis/perxis-go/pkg/errors"
"git.perx.ru/perxis/perxis-go/proto/common"
"github.com/hashicorp/go-multierror"
"google.golang.org/grpc/status"
)
func getHelp(err error) *common.Error_Help {
if help := errors.GetHelp(err); help != nil {
pbhelp := &common.Error_Help{}
for _, hl := range help.Links {
pbhelp.Links = append(pbhelp.Links, &common.Error_Help_Link{Description: hl.Description, Url: hl.URL})
}
return pbhelp
}
return nil
}
func helpFromPb(err error, pberr *common.Error) error {
if pberr.Help == nil || len(pberr.Help.Links) == 0 {
return err
}
h := &errors.Help{}
for _, l := range pberr.Help.Links {
h.Links = append(h.Links, errors.HelpLink{Description: l.Description, URL: l.Url})
}
return errors.WithHelp(err, h)
}
func getBadRequest(err error) *common.Error_BadRequest {
br := &common.Error_BadRequest{}
var merr *multierror.Error
if errors.As(err, &merr) {
for _, e := range merr.Errors {
var errField errors.FieldError
if errors.As(e, &errField) {
br.Errors = append(br.Errors, &common.Error_BadRequest_FieldViolation{Field: errField.Field(), Description: errors.Unwrap(errField).Error()})
}
}
} else {
var errField errors.FieldError
if errors.As(err, &errField) {
br.Errors = append(br.Errors, &common.Error_BadRequest_FieldViolation{Field: errField.Field(), Description: errors.Unwrap(errField).Error()})
}
}
if len(br.Errors) > 0 {
return br
}
return nil
}
func getDebugInfo(err error) *common.Error_DebugInfo {
if trace, ok := errors.GetStackTrace(err); ok {
di := &common.Error_DebugInfo{}
for _, t := range trace {
di.StackTrace = append(di.StackTrace, fmt.Sprintf("%+v", t))
}
return di
}
return nil
}
func badRequestFromPb(err error, pberr *common.Error) error {
if pberr.BadRequest == nil || len(pberr.BadRequest.Errors) == 0 {
return err
}
var merr error
for _, e := range pberr.BadRequest.Errors {
merr = multierror.Append(merr, errors.WithField(errors.New(e.Description), e.Field))
}
return errors.WrapErr(err, merr)
}
func StatusFromError(err error) *status.Status {
if err == nil {
return nil
}
err = errors.WithID(err)
pberr := &common.Error{
ErrorCode: errors.GetCode(err),
ErrorId: errors.GetID(err),
Reason: "", // TBD
Domain: errors.GetDomain(err),
Help: getHelp(err),
Metadata: nil, // TBD
BadRequest: getBadRequest(err),
DebugInfo: getDebugInfo(err),
LocalizedMessages: nil, // TBD
}
st := status.New(errors.GetStatusCode(err), err.Error())
st, _ = st.WithDetails(pberr)
return st
}
func convertProtoError(err error, pberr *common.Error) error {
if pberr == nil {
return nil
}
// Должен быть первым в цепочке
err = badRequestFromPb(err, pberr)
if pberr.ErrorCode != 0 {
err = errors.WithCode(err, pberr.ErrorCode)
}
if pberr.ErrorId != "" {
err = errors.SetID(err, pberr.ErrorId)
}
if pberr.Domain != "" {
err = errors.WithDomain(err, pberr.Domain)
}
err = helpFromPb(err, pberr)
return err
}
func ErrorFromStatus(st *status.Status) error {
details := st.Details()
err := errors.New(st.Message())
if len(details) > 0 {
if pberr, ok := details[0].(*common.Error); ok {
err = convertProtoError(err, pberr)
}
}
err = errors.WithStatusCode(err, st.Code())
return err
}
package grpc
import (
"reflect"
"testing"
"git.perx.ru/perxis/perxis-go/pkg/errors"
"git.perx.ru/perxis/perxis-go/proto/common"
"github.com/hashicorp/go-multierror"
)
func Test_getBadRequest(t *testing.T) {
tests := []struct {
name string
err error
want *common.Error_BadRequest
}{
{"Without field error", errors.New("some"), nil},
{"Field error", errors.WithField(errors.New("some"), "fld1"),
&common.Error_BadRequest{Errors: []*common.Error_BadRequest_FieldViolation{{Description: "some", Field: "fld1"}}}},
{"Deep field error", errors.Wrap(errors.WithField(errors.New("some"), "fld1"), "extra"),
&common.Error_BadRequest{Errors: []*common.Error_BadRequest_FieldViolation{{Description: "some", Field: "fld1"}}}},
{"Nested field errors", errors.WithField(errors.WithField(errors.New("some"), "fld1"), "fld2"),
&common.Error_BadRequest{Errors: []*common.Error_BadRequest_FieldViolation{{Description: "some", Field: "fld2.fld1"}}}},
{"Deep nested field errors", errors.WithField(errors.Wrap(errors.WithField(errors.New("some"), "fld1"), "extra"), "fld2"),
&common.Error_BadRequest{Errors: []*common.Error_BadRequest_FieldViolation{{Description: "some", Field: "fld2.fld1"}}}},
{"Multi Field error", multierror.Append(errors.WithField(errors.New("some"), "fld1"), errors.WithField(errors.New("some"), "fld2")),
&common.Error_BadRequest{Errors: []*common.Error_BadRequest_FieldViolation{{Description: "some", Field: "fld1"}, {Description: "some", Field: "fld2"}}}},
{"Nested Multi Field error", errors.WithField(multierror.Append(errors.WithField(errors.New("some"), "fld1"), errors.WithField(errors.New("some"), "fld2")), "fld3"),
&common.Error_BadRequest{Errors: []*common.Error_BadRequest_FieldViolation{{Description: "some", Field: "fld3.fld1"}, {Description: "some", Field: "fld3.fld2"}}}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := getBadRequest(tt.err); !reflect.DeepEqual(got, tt.want) {
t.Errorf("getBadRequest() = %v, want %v", got, tt.want)
}
})
}
}
func Test_getHelp(t *testing.T) {
tests := []struct {
name string
err error
want *common.Error_Help
}{
{"Without help", errors.New("some"), nil},
{"With help",
errors.WithHelp(errors.New("some"), &errors.Help{Links: []errors.HelpLink{{Description: "Help1", URL: "Url1"}}}),
&common.Error_Help{Links: []*common.Error_Help_Link{{Description: "Help1", Url: "Url1"}}}},
{"With nested help",
errors.WithHelp(errors.WithHelp(errors.New("some"), &errors.Help{Links: []errors.HelpLink{{Description: "Help2", URL: "Url2"}}}), &errors.Help{Links: []errors.HelpLink{{Description: "Help1", URL: "Url1"}}}),
&common.Error_Help{Links: []*common.Error_Help_Link{{Description: "Help1", Url: "Url1"}, {Description: "Help2", Url: "Url2"}}}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := getHelp(tt.err); !reflect.DeepEqual(got, tt.want) {
t.Errorf("getHelp() = %v, want %v", got, tt.want)
}
})
}
}
package errors
type Help struct {
Links []HelpLink
}
type HelpLink struct {
Description string
URL string
}
type HelpError interface{ Help() *Help }
type withHelp struct {
err error
help *Help
}
func (w *withHelp) Help() *Help { return w.help }
func (w *withHelp) Error() string { return w.err.Error() }
func (w *withHelp) Unwrap() error { return w.err }
//func (w *withHelp) Format(s fmt.State, verb rune) {
// switch verb {
// case 'v':
// if s.Flag('+') {
// fmt.Fprintf(s, "%+v", w.Unwrap())
// fmt.Fprintf(s, "\nerror hint: %s", w.hint)
// return
// }
// fallthrough
// case 's':
// io.WriteString(s, w.Error())
// case 'q':
// fmt.Fprintf(s, "%q", w.Error())
// }
//}
func WithHelp(err error, help *Help) error {
if err == nil {
return nil
}
return &withHelp{err: err, help: help}
}
func GetHelp(err error) *Help {
var help Help
for e := err; e != nil; e = Unwrap(e) {
if errHelp, ok := e.(HelpError); ok {
h := errHelp.Help()
if h != nil && len(h.Links) > 0 {
help.Links = append(help.Links, h.Links...)
}
}
}
if len(help.Links) > 0 {
return &help
}
return nil
}
package errors
import (
"fmt"
"io"
)
type ErrHint interface{ Hint() string }
type withHint struct {
err error
hint string
}
func (w *withHint) Hint() string { return w.hint }
func (w *withHint) Error() string { return w.err.Error() }
func (w *withHint) Cause() error { return w.err }
func (w *withHint) Unwrap() error { return w.err }
func (w *withHint) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "%+v", w.Cause())
fmt.Fprintf(s, "\nerror hint: %s", w.hint)
return
}
fallthrough
case 's':
io.WriteString(s, w.Error())
case 'q':
fmt.Fprintf(s, "%q", w.Error())
}
}
func WithHint(err error, hint string) error {
if err == nil {
return nil
}
return &withHint{err: err, hint: hint}
}
func WithHintf(err error, format string, args ...interface{}) error {
if err == nil {
return nil
}
return &withHint{err: err, hint: fmt.Sprintf(format, args...)}
}
func GetHint(err error) string {
for e := err; e != nil; e = Unwrap(e) {
if errDetail, ok := e.(ErrHint); ok {
return errDetail.Hint()
}
}
return ""
}
package errors
import (
"fmt"
"io"
"github.com/rs/xid"
)
type ErrID interface{ ID() string }
type withId struct {
err error
id string
}
func (w *withId) ID() string { return w.id }
func (w *withId) Error() string { return w.err.Error() }
func (w *withId) Cause() error { return w.err }
func (w *withId) Unwrap() error { return w.err }
func (w *withId) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "%+v", w.Cause())
fmt.Fprintf(s, "\nerror id: %s", w.id)
return
}
fallthrough
case 's':
io.WriteString(s, w.Error())
case 'q':
fmt.Fprintf(s, "%q", w.Error())
}
}
func SetID(err error, id string) error {
if GetID(err) != "" {
return err
}
return &withId{err: err, id: id}
}
func GetID(err error) string {
for e := err; e != nil; e = Unwrap(e) {
if errID, ok := e.(ErrID); ok {
return errID.ID()
}
}
return ""
}
func WithID(err error) error {
if err == nil {
return nil
}
id := GetID(err)
if id == "" {
id = xid.New().String()
err = &withId{err: err, id: id}
}
return err
}
package errors
import (
"fmt"
"io"
)
type MultiError interface {
Errors() []error
Error() string
}
type withMultiError struct {
err error
errors []error
}
func (w *withMultiError) Errors() []error { return w.errors }
func (w *withMultiError) Error() string { return w.err.Error() }
func (w *withMultiError) Unwrap() error { return w.err }
func (w *withMultiError) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "%+v", w.Unwrap())
if len(w.errors) > 0 {
fmt.Fprint(s, "\ninclude errors:\n")
for _, e := range w.errors {
fmt.Fprintf(s, " %s\n", e)
}
}
return
}
fallthrough
case 's':
io.WriteString(s, w.Error())
case 'q':
fmt.Fprintf(s, "%q", w.Error())
}
}
func WithErrors(err error, errs ...error) error {
if err == nil || len(errs) == 0 {
return err
}
return &withMultiError{err: err, errors: errs}
}
func GetErrors(err error) []error {
for e := err; e != nil; e = Unwrap(e) {
if errMulti, ok := e.(MultiError); ok {
return errMulti.Errors()
}
}
return nil
}
package errors
import (
"fmt"
"io"
)
type ErrorSource struct {
Pointer string `json:"pointer,omitempty"`
Parameter string `json:"parameter,omitempty"`
Field string `json:"field,omitempty"`
}
func NewSource(args ...string) *ErrorSource {
s := &ErrorSource{}
if len(args) > 0 {
s.Pointer = args[0]
}
if len(args) > 1 {
s.Parameter = args[1]
}
if len(args) > 2 {
s.Field = args[2]
}
return s
}
type ErrSource interface{ Source() *ErrorSource }
type withSource struct {
err error
source *ErrorSource
}
func (w *withSource) Source() *ErrorSource { return w.source }
func (w *withSource) Error() string { return w.err.Error() }
func (w *withSource) Cause() error { return w.err }
func (w *withSource) Unwrap() error { return w.err }
func (w *withSource) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
fmt.Fprintf(s, "%+v", w.Cause())
fmt.Fprintf(s, "\nerror source: %+v", w.source)
return
}
fallthrough
case 's':
io.WriteString(s, w.Error())
case 'q':
fmt.Fprintf(s, "%q", w.Error())
}
}
func WithSource(err error, source *ErrorSource) error {
if err == nil {
return nil
}
return &withSource{err: err, source: source}
}
func GetSource(err error) *ErrorSource {
for e := err; e != nil; e = Unwrap(e) {
if errSource, ok := e.(ErrSource); ok {
return errSource.Source()
}
}
return nil
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment