add handler
parent
960176c863
commit
c0a27b8d1f
|
|
@ -0,0 +1,96 @@
|
||||||
|
version: "2"
|
||||||
|
|
||||||
|
run:
|
||||||
|
timeout: 5m
|
||||||
|
# tests: false # 过滤_test.go文件
|
||||||
|
build-tags:
|
||||||
|
- goexperiment.jsonv2
|
||||||
|
|
||||||
|
issues:
|
||||||
|
# 显示所有 issue
|
||||||
|
max-issues-per-linter: 0
|
||||||
|
max-same-issues: 0
|
||||||
|
|
||||||
|
formatters:
|
||||||
|
# 必须在enable打开才能用
|
||||||
|
enable:
|
||||||
|
- gofmt
|
||||||
|
- gci
|
||||||
|
|
||||||
|
settings:
|
||||||
|
gci:
|
||||||
|
sections:
|
||||||
|
- standard
|
||||||
|
- default
|
||||||
|
- prefix(git.ifooth.com/common/pkg/task)
|
||||||
|
custom-order: true
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
# enable by default
|
||||||
|
- errcheck
|
||||||
|
- govet
|
||||||
|
- ineffassign
|
||||||
|
- staticcheck
|
||||||
|
- unused
|
||||||
|
|
||||||
|
# custom
|
||||||
|
- goconst
|
||||||
|
- goheader
|
||||||
|
- gosec
|
||||||
|
- misspell
|
||||||
|
- nakedret
|
||||||
|
- revive
|
||||||
|
- unconvert
|
||||||
|
- unparam
|
||||||
|
- modernize
|
||||||
|
|
||||||
|
# 忽略特定错误
|
||||||
|
# exclusions:
|
||||||
|
# rules:
|
||||||
|
# - linters:
|
||||||
|
# - govet
|
||||||
|
# text: 'shadow: declaration of "err" shadows declaration'
|
||||||
|
|
||||||
|
settings:
|
||||||
|
# 只开启特定的规则
|
||||||
|
errcheck:
|
||||||
|
exclude-functions:
|
||||||
|
- (*os.File).Close
|
||||||
|
- (io.Closer).Close
|
||||||
|
- (net/http.ResponseWriter).Write
|
||||||
|
- io.Copy
|
||||||
|
- os.RemoveAll
|
||||||
|
govet:
|
||||||
|
enable:
|
||||||
|
- shadow
|
||||||
|
gosec:
|
||||||
|
includes:
|
||||||
|
- G201 # SQL query construction using format string
|
||||||
|
- G202 # SQL query construction using string concatenation
|
||||||
|
- G101 # Look for hard coded credentials
|
||||||
|
- G401 # Detect the usage of DES, RC4, MD5 or SHA1
|
||||||
|
- G402 # Look for bad TLS connection settings
|
||||||
|
- G403 # Ensure minimum RSA key length of 2048 bits
|
||||||
|
- G504 # Import blocklist: net/http/cgi
|
||||||
|
misspell:
|
||||||
|
locale: US
|
||||||
|
revive:
|
||||||
|
rules:
|
||||||
|
- name: line-length-limit
|
||||||
|
arguments:
|
||||||
|
- 120
|
||||||
|
- name: function-length
|
||||||
|
arguments:
|
||||||
|
- 80 # statements
|
||||||
|
- 80 # lines
|
||||||
|
- name: cyclomatic
|
||||||
|
arguments:
|
||||||
|
- 20
|
||||||
|
- name: use-any
|
||||||
|
- name: early-return
|
||||||
|
- name: exported
|
||||||
|
arguments:
|
||||||
|
- checkPrivateReceivers
|
||||||
|
- sayRepetitiveInsteadOfStutters
|
||||||
|
- name: package-comments
|
||||||
|
|
@ -18,7 +18,6 @@ import (
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"go.etcd.io/etcd/api/v3/mvccpb"
|
"go.etcd.io/etcd/api/v3/mvccpb"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,10 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
|
|
||||||
"github.com/RichardKnop/machinery/v2/config"
|
"github.com/RichardKnop/machinery/v2/config"
|
||||||
"github.com/RichardKnop/machinery/v2/tasks"
|
"github.com/RichardKnop/machinery/v2/tasks"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFindTaskKey(t *testing.T) {
|
func TestFindTaskKey(t *testing.T) {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,8 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/RichardKnop/machinery/v2/config"
|
||||||
|
|
||||||
"git.ifooth.com/common/pkg/task"
|
"git.ifooth.com/common/pkg/task"
|
||||||
etcdbackend "git.ifooth.com/common/pkg/task/backends/etcd"
|
etcdbackend "git.ifooth.com/common/pkg/task/backends/etcd"
|
||||||
etcdbroker "git.ifooth.com/common/pkg/task/brokers/etcd"
|
etcdbroker "git.ifooth.com/common/pkg/task/brokers/etcd"
|
||||||
|
|
@ -28,7 +30,6 @@ import (
|
||||||
istep "git.ifooth.com/common/pkg/task/steps/iface"
|
istep "git.ifooth.com/common/pkg/task/steps/iface"
|
||||||
mysqlstore "git.ifooth.com/common/pkg/task/stores/mysql"
|
mysqlstore "git.ifooth.com/common/pkg/task/stores/mysql"
|
||||||
"git.ifooth.com/common/pkg/task/types"
|
"git.ifooth.com/common/pkg/task/types"
|
||||||
"github.com/RichardKnop/machinery/v2/config"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
17
task/go.mod
17
task/go.mod
|
|
@ -2,10 +2,14 @@ module git.ifooth.com/common/pkg/task
|
||||||
|
|
||||||
go 1.25
|
go 1.25
|
||||||
|
|
||||||
|
replace git.ifooth.com/common/pkg => ../
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
git.ifooth.com/common/pkg v0.0.0-00010101000000-000000000000
|
||||||
github.com/RichardKnop/machinery/v2 v2.0.16
|
github.com/RichardKnop/machinery/v2 v2.0.16
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/prometheus/client_golang v1.20.5
|
github.com/prometheus/client_golang v1.20.5
|
||||||
|
github.com/samber/lo v1.52.0
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/urfave/cli v1.22.17
|
github.com/urfave/cli v1.22.17
|
||||||
go.etcd.io/etcd/api/v3 v3.6.6
|
go.etcd.io/etcd/api/v3 v3.6.6
|
||||||
|
|
@ -34,6 +38,13 @@ require (
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
|
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||||
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
|
github.com/go-playground/validator/v10 v10.23.0 // indirect
|
||||||
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
|
||||||
|
|
@ -47,6 +58,7 @@ require (
|
||||||
github.com/jstemmer/go-junit-report v0.9.1 // indirect
|
github.com/jstemmer/go-junit-report v0.9.1 // indirect
|
||||||
github.com/kelseyhightower/envconfig v1.4.0 // indirect
|
github.com/kelseyhightower/envconfig v1.4.0 // indirect
|
||||||
github.com/klauspost/compress v1.17.9 // indirect
|
github.com/klauspost/compress v1.17.9 // indirect
|
||||||
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/montanaflynn/stats v0.7.1 // indirect
|
github.com/montanaflynn/stats v0.7.1 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||||
|
|
@ -64,6 +76,11 @@ require (
|
||||||
go.etcd.io/etcd/client/pkg/v3 v3.6.6 // indirect
|
go.etcd.io/etcd/client/pkg/v3 v3.6.6 // indirect
|
||||||
go.mongodb.org/mongo-driver v1.17.0 // indirect
|
go.mongodb.org/mongo-driver v1.17.0 // indirect
|
||||||
go.opencensus.io v0.22.5 // indirect
|
go.opencensus.io v0.22.5 // indirect
|
||||||
|
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 // indirect
|
||||||
|
go.opentelemetry.io/otel v1.34.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/metric v1.34.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.34.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.27.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
golang.org/x/crypto v0.36.0 // indirect
|
golang.org/x/crypto v0.36.0 // indirect
|
||||||
|
|
|
||||||
19
task/go.sum
19
task/go.sum
|
|
@ -89,13 +89,26 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
|
||||||
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
|
||||||
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.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||||
|
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
|
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
|
github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o=
|
||||||
|
github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
|
@ -192,6 +205,8 @@ 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.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||||
|
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||||
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
|
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
|
||||||
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
|
|
@ -218,6 +233,8 @@ github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0t
|
||||||
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
|
github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw=
|
||||||
|
github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
|
|
@ -263,6 +280,8 @@ go.opencensus.io v0.22.5 h1:dntmOdLpSpHlVqbW5Eay97DelsZHe+55D+xC6i0dDS0=
|
||||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0 h1:9l89oX4ba9kHbBol3Xin3leYJ+252h0zszDtBwyKe2A=
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.52.0/go.mod h1:XLZfZboOJWHNKUv7eH0inh0E9VV6eWDFB/9yJyTLPp0=
|
||||||
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
||||||
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
||||||
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,418 @@
|
||||||
|
package task
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.ifooth.com/common/pkg/rest"
|
||||||
|
"git.ifooth.com/common/pkg/validator"
|
||||||
|
"github.com/samber/lo"
|
||||||
|
|
||||||
|
istore "git.ifooth.com/common/pkg/task/stores/iface"
|
||||||
|
"git.ifooth.com/common/pkg/task/types"
|
||||||
|
itypes "git.ifooth.com/common/pkg/task/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type service struct {
|
||||||
|
host string
|
||||||
|
routePrefix string
|
||||||
|
mgr *TaskManager
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// TaskStatusSlice ...
|
||||||
|
TaskStatusSlice = []string{
|
||||||
|
types.TaskStatusInit,
|
||||||
|
types.TaskStatusRunning,
|
||||||
|
types.TaskStatusSuccess,
|
||||||
|
types.TaskStatusFailure,
|
||||||
|
types.TaskStatusTimeout,
|
||||||
|
types.TaskStatusRevoked,
|
||||||
|
types.TaskStatusNotStarted,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewHandler(mgr *TaskManager, host string, routePrefix string) http.Handler {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
|
||||||
|
s := &service{
|
||||||
|
mgr: mgr,
|
||||||
|
host: host,
|
||||||
|
routePrefix: routePrefix,
|
||||||
|
}
|
||||||
|
|
||||||
|
// 任务管理
|
||||||
|
mux.HandleFunc("POST /api/v1/task/update", rest.Handle(s.Update))
|
||||||
|
mux.HandleFunc("POST /api/v1/task/retry", rest.Handle(s.Retry))
|
||||||
|
mux.HandleFunc("POST /api/v1/task/revoke", rest.Handle(s.Revoke))
|
||||||
|
mux.HandleFunc("GET /api/v1/task/status", rest.Handle(s.Status))
|
||||||
|
mux.HandleFunc("GET /api/v1/task/list", rest.Handle(s.List))
|
||||||
|
|
||||||
|
return mux
|
||||||
|
}
|
||||||
|
|
||||||
|
// Task bcs_task task with execution duration
|
||||||
|
type Task struct {
|
||||||
|
*itypes.Task
|
||||||
|
Steps []*Step `json:"steps,omitempty"`
|
||||||
|
ExecutionDuration time.Duration `json:"executionDuration" swaggertype:"string"`
|
||||||
|
MaxExecutionDuration time.Duration `json:"maxExecutionDuration" swaggertype:"string"`
|
||||||
|
DetailURL string `json:"detailURL,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step bcs_task step with execution duration
|
||||||
|
type Step struct {
|
||||||
|
*itypes.Step
|
||||||
|
ExecutionDuration time.Duration `json:"executionDuration" swaggertype:"string"`
|
||||||
|
MaxExecutionDuration time.Duration `json:"maxExecutionDuration" swaggertype:"string"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// StepReq ...
|
||||||
|
type StepReq struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Params *map[string]string `json:"params"`
|
||||||
|
Payload *string `json:"payload"`
|
||||||
|
RetryCount *uint32 `json:"retryCount"`
|
||||||
|
Status *string `json:"status"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate ...
|
||||||
|
func (s *StepReq) Validate() error {
|
||||||
|
if s.Status != nil && !lo.Contains(TaskStatusSlice, *s.Status) {
|
||||||
|
return fmt.Errorf("step status %s not valid", *s.Status)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateReq 请求参数
|
||||||
|
type UpdateReq struct {
|
||||||
|
TaskID string `json:"taskID" validate:"required"`
|
||||||
|
ResetStartTime bool `json:"resetStartTime"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
Steps []*StepReq `json:"steps"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate ...
|
||||||
|
func (r *UpdateReq) Validate() error {
|
||||||
|
if r.Status != "" && !lo.Contains(TaskStatusSlice, r.Status) {
|
||||||
|
return fmt.Errorf("task status %s not valid", r.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range r.Steps {
|
||||||
|
if err := v.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RetryReq 请求参数
|
||||||
|
type RetryReq struct {
|
||||||
|
TaskID string `json:"taskID" validate:"required"`
|
||||||
|
StepName string `json:"stepName"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update 更新任务
|
||||||
|
//
|
||||||
|
// @ID UpdateTask
|
||||||
|
// @Summary 更新任务
|
||||||
|
// @Description 更新任务
|
||||||
|
// @Tags 任务管理
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param request body UpdateReq true "task info"
|
||||||
|
// @Success 200 {object} rest.APIResponse{data=nil}
|
||||||
|
// @Failure 400
|
||||||
|
// @x-bk-apigateway {"isPublic": false, "appVerifiedRequired": true, "userVerifiedRequired": false}
|
||||||
|
// @Router /api/v1/remotedevenv/task/update [post]
|
||||||
|
func (s *service) Update(ctx context.Context, req *UpdateReq) (*rest.EmptyResp, error) {
|
||||||
|
if err := validator.Struct(ctx, req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
t, err := s.mgr.GetTaskWithID(ctx, req.TaskID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if req.ResetStartTime {
|
||||||
|
t.Start = time.Now()
|
||||||
|
}
|
||||||
|
if req.Status != "" {
|
||||||
|
t.Status = req.Status
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range req.Steps {
|
||||||
|
step, ok := t.GetStep(v.Name)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("step %s not found", v.Name)
|
||||||
|
}
|
||||||
|
if v.Params != nil {
|
||||||
|
step.Params = *v.Params
|
||||||
|
}
|
||||||
|
if v.RetryCount != nil {
|
||||||
|
step.RetryCount = *v.RetryCount
|
||||||
|
}
|
||||||
|
if v.Status != nil {
|
||||||
|
step.Status = *v.Status
|
||||||
|
}
|
||||||
|
if v.Payload != nil {
|
||||||
|
body, err := base64.StdEncoding.DecodeString(*v.Payload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
step.Payload = string(body)
|
||||||
|
}
|
||||||
|
|
||||||
|
t.SetCurrentStep(v.Name)
|
||||||
|
// 只更新DB
|
||||||
|
if err := s.mgr.UpdateTask(ctx, t); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := &rest.EmptyResp{}
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retry 重试任务
|
||||||
|
//
|
||||||
|
// @ID RetryTask
|
||||||
|
// @Summary 重试任务
|
||||||
|
// @Description 重试任务
|
||||||
|
// @Tags 任务管理,clouddev,cloudpc
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param request body RetryReq true "task info"
|
||||||
|
// @Success 200 {object} rest.APIResponse{data=nil}
|
||||||
|
// @Failure 400
|
||||||
|
// @x-bk-apigateway {"isPublic": false, "appVerifiedRequired": true, "userVerifiedRequired": false}
|
||||||
|
// @Router /api/v1/remotedevenv/task/retry [post]
|
||||||
|
func (s *service) Retry(ctx context.Context, req *RetryReq) (*rest.EmptyResp, error) {
|
||||||
|
if err := validator.Struct(ctx, req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
t, err := s.mgr.GetTaskWithID(ctx, req.TaskID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := &rest.EmptyResp{}
|
||||||
|
|
||||||
|
if t.Status != itypes.TaskStatusFailure &&
|
||||||
|
t.Status != itypes.TaskStatusRevoked &&
|
||||||
|
t.Status != itypes.TaskStatusTimeout {
|
||||||
|
return nil, fmt.Errorf("task %s already in process %s", req.TaskID, t.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
if t.Status == itypes.TaskStatusTimeout {
|
||||||
|
t.Start = time.Now()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 只重试单步骤
|
||||||
|
if req.StepName != "" {
|
||||||
|
step, ok := t.GetStep(req.StepName)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("step %s not found", req.StepName)
|
||||||
|
}
|
||||||
|
if step.Status == itypes.TaskStatusSuccess {
|
||||||
|
return nil, fmt.Errorf("step %s already success", req.StepName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if step.Status == itypes.TaskStatusFailure {
|
||||||
|
step.RetryCount = 0
|
||||||
|
step.Status = itypes.TaskStatusNotStarted
|
||||||
|
}
|
||||||
|
t.SetCurrentStep(req.StepName)
|
||||||
|
if err := s.mgr.RetryAt(t, req.StepName); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 全量重试必须有失败的任务
|
||||||
|
notSuccessStep := lo.Filter(t.Steps, func(v *itypes.Step, _ int) bool {
|
||||||
|
return v.Status != itypes.TaskStatusSuccess
|
||||||
|
})
|
||||||
|
if len(notSuccessStep) == 0 {
|
||||||
|
return nil, fmt.Errorf("task %s all step already success", req.TaskID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 错误步骤重试次数置为0, 只当前步骤有效
|
||||||
|
for _, step := range t.Steps {
|
||||||
|
if step.Status == itypes.TaskStatusFailure {
|
||||||
|
step.RetryCount = 0
|
||||||
|
step.Status = itypes.TaskStatusNotStarted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 任务级重试
|
||||||
|
if err := s.mgr.RetryAll(t); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// commonReq 任务请求参数
|
||||||
|
type commonReq struct {
|
||||||
|
TaskID string `json:"taskID" in:"query=taskID" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Revoke 取消任务
|
||||||
|
//
|
||||||
|
// @ID RevokeTask
|
||||||
|
// @Summary 取消任务
|
||||||
|
// @Description 取消任务
|
||||||
|
// @Tags 任务管理,clouddev,cloudpc
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param request body commonReq true "common info"
|
||||||
|
// @Success 200 {object} rest.APIResponse{data=nil}
|
||||||
|
// @Failure 400
|
||||||
|
// @x-bk-apigateway {"isPublic": false, "appVerifiedRequired": true, "userVerifiedRequired": false}
|
||||||
|
// @Router /api/v1/remotedevenv/task/revoke [post]
|
||||||
|
func (s *service) Revoke(ctx context.Context, req *commonReq) (*rest.EmptyResp, error) {
|
||||||
|
if err := validator.Struct(ctx, req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
t, err := s.mgr.GetTaskWithID(ctx, req.TaskID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if t.Status != itypes.TaskStatusRunning {
|
||||||
|
return nil, fmt.Errorf("task %s not running", req.TaskID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.mgr.Revoke(t); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &rest.EmptyResp{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status 任务状态
|
||||||
|
//
|
||||||
|
// @ID TaskStatus
|
||||||
|
// @Summary 任务状态
|
||||||
|
// @Description 获取任务状态
|
||||||
|
// @Tags 任务管理,clouddev,cloudpc
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param taskID query string true "task id"
|
||||||
|
// @Success 200 {object} rest.APIResponse{data=Task}
|
||||||
|
// @Failure 400
|
||||||
|
// @x-bk-apigateway {"isPublic": false, "appVerifiedRequired": true, "userVerifiedRequired": false}
|
||||||
|
// @Router /api/v1/remotedevenv/task/status [get]
|
||||||
|
func (s *service) Status(ctx context.Context, req *commonReq) (*Task, error) {
|
||||||
|
if err := validator.Struct(ctx, req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
taskData, err := s.mgr.GetTaskWithID(ctx, req.TaskID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
steps := lo.Map(taskData.Steps, func(v *itypes.Step, _ int) *Step {
|
||||||
|
return &Step{
|
||||||
|
Step: v,
|
||||||
|
ExecutionDuration: time.Duration(v.ExecutionTime) * time.Millisecond,
|
||||||
|
MaxExecutionDuration: time.Duration(v.MaxExecutionSeconds) * time.Second,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t := &Task{
|
||||||
|
Task: taskData,
|
||||||
|
Steps: steps,
|
||||||
|
ExecutionDuration: time.Duration(taskData.ExecutionTime) * time.Millisecond,
|
||||||
|
MaxExecutionDuration: time.Duration(taskData.MaxExecutionSeconds) * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
return t, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListReq ...
|
||||||
|
type ListReq struct {
|
||||||
|
rest.PaginationReq
|
||||||
|
TaskID string `json:"taskID" in:"query=taskID"`
|
||||||
|
TaskType string `json:"taskType" in:"query=taskType"`
|
||||||
|
TaskName string `json:"taskName" in:"query=taskName"`
|
||||||
|
TaskIndex string `json:"taskIndex" in:"query=taskIndex"`
|
||||||
|
CurrentStep string `json:"currentStep" in:"query=currentStep"`
|
||||||
|
Status string `json:"status" in:"query=status" validate:"oneof='' SUCCESS FAILURE RUNNING TIMEOUT REVOKED NOTSTARTED INITIALIZING"` // nolint
|
||||||
|
Creator string `json:"creator" in:"query=creator"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// List 任务分页列表
|
||||||
|
//
|
||||||
|
// @ID ListTask
|
||||||
|
// @Summary 任务列表
|
||||||
|
// @Description 获取任务列表
|
||||||
|
// @Tags 任务管理
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param offset query int false "offset"
|
||||||
|
// @Param limit query int false "limit"
|
||||||
|
// @Param taskID query string false "task id"
|
||||||
|
// @Param taskType query string false "task type"
|
||||||
|
// @Param taskName query string false "task name"
|
||||||
|
// @Param taskIndex query string false "task id"
|
||||||
|
// @Param currentStep query string false "current step"
|
||||||
|
// @Param status query string false "status"
|
||||||
|
// @Param creator query string false "creator"
|
||||||
|
// @Success 200 {object} rest.APIResponse{data=rest.PaginationResp[Task]}
|
||||||
|
// @Failure 400
|
||||||
|
// @x-bk-apigateway {"isPublic": false, "appVerifiedRequired": true, "userVerifiedRequired": false}
|
||||||
|
// @Router /api/v1/task/list [get]
|
||||||
|
func (s *service) List(ctx context.Context, req *ListReq) (*rest.PaginationResp[Task], error) {
|
||||||
|
if err := validator.Struct(ctx, req); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
statusURL := "/api/v1/task/status"
|
||||||
|
detailURL, err := url.JoinPath(s.host, s.routePrefix, statusURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// 默认返回20条数据
|
||||||
|
if req.Limit == 0 {
|
||||||
|
req.Limit = 20
|
||||||
|
}
|
||||||
|
|
||||||
|
listReq := &istore.ListOption{
|
||||||
|
TaskID: req.TaskID,
|
||||||
|
TaskType: req.TaskType,
|
||||||
|
TaskName: req.TaskName,
|
||||||
|
TaskIndex: req.TaskIndex,
|
||||||
|
CurrentStep: req.CurrentStep,
|
||||||
|
Status: req.Status,
|
||||||
|
Creator: req.Creator,
|
||||||
|
Limit: int64(req.Limit),
|
||||||
|
Offset: int64(req.Offset),
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := s.mgr.ListTask(ctx, listReq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
items := lo.Map(result.Items, func(v *itypes.Task, _ int) Task {
|
||||||
|
return Task{
|
||||||
|
Task: v,
|
||||||
|
ExecutionDuration: time.Duration(v.ExecutionTime) * time.Millisecond,
|
||||||
|
MaxExecutionDuration: time.Duration(v.MaxExecutionSeconds) * time.Second,
|
||||||
|
DetailURL: fmt.Sprintf("%s?taskID=%s", detailURL, v.TaskID),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
resp := &rest.PaginationResp[Task]{
|
||||||
|
Items: items,
|
||||||
|
Count: result.Count,
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue