Compare commits

...

6 Commits

Author SHA1 Message Date
douxu 5a9fa5cc4d write code for polling real time data from dataRT service 2024-12-26 15:03:20 +08:00
douxu 39e380ee1e optimize demo code 2024-12-25 16:34:57 +08:00
douxu c3f7ddf210 optimize demo code 2024-12-23 14:47:22 +08:00
douxu f8b9a70250 add replace anchor point api and optimize code of anchor param data polling function points 2024-12-20 16:06:42 +08:00
douxu efc15c3b2d wirte demo code 2024-12-18 16:25:49 +08:00
douxu a611c08c20 init modelRT show demo 2024-12-16 15:37:44 +08:00
28 changed files with 763 additions and 149 deletions

View File

@ -0,0 +1,59 @@
// Package config define config struct of model runtime service
package config
import (
"modelRT/constant"
)
// AnchorParamListConfig define anchor params list config struct
type AnchorParamListConfig struct {
AnchorName string
FuncType string // 函数类型
UpperLimit float64 // 比较值上限
LowerLimit float64 // 比较值下限
}
// AnchorParamBaseConfig define anchor params base config struct
type AnchorParamBaseConfig struct {
StationID string // component表 station_id
ComponentID string // component表 ID
UUID string // component表 global_uuid
AnchorName string // 锚定参量名称
CompareValUpperLimit float64 // 比较值上限
CompareValLowerLimit float64 // 比较值下限
}
// AnchorParamConfig define anchor params config struct
type AnchorParamConfig struct {
AnchorParamBaseConfig
CalculateFunc func(archorValue float64, args ...float64) float64 // 计算函数
CalculateParams []float64 // 计算参数
APIURL string // API URL
APIMethod string // API Method
}
var baseVoltageFunc = func(archorValue float64, args ...float64) float64 {
voltage := archorValue
resistance := args[1]
return voltage / resistance
}
var baseCurrentFunc = func(archorValue float64, args ...float64) float64 {
current := archorValue
resistance := args[1]
return current * resistance
}
// SelectAnchorCalculateFuncAndParams define select anchor func and anchor calculate value by component type 、 anchor name and component data
func SelectAnchorCalculateFuncAndParams(componentType int, anchorName string, componentData map[string]interface{}) (func(archorValue float64, args ...float64) float64, []float64) {
if componentType == constant.DemoType {
if anchorName == "voltage" {
resistance := componentData["resistance"].(float64)
return baseVoltageFunc, []float64{resistance}
} else if anchorName == "current" {
resistance := componentData["resistance"].(float64)
return baseCurrentFunc, []float64{resistance}
}
}
return nil, []float64{}
}

View File

@ -45,7 +45,16 @@ type LoggerConfig struct {
// AntsConfig define config stuct of ants pool config
type AntsConfig struct {
ParseConcurrentQuantity int `mapstructure:"parse_concurrent_quantity"` // parse comtrade file concurrent quantity
ParseConcurrentQuantity int `mapstructure:"parse_concurrent_quantity"` // parse comtrade file concurrent quantity
PollingConcurrentQuantity int `mapstructure:"polling_concurrent_quantity"` // polling real time data concurrent quantity
}
// DataRTConfig define config stuct of data runtime server api config
type DataRTConfig struct {
Host string `mapstructure:"host"`
Port int64 `mapstructure:"port"`
PollingAPI string `mapstructure:"polling_api"`
Method string `mapstructure:"polling_api_method"`
}
// ModelRTConfig define config stuct of model runtime server
@ -55,6 +64,7 @@ type ModelRTConfig struct {
KafkaConfig `mapstructure:"kafka"`
LoggerConfig `mapstructure:"logger"`
AntsConfig `mapstructure:"ants"`
DataRTConfig `mapstructure:"dataRT"`
PostgresDBURI string `mapstructure:"-"`
}
@ -71,12 +81,12 @@ func ReadAndInitConfig(configDir, configName, configType string) (modelRTConfig
panic(err)
}
rtConfig := ModelRTConfig{}
if err := config.Unmarshal(&rtConfig); err != nil {
modelRTconf := ModelRTConfig{}
if err := config.Unmarshal(&modelRTConfig); err != nil {
panic(fmt.Sprintf("unmarshal modelRT config failed:%s\n", err.Error()))
}
modelRTConfig.PostgresDBURI = fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s", rtConfig.Host, rtConfig.Port, rtConfig.User, rtConfig.Password, rtConfig.DataBase)
modelRTConfig.PostgresDBURI = fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s", modelRTconf.PostgresConfig.Host, modelRTconf.PostgresConfig.Port, modelRTconf.PostgresConfig.User, modelRTconf.PostgresConfig.Password, modelRTconf.PostgresConfig.DataBase)
return modelRTConfig
}

View File

@ -33,9 +33,17 @@ logger:
# ants config
ants:
parse_concurrent_quantity: 10
polling_concurrent_quantity: 10
# modelRT base config
base:
grid_id: 1
zone_id: 1
station_id: 1
# dataRT api config
dataRT:
host: "http://127.0.0.1"
port: 8888
polling_api: "datart/getPointData"
polling_api_method: "GET"

View File

@ -10,4 +10,5 @@ import (
type ModelParseConfig struct {
ComponentInfo orm.Component
Context context.Context
AnchorChan chan AnchorParamConfig
}

View File

@ -8,4 +8,6 @@ const (
BusbarType
// AsyncMotorType 异步电动机类型
AsyncMotorType
// DemoType Demo类型
DemoType
)

View File

@ -11,6 +11,9 @@ var ErrUpdateRowZero = errors.New("update affected rows is zero")
// ErrDeleteRowZero define error of delete affected row zero
var ErrDeleteRowZero = errors.New("delete affected rows is zero")
// ErrQueryRowZero define error of query affected row zero
var ErrQueryRowZero = errors.New("query affected rows is zero")
// ErrInsertRowUnexpected define error of insert affected row not reach expected number
var ErrInsertRowUnexpected = errors.New("the number of inserted data rows don't reach the expected value")

41
diagram/anchor_set.go Normal file
View File

@ -0,0 +1,41 @@
package diagram
import (
"errors"
"fmt"
"sync"
)
// anchorValueOverview define struct of storage all anchor value
var anchorValueOverview sync.Map
// GetAnchorValue define func of get circuit diagram data by global uuid
func GetAnchorValue(uuid string) (string, error) {
value, ok := diagramsOverview.Load(uuid)
if !ok {
return "", fmt.Errorf("can not find anchor value by global uuid:%s", uuid)
}
anchorValue, ok := value.(string)
if !ok {
return "", errors.New("convert to string failed")
}
return anchorValue, nil
}
// UpdateAnchorValue define func of update anchor value by global uuid and anchor name
func UpdateAnchorValue(uuid string, anchorValue string) bool {
_, result := anchorValueOverview.Swap(uuid, anchorValue)
return result
}
// StoreAnchorValue define func of store anchor value with global uuid and anchor name
func StoreAnchorValue(uuid string, anchorValue string) {
anchorValueOverview.Store(uuid, anchorValue)
return
}
// DeleteAnchorValue define func of delete anchor value with global uuid
func DeleteAnchorValue(uuid string) {
anchorValueOverview.Delete(uuid)
return
}

View File

@ -4,20 +4,18 @@ import (
"errors"
"fmt"
"sync"
cmap "github.com/orcaman/concurrent-map/v2"
)
// DiagramsOverview define struct of storage all circuit diagram data
// diagramsOverview define struct of storage all circuit diagram data
var diagramsOverview sync.Map
// GetComponentMap define func of get circuit diagram data by global uuid
func GetComponentMap(uuid string) (*cmap.ConcurrentMap[string, any], error) {
func GetComponentMap(uuid string) (map[string]interface{}, error) {
value, ok := diagramsOverview.Load(uuid)
if !ok {
return nil, fmt.Errorf("can not find graph by global uuid:%s", uuid)
}
paramsMap, ok := value.(*cmap.ConcurrentMap[string, any])
paramsMap, ok := value.(map[string]interface{})
if !ok {
return nil, errors.New("convert to component map struct failed")
}
@ -25,13 +23,13 @@ func GetComponentMap(uuid string) (*cmap.ConcurrentMap[string, any], error) {
}
// UpdateComponentMap define func of update circuit diagram data by global uuid and component info
func UpdateComponentMap(uuid string, componentInfo *cmap.ConcurrentMap[string, any]) bool {
func UpdateComponentMap(uuid string, componentInfo map[string]interface{}) bool {
_, result := diagramsOverview.Swap(uuid, componentInfo)
return result
}
// StoreComponentMap define func of store circuit diagram data with global uuid and component info
func StoreComponentMap(uuid string, componentInfo *cmap.ConcurrentMap[string, any]) {
func StoreComponentMap(uuid string, componentInfo map[string]interface{}) {
diagramsOverview.Store(uuid, componentInfo)
return
}

View File

@ -6,7 +6,7 @@ import (
"sync"
)
// GraphOverview define struct of storage all circuit diagram topologic data
// graphOverview define struct of storage all circuit diagram topologic data
var graphOverview sync.Map
// GetGraphMap define func of get circuit diagram topologic data by pageID

View File

@ -0,0 +1,13 @@
{
"params_list": [{
"anchor_name": "voltage",
"func_type": "1",
"upper_limit": 23,
"lower_limit": 0.5
}, {
"anchor_name": "current",
"func_type": "2",
"upper_limit": 23,
"lower_limit": 0.5
}]
}

17
go.mod
View File

@ -3,14 +3,17 @@ module modelRT
go 1.22.5
require (
github.com/bitly/go-simplejson v0.5.1
github.com/confluentinc/confluent-kafka-go v1.9.2
github.com/gin-gonic/gin v1.10.0
github.com/gofrs/uuid v4.4.0+incompatible
github.com/json-iterator/go v1.1.12
github.com/natefinch/lumberjack v2.0.0+incompatible
github.com/orcaman/concurrent-map/v2 v2.0.1
github.com/panjf2000/ants/v2 v2.10.0
github.com/spf13/viper v1.19.0
github.com/swaggo/files v1.0.1
github.com/swaggo/gin-swagger v1.6.0
github.com/swaggo/swag v1.16.4
go.uber.org/zap v1.27.0
gorm.io/driver/postgres v1.5.9
gorm.io/gorm v1.25.12
@ -19,13 +22,10 @@ require (
require (
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/PuerkitoBio/purell v1.2.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/bytedance/sonic v1.12.5 // indirect
github.com/bytedance/sonic/loader v0.2.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.7 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
@ -54,22 +54,15 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/swaggo/files v1.0.1 // indirect
github.com/swaggo/gin-swagger v1.6.0 // indirect
github.com/swaggo/swag v1.16.4 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/urfave/cli/v2 v2.27.5 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
go.uber.org/multierr v1.10.0 // indirect
golang.org/x/arch v0.12.0 // indirect
golang.org/x/crypto v0.30.0 // indirect
@ -82,7 +75,5 @@ require (
google.golang.org/protobuf v1.35.2 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)

63
go.sum
View File

@ -5,19 +5,14 @@ github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/PuerkitoBio/purell v1.2.1 h1:QsZ4TjvwiMpat6gBCBxEQI0rcS9ehtkKtSpiUnd9N28=
github.com/PuerkitoBio/purell v1.2.1/go.mod h1:ZwHcC/82TOaovDi//J/804umJFFmbOHPngi8iYYv/Eo=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/actgardner/gogen-avro/v10 v10.1.0/go.mod h1:o+ybmVjEa27AAr35FRqU98DJu1fXES56uXniYFv4yDA=
github.com/actgardner/gogen-avro/v10 v10.2.1/go.mod h1:QUhjeHPchheYmMDni/Nx7VB0RsT/ee8YIgGY/xpEQgQ=
github.com/actgardner/gogen-avro/v9 v9.1.0/go.mod h1:nyTj6wPqDJoxM3qdnjcLv+EnMDSDFqE0qDpva2QRmKc=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/bitly/go-simplejson v0.5.1 h1:xgwPbetQScXt1gh9BmoJ6j9JMr3TElvuIyjR8pgdoow=
github.com/bitly/go-simplejson v0.5.1/go.mod h1:YOPVLzCfwK14b4Sff3oP1AmGhI9T9Vsg84etUnlyp+Q=
github.com/bytedance/sonic v1.12.5 h1:hoZxY8uW+mT+OpkcUWw4k0fDINtOcVavEsGfzwzFU/w=
github.com/bytedance/sonic v1.12.5/go.mod h1:B8Gt/XvtZ3Fqj+iSKMypzymZxw/FVwgIGKzMzT9r/rk=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/bytedance/sonic/loader v0.2.1 h1:1GgorWTqf12TA8mma4DDSbaQigE2wOgQo7iCjjJv3+E=
github.com/bytedance/sonic/loader v0.2.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
@ -39,8 +34,6 @@ github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/confluentinc/confluent-kafka-go v1.9.2 h1:gV/GxhMBUb03tFWkN+7kdhg+zf+QUM+wVkI9zwh770Q=
github.com/confluentinc/confluent-kafka-go v1.9.2/go.mod h1:ptXNqsuDfYbAE/LBW6pnwWZElUoWxHoV8E43DCrliyo=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
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=
@ -61,11 +54,11 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
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/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/gabriel-vasile/mimetype v1.4.7 h1:SKFKl7kD0RiPdbht0s7hFtjl489WcQ1VyPW8ZzUMYCA=
github.com/gabriel-vasile/mimetype v1.4.7/go.mod h1:GDlAgAyIRT27BhFl53XNAFtfjzOkLaF35JdEG0P7LtU=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
@ -84,12 +77,8 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
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.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
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/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
@ -120,8 +109,8 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20211008130755-947d60d73cc0/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -159,8 +148,6 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
github.com/juju/qthttptest v0.1.1/go.mod h1:aTlAv8TYaflIiTDIQYzxnl1QdPjAg8Q8qJMErpKy6A4=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
@ -197,12 +184,8 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
github.com/nrwiersma/avro-benchmarks v0.0.0-20210913175520-21aec48c8f76/go.mod h1:iKyFMidsk/sVYONJRE372sJuX/QTRPacU7imPqqsu7g=
github.com/orcaman/concurrent-map/v2 v2.0.1 h1:jOJ5Pg2w1oeB6PeDurIYf6k9PQ+aTITr/6lP/L/zp6c=
github.com/orcaman/concurrent-map/v2 v2.0.1/go.mod h1:9Eq3TG2oBe5FirmYWQfYO5iH1q0Jv47PLaNK++uCdOM=
github.com/panjf2000/ants/v2 v2.10.0 h1:zhRg1pQUtkyRiOFo2Sbqwjp0GfBNo9cUY2/Grpx1p+8=
github.com/panjf2000/ants/v2 v2.10.0/go.mod h1:7ZxyxsqE4vvW0M7LSD8aI3cKwgFhBHbxnlN8mDqHa1I=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
@ -214,17 +197,13 @@ github.com/rogpeppe/clock v0.0.0-20190514195947-2896927a307a/go.mod h1:4r5QyqhjI
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
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/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
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/santhosh-tekuri/jsonschema/v5 v5.0.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0=
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
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=
@ -238,7 +217,6 @@ github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+
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/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
@ -247,7 +225,6 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
@ -262,10 +239,6 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
@ -275,17 +248,12 @@ go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/arch v0.12.0 h1:UsYJhbzPYGsT0HbEdmYcqtCv8UNGvnaL561NnIUvaKg=
golang.org/x/arch v0.12.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
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.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.30.0 h1:RwoQn3GkWiMkzlX562cLB7OxWvjH1L8xutO2WoJcRoY=
golang.org/x/crypto v0.30.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -296,6 +264,8 @@ golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvx
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
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=
@ -312,8 +282,6 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -326,8 +294,6 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -345,8 +311,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
@ -358,8 +322,6 @@ 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/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -404,8 +366,6 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
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/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
gopkg.in/avro.v0 v0.0.0-20171217001914-a730b5802183/go.mod h1:FvqrFXt+jCsyQibeRv4xxEJBL5iG2DDW5aeJwzDiq4A=
@ -440,6 +400,3 @@ gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
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=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=

View File

@ -0,0 +1,161 @@
package handler
import (
"context"
"fmt"
"net/http"
"strconv"
"time"
"modelRT/config"
"modelRT/constant"
"modelRT/database"
"modelRT/diagram"
"modelRT/logger"
"modelRT/model"
"modelRT/network"
"modelRT/orm"
realtimedata "modelRT/real-time-data"
"github.com/bitly/go-simplejson"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
)
// ComponentAnchorReplaceHandler define component anchor point replace process API
func ComponentAnchorReplaceHandler(c *gin.Context) {
var uuid, anchorName string
logger := logger.GetLoggerInstance()
pgClient := database.GetPostgresDBClient()
cancelCtx, cancel := context.WithTimeout(c, 5*time.Second)
defer cancel()
var request network.ComponetAnchorReplaceRequest
if err := c.ShouldBindJSON(&request); err != nil {
logger.Error("unmarshal component anchor point replace info failed", zap.Error(err))
header := network.FailResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()}
resp := network.FailureResponse{
FailResponseHeader: header,
}
c.JSON(http.StatusOK, resp)
return
}
uuid = request.UUID
anchorName = request.AnchorName
var componentInfo orm.Component
result := pgClient.WithContext(cancelCtx).Model(&orm.Component{}).Where("global_uuid = ?", uuid).Find(&componentInfo)
if result.Error != nil {
logger.Error("query component detail info failed", zap.Error(result.Error))
header := network.FailResponseHeader{Status: http.StatusBadRequest, ErrMsg: result.Error.Error()}
resp := network.FailureResponse{
FailResponseHeader: header,
}
c.JSON(http.StatusOK, resp)
return
}
if result.RowsAffected == 0 {
err := fmt.Errorf("query component detail info by uuid failed:%w", constant.ErrQueryRowZero)
logger.Error("query component detail info from table is empty", zap.String("table_name", "component"))
header := network.FailResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()}
resp := network.FailureResponse{
FailResponseHeader: header,
}
c.JSON(http.StatusOK, resp)
return
}
cancelCtx, cancel = context.WithTimeout(c, 5*time.Second)
defer cancel()
unmarshalMap := make(map[string]interface{})
tableName := model.SelectModelNameByType(componentInfo.ComponentType)
result = pgClient.WithContext(cancelCtx).Table(tableName).Where("global_uuid = ?", uuid).Find(&unmarshalMap)
if result.Error != nil {
logger.Error("query model detail info failed", zap.Error(result.Error))
header := network.FailResponseHeader{Status: http.StatusBadRequest, ErrMsg: result.Error.Error()}
resp := network.FailureResponse{
FailResponseHeader: header,
}
c.JSON(http.StatusOK, resp)
return
}
if unmarshalMap == nil {
err := fmt.Errorf("query model detail info by uuid failed:%w", constant.ErrQueryRowZero)
logger.Error("query model detail info from table is empty", zap.String("table_name", tableName))
header := network.FailResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()}
resp := network.FailureResponse{
FailResponseHeader: header,
}
c.JSON(http.StatusOK, resp)
return
}
configsStr, exist := unmarshalMap["anchor_configs_list"]
if !exist {
logger.Error("can not find anchor config list in model model detail info")
header := network.FailResponseHeader{Status: http.StatusBadRequest, ErrMsg: "can not find anchor config list in model model detail info"}
resp := network.FailureResponse{
FailResponseHeader: header,
}
c.JSON(http.StatusOK, resp)
return
}
anchorConfigsJSON, err := simplejson.NewJson([]byte(configsStr.(string)))
if err != nil {
logger.Error("formmat anchor configs json failed", zap.Error(err))
header := network.FailResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()}
resp := network.FailureResponse{
FailResponseHeader: header,
}
c.JSON(http.StatusOK, resp)
return
}
var existFlag bool
var anchorIndex int
paramsList := anchorConfigsJSON.Get("params_list").MustArray()
for index := range paramsList {
paramAnchorName := anchorConfigsJSON.Get("params_list").GetIndex(index).Get("anchor_name").MustString()
if anchorName == paramAnchorName {
existFlag = true
anchorIndex = index
}
}
if !existFlag {
header := network.FailResponseHeader{Status: http.StatusBadRequest, ErrMsg: "can not find new anchor name in model anchor point list"}
resp := network.FailureResponse{
FailResponseHeader: header,
}
c.JSON(http.StatusOK, resp)
return
}
diagram.UpdateAnchorValue(uuid, anchorName)
anchorParam := config.AnchorParamConfig{
AnchorParamBaseConfig: config.AnchorParamBaseConfig{
StationID: strconv.FormatInt(componentInfo.StationID, 10),
ComponentID: strconv.FormatInt(componentInfo.ID, 10),
UUID: uuid,
AnchorName: anchorName,
CompareValUpperLimit: anchorConfigsJSON.Get("params_list").GetIndex(anchorIndex).Get("upper_limit").MustFloat64(),
CompareValLowerLimit: anchorConfigsJSON.Get("params_list").GetIndex(anchorIndex).Get("lower_limit").MustFloat64(),
},
}
anchorParam.CalculateFunc, anchorParam.CalculateParams = config.SelectAnchorCalculateFuncAndParams(componentInfo.ComponentType, anchorName, unmarshalMap)
realtimedata.AnchorParamsChan <- anchorParam
resp := network.SuccessResponse{
SuccessResponseHeader: network.SuccessResponseHeader{Status: http.StatusOK},
PayLoad: map[string]interface{}{
"uuid": request.UUID,
},
}
c.JSON(http.StatusOK, resp)
}

View File

@ -6,18 +6,18 @@ import (
"modelRT/database"
"modelRT/diagram"
"modelRT/log"
"modelRT/logger"
"modelRT/network"
"github.com/bitly/go-simplejson"
"github.com/gin-gonic/gin"
"github.com/gofrs/uuid"
cmap "github.com/orcaman/concurrent-map/v2"
"go.uber.org/zap"
)
// CircuitDiagramCreateHandler define circuit diagram create process API
func CircuitDiagramCreateHandler(c *gin.Context) {
logger := log.GetLoggerInstance()
logger := logger.GetLoggerInstance()
pgClient := database.GetPostgresDBClient()
var request network.CircuitDiagramCreateRequest
@ -131,10 +131,9 @@ func CircuitDiagramCreateHandler(c *gin.Context) {
}
for _, componentInfo := range request.ComponentInfos {
componentMap := cmap.New[any]()
err = componentMap.UnmarshalJSON([]byte(componentInfo.Params))
paramsJSON, err := simplejson.NewJson([]byte(componentInfo.Params))
if err != nil {
logger.Error("unmarshal component info by concurrent map failed", zap.String("component_params", componentInfo.Params), zap.Error(err))
logger.Error("unmarshal component params info failed", zap.String("component_params", componentInfo.Params), zap.Error(err))
header := network.FailResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()}
resp := network.FailureResponse{
FailResponseHeader: header,
@ -146,7 +145,22 @@ func CircuitDiagramCreateHandler(c *gin.Context) {
c.JSON(http.StatusOK, resp)
return
}
diagram.StoreComponentMap(componentInfo.UUID, &componentMap)
componentMap, err := paramsJSON.Map()
if err != nil {
logger.Error("format params json info to map failed", zap.Error(err))
header := network.FailResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()}
resp := network.FailureResponse{
FailResponseHeader: header,
PayLoad: map[string]interface{}{
"uuid": componentInfo.UUID,
"component_params": componentInfo.Params,
},
}
c.JSON(http.StatusOK, resp)
return
}
diagram.StoreComponentMap(componentInfo.UUID, componentMap)
}
if len(request.FreeVertexs) > 0 {

View File

@ -9,7 +9,7 @@ import (
"modelRT/constant"
"modelRT/database"
"modelRT/diagram"
"modelRT/log"
"modelRT/logger"
"modelRT/model"
"modelRT/network"
"modelRT/orm"
@ -21,7 +21,7 @@ import (
// CircuitDiagramDeleteHandler define circuit diagram delete process API
func CircuitDiagramDeleteHandler(c *gin.Context) {
logger := log.GetLoggerInstance()
logger := logger.GetLoggerInstance()
pgClient := database.GetPostgresDBClient()
var request network.CircuitDiagramDeleteRequest

View File

@ -5,7 +5,7 @@ import (
"strconv"
"modelRT/diagram"
"modelRT/log"
"modelRT/logger"
"modelRT/network"
"github.com/gin-gonic/gin"
@ -23,7 +23,7 @@ import (
// @Failure 400 {object} network.FailureResponse "request process failed"
// @Router /model/diagram_load/{page_id} [get]
func CircuitDiagramLoadHandler(c *gin.Context) {
logger := log.GetLoggerInstance()
logger := logger.GetLoggerInstance()
pageID, err := strconv.ParseInt(c.Query("page_id"), 10, 64)
if err != nil {
logger.Error("get pageID from url param failed", zap.Error(err))
@ -55,7 +55,7 @@ func CircuitDiagramLoadHandler(c *gin.Context) {
payLoad["root_vertex"] = topologicInfo.RootVertex
payLoad["topologic"] = topologicInfo.VerticeLinks
componentParamMap := make(map[string][]byte)
componentParamMap := make(map[string]any)
for _, VerticeLink := range topologicInfo.VerticeLinks {
for _, componentUUID := range VerticeLink {
UUIDStr := componentUUID.String()
@ -72,17 +72,7 @@ func CircuitDiagramLoadHandler(c *gin.Context) {
c.JSON(http.StatusOK, resp)
return
}
byteSlice, err := componentParams.MarshalJSON()
if err != nil {
logger.Error("marshal component data failed", zap.Error(err))
header := network.FailResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()}
resp := network.FailureResponse{
FailResponseHeader: header,
}
c.JSON(http.StatusOK, resp)
return
}
componentParamMap[UUIDStr] = byteSlice
componentParamMap[UUIDStr] = componentParams
}
}
payLoad["component_params"] = componentParamMap

View File

@ -5,17 +5,17 @@ import (
"modelRT/database"
"modelRT/diagram"
"modelRT/log"
"modelRT/logger"
"modelRT/network"
"github.com/bitly/go-simplejson"
"github.com/gin-gonic/gin"
cmap "github.com/orcaman/concurrent-map/v2"
"go.uber.org/zap"
)
// CircuitDiagramUpdateHandler define circuit diagram update process API
func CircuitDiagramUpdateHandler(c *gin.Context) {
logger := log.GetLoggerInstance()
logger := logger.GetLoggerInstance()
pgClient := database.GetPostgresDBClient()
var request network.CircuitDiagramUpdateRequest
@ -129,8 +129,7 @@ func CircuitDiagramUpdateHandler(c *gin.Context) {
}
for _, componentInfo := range request.ComponentInfos {
componentMap := cmap.New[any]()
err = componentMap.UnmarshalJSON([]byte(componentInfo.Params))
paramsJSON, err := simplejson.NewJson([]byte(componentInfo.Params))
if err != nil {
logger.Error("unmarshal component info by concurrent map failed", zap.String("component_params", componentInfo.Params), zap.Error(err))
header := network.FailResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()}
@ -144,7 +143,22 @@ func CircuitDiagramUpdateHandler(c *gin.Context) {
c.JSON(http.StatusOK, resp)
return
}
diagram.UpdateComponentMap(componentInfo.UUID, &componentMap)
componentMap, err := paramsJSON.Map()
if err != nil {
logger.Error("format params json info to map failed", zap.Error(err))
header := network.FailResponseHeader{Status: http.StatusBadRequest, ErrMsg: err.Error()}
resp := network.FailureResponse{
FailResponseHeader: header,
PayLoad: map[string]interface{}{
"uuid": componentInfo.UUID,
"component_params": componentInfo.Params,
},
}
c.JSON(http.StatusOK, resp)
return
}
diagram.UpdateComponentMap(componentInfo.UUID, componentMap)
}
if len(request.FreeVertexs) > 0 {

View File

@ -1,5 +1,5 @@
// Package log define log struct of wave record project
package log
// Package logger define log struct of wave record project
package logger
import (
"os"

44
main.go
View File

@ -10,10 +10,10 @@ import (
"modelRT/database"
_ "modelRT/docs"
"modelRT/handler"
"modelRT/log"
"modelRT/logger"
"modelRT/middleware"
"modelRT/pool"
subscription "modelRT/real-time-data"
realtimedata "modelRT/real-time-data"
swaggerFiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
@ -39,7 +39,7 @@ var (
var (
modelRTConfig config.ModelRTConfig
postgresDBClient *gorm.DB
logger *zap.Logger
zapLogger *zap.Logger
)
// TODO 使用 wire 依赖注入管理 DVIE 面板注册的 panel
@ -60,34 +60,47 @@ func main() {
}()
// init logger
logger = log.InitLoggerInstance(modelRTConfig.LoggerConfig)
defer logger.Sync()
zapLogger = logger.InitLoggerInstance(modelRTConfig.LoggerConfig)
defer zapLogger.Sync()
// init ants pool
pool, err := ants.NewPoolWithFunc(modelRTConfig.ParseConcurrentQuantity, pool.ParseFunc)
// init model parse ants pool
parsePool, err := ants.NewPoolWithFunc(modelRTConfig.ParseConcurrentQuantity, pool.ParseFunc)
if err != nil {
logger.Error("init concurrent parse task pool failed", zap.Error(err))
zapLogger.Error("init concurrent parse task pool failed", zap.Error(err))
panic(err)
}
defer ants.Release()
defer parsePool.Release()
// init data polling ants pool
pollingPool, err := ants.NewPoolWithFunc(modelRTConfig.PollingConcurrentQuantity, pool.AnchorFunc)
if err != nil {
zapLogger.Error("init concurrent data polling task pool failed", zap.Error(err))
panic(err)
}
defer pollingPool.Release()
// init data polling
cancelCtx, cancel := context.WithCancel(ctx)
defer cancel()
go realtimedata.DataPolling(cancelCtx, pollingPool)
// load circuit diagram from postgres
err = database.QueryCircuitDiagramComponentFromDB(ctx, pool, logger)
err = database.QueryCircuitDiagramComponentFromDB(ctx, parsePool, zapLogger)
if err != nil {
logger.Error("load circuit diagrams from postgres failed", zap.Error(err))
zapLogger.Error("load circuit diagrams from postgres failed", zap.Error(err))
panic(err)
}
// TODO 暂时屏蔽完成 swagger 启动测试
err = database.QueryTopologicFromDB(ctx, logger, modelRTConfig.GridID, modelRTConfig.ZoneID, modelRTConfig.StationID)
err = database.QueryTopologicFromDB(ctx, zapLogger, modelRTConfig.GridID, modelRTConfig.ZoneID, modelRTConfig.StationID)
if err != nil {
logger.Error("load topologic info from postgres failed", zap.Error(err))
zapLogger.Error("load topologic info from postgres failed", zap.Error(err))
panic(err)
}
// TODO 完成订阅数据分析
// TODO 暂时屏蔽完成 swagger 启动测试
go subscription.RealTimeDataComputer(ctx, nil, []string{}, "")
go realtimedata.RealTimeDataComputer(ctx, nil, []string{}, "")
engine := gin.Default()
engine.Use(limiter.Middleware)
@ -98,6 +111,9 @@ func main() {
engine.POST("/model/diagram_update", handler.CircuitDiagramUpdateHandler)
engine.POST("/model/diagram_delete", handler.CircuitDiagramDeleteHandler)
// anchor api
engine.POST("/model/anchor_replace", handler.ComponentAnchorReplaceHandler)
// dashborad api
dashboard := engine.Group("/dashboard", limiter.Middleware)
{

View File

@ -12,6 +12,8 @@ func SelectModelByType(modelType int) BasicModelInterface {
return &orm.BusbarSection{}
} else if modelType == constant.AsyncMotorType {
return &orm.AsyncMotor{}
} else if modelType == constant.DemoType {
return &orm.Demo{}
}
return nil
}

View File

@ -0,0 +1,8 @@
// Package network define struct of network operation
package network
// ComponetAnchorReplaceRequest defines request params of component anchor point replace api
type ComponetAnchorReplaceRequest struct {
UUID string `json:"uuid"`
AnchorName string `json:"anchor_name"`
}

84
network/api_endpoint.go Normal file
View File

@ -0,0 +1,84 @@
// Package network define struct of network operation
package network
import (
"fmt"
"io"
"net/http"
"strings"
"github.com/bitly/go-simplejson"
)
// APIEndpoint defines an api endpoint struct to poll data from dataRT service
type APIEndpoint struct {
URL string `json:"url"`
Method string `json:"method"` // HTTP 方法,如 "GET", "POST"
Headers map[string]string `json:"headers"`
QueryParams map[string]string `json:"query_params"`
Body string `json:"body"` // 对于 POST 请求需要一个请求体
Interval int `json:"interval"` // 轮询间隔时间(秒)
}
// fetchAPI defines execute http request and return response or error
func fetchAPI(endpoint APIEndpoint) (string, error) {
client := &http.Client{}
req, err := http.NewRequest(endpoint.Method, endpoint.URL, nil)
if err != nil {
return "", err
}
for key, value := range endpoint.Headers {
req.Header.Set(key, value)
}
query := req.URL.Query()
for key, value := range endpoint.QueryParams {
query.Set(key, value)
}
req.URL.RawQuery = query.Encode()
if endpoint.Method == "POST" || endpoint.Method == "PUT" {
req.Body = io.NopCloser(strings.NewReader(endpoint.Body))
req.Header.Set("Content-Type", "application/json")
}
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(body), nil
}
// PollAPIEndpoints defines unmarshal polling data from http request
func PollAPIEndpoints(endpoint APIEndpoint) ([]float64, error) {
var valueSlice []float64
respStr, err := fetchAPI(endpoint)
if err != nil {
return valueSlice, fmt.Errorf("fetch api failed:%w", err)
}
realDataJSON, err := simplejson.NewJson([]byte(respStr))
if err != nil {
return valueSlice, fmt.Errorf("format real time data failed:%w", err)
}
simplejson.New().UnmarshalJSON([]byte(respStr))
code := realDataJSON.Get("code").MustInt()
if code != 0 {
return valueSlice, fmt.Errorf("polling data api status error:%s", realDataJSON.Get("msg").MustString())
}
dataLen := len(realDataJSON.Get("data").MustArray())
for i := 0; i < dataLen; i++ {
valueSlice = append(valueSlice, realDataJSON.Get("data").GetIndex(i).Get("value").MustFloat64())
}
return valueSlice, nil
}

37
orm/demo.go Normal file
View File

@ -0,0 +1,37 @@
// Package orm define database data struct
package orm
import "github.com/gofrs/uuid"
type Demo struct {
// 母线基本参数
DemoName string // 母线端名称,默认值BusX
BusbarNumber int // 母线编号,默认值1
Resistance float32 // 电阻值
Voltage float32 // 电压(测点)
AnchorVoltage bool // 是否锚定电压
VoltageUpperLimit float32 // 电压上限
VoltageLowerLimit float32 // 电压下限
Current float32 // 电流(测点)
AnchorCurrent bool // 是否锚定电流
CurrentUpperLimit float32 // 电流上限
CurrentLowerLimit float32 // 电流下限
AnchorParaList string // 锚定参量列表
UUID uuid.UUID `gorm:"column:global_uuid;primaryKey"`
}
// TableName func respresent return table name of busbar section
func (d *Demo) TableName() string {
return "Demo"
}
// SetUUID func implement BasicModelInterface interface
func (d *Demo) SetUUID(uuid uuid.UUID) {
d.UUID = uuid
return
}
// ReturnTableName func implement BasicModelInterface interface
func (d *Demo) ReturnTableName() string {
return "Demo"
}

View File

@ -0,0 +1,86 @@
// Package pool define concurrency call function in ants
package pool
import (
"fmt"
"strconv"
"time"
"modelRT/config"
"modelRT/diagram"
"modelRT/logger"
"modelRT/network"
"go.uber.org/zap"
)
var AnchorFunc = func(anchorConfig interface{}) {
logger := logger.GetLoggerInstance()
var firstTimePolling bool
paramConfig, ok := anchorConfig.(config.AnchorParamConfig)
if !ok {
logger.Error("conversion model anchor param config type failed")
return
}
for {
var beginUnixTime, endUnixTime int64
if firstTimePolling {
milliUnixTime := time.Now().UnixMilli()
endUnixTime = milliUnixTime
beginUnixTime = milliUnixTime - 1000*60
firstTimePolling = false
} else {
// 判断时间差值是否小于10s如果小于则重新获取时间
endUnixTime = time.Now().UnixMilli()
if endUnixTime-beginUnixTime < 1000*10 {
time.Sleep(time.Duration(1 * time.Second))
endUnixTime = time.Now().UnixMilli()
}
}
pollingAPI := network.APIEndpoint{
URL: paramConfig.APIURL,
Method: paramConfig.APIMethod,
QueryParams: map[string]string{
"station": paramConfig.StationID,
"component": paramConfig.ComponentID,
"point": paramConfig.AnchorName,
"begin": strconv.FormatInt(beginUnixTime, 10),
"end": strconv.FormatInt(endUnixTime, 10),
},
}
if !firstTimePolling {
beginUnixTime = time.Now().UnixMilli()
}
valueSlice, err := network.PollAPIEndpoints(pollingAPI)
if err != nil {
logger.Error("polling real time data from dataRT service failed", zap.Error(err))
continue
}
for _, value := range valueSlice {
anchorName, err := diagram.GetAnchorValue(paramConfig.UUID)
if err != nil {
logger.Error("can not get anchor value from map by uuid", zap.String("uuid", paramConfig.UUID), zap.Error(err))
continue
}
if anchorName != paramConfig.AnchorName {
logger.Error("anchor name not equal param config anchor value", zap.String("map_anchor_name", anchorName), zap.String("param_anchor_name", paramConfig.AnchorName))
continue
}
upperLimitVal := paramConfig.CompareValUpperLimit
lowerlimitVal := paramConfig.CompareValLowerLimit
compareValue := paramConfig.CalculateFunc(value, paramConfig.CalculateParams...)
if compareValue > upperLimitVal || compareValue < lowerlimitVal {
// TODO 选择报警方式
fmt.Println("log warning")
}
}
}
}

View File

@ -3,55 +3,92 @@ package pool
import (
"context"
"errors"
"strconv"
"time"
"modelRT/config"
"modelRT/database"
"modelRT/diagram"
"modelRT/logger"
"modelRT/model"
realtimedata "modelRT/real-time-data"
cmap "github.com/orcaman/concurrent-map/v2"
"github.com/bitly/go-simplejson"
"go.uber.org/zap"
)
// ParseFunc defines func that parses the model data from postgres
var ParseFunc = func(parseConfig interface{}) {
logger := zap.L()
logger := logger.GetLoggerInstance()
modelParseConfig, ok := parseConfig.(config.ModelParseConfig)
if !ok {
logger.Error("conversion model parse config type failed")
panic(errors.New("conversion model parse config type failed"))
return
}
cancelCtx, cancel := context.WithTimeout(modelParseConfig.Context, 5*time.Second)
defer cancel()
pgClient := database.GetPostgresDBClient()
uuid := modelParseConfig.ComponentInfo.GlobalUUID.String()
unmarshalMap := cmap.New[any]()
unmarshalMap := make(map[string]interface{})
tableName := model.SelectModelNameByType(modelParseConfig.ComponentInfo.ComponentType)
result := pgClient.Table(tableName).WithContext(cancelCtx).Find(&unmarshalMap)
result := pgClient.WithContext(cancelCtx).Table(tableName).Where("global_uuid = ?", modelParseConfig.ComponentInfo.GlobalUUID).Find(&unmarshalMap)
if result.Error != nil {
logger.Error("query component detail info failed", zap.Error(result.Error))
return
} else if result.RowsAffected == 0 {
logger.Error("query component detail info from table is empty", zap.String("table_name", tableName))
return
}
unmarshalMap.Set("id", modelParseConfig.ComponentInfo.ID)
unmarshalMap.Set("uuid", modelParseConfig.ComponentInfo.GlobalUUID.String())
unmarshalMap.Set("created_time", modelParseConfig.ComponentInfo.VisibleID)
unmarshalMap.Set("parent_id", modelParseConfig.ComponentInfo.GridID)
unmarshalMap.Set("type", modelParseConfig.ComponentInfo.ZoneID)
unmarshalMap.Set("created_time", modelParseConfig.ComponentInfo.StationID)
unmarshalMap.Set("updated_time", modelParseConfig.ComponentInfo.ComponentType)
unmarshalMap.Set("id", modelParseConfig.ComponentInfo.State)
unmarshalMap.Set("parent_id", modelParseConfig.ComponentInfo.ConnectedBus)
unmarshalMap.Set("type", modelParseConfig.ComponentInfo.Name)
unmarshalMap.Set("updated_time", modelParseConfig.ComponentInfo.Description)
unmarshalMap.Set("id", modelParseConfig.ComponentInfo.Context)
unmarshalMap.Set("parent_id", modelParseConfig.ComponentInfo.Comment)
unmarshalMap.Set("type", modelParseConfig.ComponentInfo.InService)
diagram.StoreComponentMap(uuid, &unmarshalMap)
uuid := modelParseConfig.ComponentInfo.GlobalUUID.String()
configsStr, exist := unmarshalMap["anchor_configs_list"]
if exist {
anchorConfigsJSON, err := simplejson.NewJson([]byte(configsStr.(string)))
if err != nil {
logger.Error("formmat anchor configs json failed", zap.Error(err))
return
}
paramsList := anchorConfigsJSON.Get("params_list").MustArray()
for index := range paramsList {
anchorName := anchorConfigsJSON.Get("params_list").GetIndex(index).Get("upper_limit").MustString()
anchorParam := config.AnchorParamConfig{
AnchorParamBaseConfig: config.AnchorParamBaseConfig{
StationID: strconv.FormatInt(modelParseConfig.ComponentInfo.StationID, 10),
ComponentID: strconv.FormatInt(modelParseConfig.ComponentInfo.ID, 10),
UUID: uuid,
AnchorName: anchorName,
CompareValUpperLimit: anchorConfigsJSON.Get("params_list").GetIndex(index).Get("upper_limit").MustFloat64(),
CompareValLowerLimit: anchorConfigsJSON.Get("params_list").GetIndex(index).Get("lower_limit").MustFloat64(),
},
}
anchorParam.CalculateFunc, anchorParam.CalculateParams = config.SelectAnchorCalculateFuncAndParams(modelParseConfig.ComponentInfo.ComponentType, anchorName, unmarshalMap)
diagram.StoreAnchorValue(modelParseConfig.ComponentInfo.GlobalUUID.String(), anchorName)
realtimedata.AnchorParamsChan <- anchorParam
}
}
unmarshalMap["id"] = modelParseConfig.ComponentInfo.ID
unmarshalMap["uuid"] = uuid
unmarshalMap["created_time"] = modelParseConfig.ComponentInfo.VisibleID
unmarshalMap["parent_id"] = modelParseConfig.ComponentInfo.GridID
unmarshalMap["type"] = modelParseConfig.ComponentInfo.ZoneID
unmarshalMap["created_time"] = modelParseConfig.ComponentInfo.StationID
unmarshalMap["updated_time"] = modelParseConfig.ComponentInfo.ComponentType
unmarshalMap["id"] = modelParseConfig.ComponentInfo.State
unmarshalMap["parent_id"] = modelParseConfig.ComponentInfo.ConnectedBus
unmarshalMap["type"] = modelParseConfig.ComponentInfo.Name
unmarshalMap["updated_time"] = modelParseConfig.ComponentInfo.Description
unmarshalMap["id"] = modelParseConfig.ComponentInfo.Context
unmarshalMap["parent_id"] = modelParseConfig.ComponentInfo.Comment
unmarshalMap["type"] = modelParseConfig.ComponentInfo.InService
diagram.StoreComponentMap(uuid, unmarshalMap)
return
}

View File

@ -0,0 +1,29 @@
// Package realtimedata define real time data operation functions
package realtimedata
import (
"context"
"modelRT/config"
"github.com/panjf2000/ants/v2"
)
var AnchorParamsChan chan config.AnchorParamConfig
func init() {
AnchorParamsChan = make(chan config.AnchorParamConfig, 100)
}
// DataPolling perform data polling on dataRT modules based on UUID
func DataPolling(ctx context.Context, pool *ants.PoolWithFunc) {
for {
select {
case <-ctx.Done():
return
case anchorParam := <-AnchorParamsChan:
pool.Invoke(anchorParam)
default:
}
}
}

View File

@ -1,11 +1,15 @@
// Package subscription define real time data operation functions
package subscription
// Package realtimedata define real time data operation functions
package realtimedata
import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"time"
"modelRT/log"
"modelRT/logger"
"github.com/confluentinc/confluent-kafka-go/kafka"
"go.uber.org/zap"
@ -18,9 +22,10 @@ func RealTimeDataComputer(ctx context.Context, consumerConfig kafka.ConfigMap, t
defer cancel()
// get a logger
logger := log.GetLoggerInstance()
logger := logger.GetLoggerInstance()
// setup a channel to listen for interrupt signals
// TODO 将中断信号放到入参中
interrupt := make(chan struct{}, 1)
// read message (-1 means wait indefinitely)
@ -63,4 +68,31 @@ func RealTimeDataComputer(ctx context.Context, consumerConfig kafka.ConfigMap, t
logger.Error("manual submission information failed", zap.Any("message", msg), zap.Error(err))
}
}
consumer.SubscribeTopics(topics, nil)
// 捕获中断信号以便优雅关闭
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM)
// 消费消息
for {
select {
case sig := <-signals:
fmt.Printf("Interrupt signal (%s) received, stopping consumers...\n", sig)
return
case ev := <-consumer.Events():
switch e := ev.(type) {
case kafka.AssignedPartitions:
fmt.Printf("Assigned partitions: %v\n", e.Partitions)
case kafka.RevokedPartitions:
fmt.Printf("Revoked partitions: %v\n", e.Partitions)
case *kafka.Message:
fmt.Printf("Consumed message: %s from %v [%d] at offset %v\n",
string(e.Value), e.TopicPartition.Topic, e.TopicPartition.Partition, e.TopicPartition.Offset)
}
}
}
// var client http.Client
// client.Do()
}

21
sql/demo.sql Normal file
View File

@ -0,0 +1,21 @@
CREATE TABLE public."Demo" (
id serial NOT NULL,
global_uuid uuid NOT NULL,
demo_number integer NOT NULL,
demo_name character varying(20) default 'Demox' NOT NULL,
voltage decimal(5, 2) NOT NULL,
voltage_upper_limit decimal(5, 2) NOT NULL,
voltage_lower_limit decimal(5, 2) NOT NULL,
anchor_voltage boolean NOT NULL,
current decimal(5, 2) NOT NULL,
current_upper_limit decimal(5, 2) NOT NULL,
current_lower_limit decimal(5, 2) NOT NULL,
anchor_current boolean NOT NULL,
resistance decimal(5, 2) NOT NULL,
anchor_para_list text NULL
);
ALTER TABLE
public."Demo"
ADD
CONSTRAINT "Demo_pkey" PRIMARY KEY (global_uuid)