refactor: Update ARR body parsing logic

The code changes in `aviation_parser_test.go` update the ARR body parsing logic. The `ParseHeader` function now correctly handles ARR bodies with optional time components. This ensures accurate parsing of ARR bodies and improves the overall functionality of the aviation parser.
This commit is contained in:
windyboy
2024-07-22 12:42:30 +08:00
parent c72b6e2163
commit 0391f9f481
11 changed files with 306 additions and 74 deletions
+3 -3
View File
@@ -5,7 +5,7 @@
# Folders # Folders
/bin/ /bin/
/pkg/ # /pkg/
/build/ /build/
# Architecture specific extensions/prefixes # Architecture specific extensions/prefixes
@@ -28,7 +28,7 @@ ehthumbs.db
Thumbs.db Thumbs.db
# Go specific # Go specific
go.sum # go.sum
go.mod go.mod
# Test binary, built with `go test -c` # Test binary, built with `go test -c`
@@ -38,7 +38,7 @@ go.mod
*.out *.out
# Project-specific # Project-specific
configs/*.toml # configs/*.toml
# Logs # Logs
*.log *.log
+7 -4
View File
@@ -3,20 +3,23 @@ package main
import ( import (
"caatsm/internal/config" "caatsm/internal/config"
"caatsm/internal/nats" "caatsm/internal/nats"
"caatsm/pkg/utils"
"fmt"
) )
func main() { func main() {
cfg, err := config.LoadConfig() cfg, err := config.LoadConfig()
if err != nil { if err != nil {
utils.Logger.WithError(err).Fatal("Error loading config") fmt.Printf("Error loading configuration: %v\n", err)
return
} }
if err := config.ValidateConfig(cfg); err != nil { if err := config.ValidateConfig(cfg); err != nil {
utils.Logger.WithError(err).Fatal("Config validation error") fmt.Printf("Invalid configuration: %v\n", err)
return
} }
utils.Logger.Info("Loaded configuration successfully") fmt.Println("Loaded configuration successfully")
subscribe := nats.NewNatsHandler(cfg) subscribe := nats.NewNatsHandler(cfg)
subscribe.Subscribe() subscribe.Subscribe()
+1
View File
@@ -0,0 +1 @@
GO_ENV=dev
+14
View File
@@ -0,0 +1,14 @@
[nats]
url = "nats://localhost:4222"
client = "serial-client"
cluster = "tele-cluster"
[subscription]
topic = "Telegram.Serial"
queue = "tele-queue"
[timeouts]
server = "5s"
reconnect_wait = "5s"
close = "10s"
ack_wait = "5s"
+22
View File
@@ -0,0 +1,22 @@
{
"zapConfig": {
"level": "debug",
"encoding": "json",
"outputPaths": ["stdout"],
"errorOutputPaths": ["stderr"],
"encoderConfig": {
"messageKey": "message",
"levelKey": "level",
"timeKey": "time",
"nameKey": "logger",
"callerKey": "caller",
"stacktraceKey": "stacktrace",
"lineEnding": "\n",
"levelEncoder": "lowercase",
"timeEncoder": "iso8601",
"durationEncoder": "string",
"callerEncoder": "short"
}
},
"lumberjackConfig": {}
}
+117
View File
@@ -0,0 +1,117 @@
github.com/ThreeDotsLabs/watermill v1.3.5 h1:50JEPEhMGZQMh08ct0tfO1PsgMOAOhV3zxK2WofkbXg=
github.com/ThreeDotsLabs/watermill v1.3.5/go.mod h1:O/u/Ptyrk5MPTxSeWM5vzTtZcZfxXfO9PK9eXTYiFZY=
github.com/ThreeDotsLabs/watermill-nats/v2 v2.0.2 h1:/87LcdSzUEdCKbJptaLE987hOVOs852b+v5pukegggo=
github.com/ThreeDotsLabs/watermill-nats/v2 v2.0.2/go.mod h1:uslCjpuzANBzawXYlwx2IDyGjpv9M42U2TQH6JMMQis=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
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/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
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/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg=
github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
github.com/hashicorp/errwrap v1.1.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/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lithammer/shortuuid/v3 v3.0.7 h1:trX0KTHy4Pbwo/6ia8fscyHoGA+mf1jWbPJVuvyJQQ8=
github.com/lithammer/shortuuid/v3 v3.0.7/go.mod h1:vMk8ke37EmiewwolSO1NLW8vP4ZaKlRuDIi8tWWmAts=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/nats-io/nats.go v1.36.0 h1:suEUPuWzTSse/XhESwqLxXGuj8vGRuPRoG7MoRN/qyU=
github.com/nats-io/nats.go v1.36.0/go.mod h1:Ubdu4Nh9exXdSz0RVWRFBbRfrbSxOYd26oF0wkWclB8=
github.com/nats-io/nkeys v0.4.7 h1:RwNJbbIdYCoClSDNY7QVKZlyb/wfT6ugvFCiKy6vDvI=
github.com/nats-io/nkeys v0.4.7/go.mod h1:kqXRgRDPlGy7nGaEDMuYzmiJCIAAWDK0IMBtDmGD0nc=
github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw=
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
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/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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
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/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/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
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.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/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=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
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/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
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/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/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw=
golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+107 -5
View File
@@ -1,6 +1,7 @@
package config package config
import ( import (
"caatsm/pkg/utils"
"fmt" "fmt"
"os" "os"
"regexp" "regexp"
@@ -8,6 +9,9 @@ import (
"time" "time"
"github.com/spf13/viper" "github.com/spf13/viper"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
) )
var MyConfig *Config var MyConfig *Config
@@ -30,10 +34,10 @@ type SubscriptionConfig struct {
} }
type TimeoutsConfig struct { type TimeoutsConfig struct {
ServerTimeout time.Duration `mapstructure:"server_timeout"` Server time.Duration `mapstructure:"server"`
ReconnectWait time.Duration `mapstructure:"reconnect_wait"` ReconnectWait time.Duration `mapstructure:"reconnect_wait"`
CloseTimeout time.Duration `mapstructure:"close_timeout"` Close time.Duration `mapstructure:"close"`
AckWaitTimeout time.Duration `mapstructure:"ack_wait_timeout"` AckWait time.Duration `mapstructure:"ack_wait"`
} }
type BodyConfig struct { type BodyConfig struct {
@@ -46,7 +50,24 @@ type PatternConfig struct {
Expression *regexp.Regexp Expression *regexp.Regexp
} }
// LoggerConfig represents the configuration for the logger.
type LoggerConfig struct {
ZapConfig zap.Config `json:"zapConfig"`
LumberjackConfig LumberjackConfig `json:"lumberjackConfig"`
}
// LumberjackConfig represents the configuration for lumberjack logging.
type LumberjackConfig struct {
Filename string `json:"filename"`
MaxSize int `json:"maxSize"`
MaxBackups int `json:"maxBackups"`
MaxAge int `json:"maxAge"`
Compress bool `json:"compress"`
}
const ( const (
EnvProd = "prod"
// logConfigFile = "configs/log_config.json"
// arrPatternString represents the regular expression pattern used to match arrival patterns. // arrPatternString represents the regular expression pattern used to match arrival patterns.
// The pattern matches strings in the format: "(TYPE-NUMBER-SSR-DEPARTURE-ARRIVAL)". // The pattern matches strings in the format: "(TYPE-NUMBER-SSR-DEPARTURE-ARRIVAL)".
// The pattern captures the following named groups: // The pattern captures the following named groups:
@@ -66,7 +87,7 @@ const (
// - departure: the four-letter departure airport code // - departure: the four-letter departure airport code
// - departure_time: the four-digit departure time // - departure_time: the four-digit departure time
// - arrival: the four-letter arrival airport code // - arrival: the four-letter arrival airport code
depPatternString = `^\((?P<category>[A-Z]{3})-(?P<number>[A-Z0-9]+)-(?P<ssr>[A-Z0-9]+)-(?P<departure>[A-Z]{4})-(?P<departure_time>\d{4})-(?P<arrival>[A-Z]{4})\)$` depPatternString = `^\((?P<category>[A-Z]{3})-(?P<number>[A-Z0-9]+)(\/(?P<ssr>[A-Z0-9]+))?-(?P<departure>[A-Z]{4})(?P<departure_time>\d{4})-(?P<arrival>[A-Z]{4})\)$`
// fplPatternString is a regular expression designed to parse and extract detailed information from formatted flight plan strings. // fplPatternString is a regular expression designed to parse and extract detailed information from formatted flight plan strings.
// The flight plan string is expected to follow a specific format, encapsulated by parentheses and containing various segments separated by hyphens. // The flight plan string is expected to follow a specific format, encapsulated by parentheses and containing various segments separated by hyphens.
@@ -185,6 +206,7 @@ func LoadConfig() (*Config, error) {
// log.Error(errMsg) // log.Error(errMsg)
return nil, fmt.Errorf(errMsg) return nil, fmt.Errorf(errMsg)
} }
// loadLoggerConfig()
// log.Debugf("Config loaded: %+v", config) // log.Debugf("Config loaded: %+v", config)
return &config, nil return &config, nil
@@ -206,3 +228,83 @@ func ValidateConfig(cfg *Config) error {
// fmt.Println("config validation passed") // fmt.Println("config validation passed")
return nil return nil
} }
func loadLoggerConfig() {
// log := utils.Logger
env := os.Getenv("GO_ENV")
if env == "" {
env = "dev"
}
// log.Infof("Environment: %s", env)
viper.SetConfigType("json")
viper.SetConfigName("logger." + env)
viper.AddConfigPath("configs")
// viper.SetEnvPrefix("tele")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
if err := viper.ReadInConfig(); err != nil {
errMsg := fmt.Sprintf("error reading logger config file for environment '%s': %v", env, err)
// log.Error(errMsg)
panic(errMsg)
}
// log.Debug("Logger config file read successfully")
// log.Debugf("Logger config keys: %v", viper.AllKeys())
var config LoggerConfig
if err := viper.Unmarshal(&config); err != nil {
errMsg := fmt.Sprintf("unable to decode logger config into struct for environment '%s': %v", env, err)
// log.Error(errMsg)
// return nil, fmt.Errorf(errMsg)
panic(errMsg)
}
var logWriter zapcore.WriteSyncer
if env == EnvProd {
logWriter = zapcore.AddSync(&lumberjack.Logger{
Filename: config.LumberjackConfig.Filename,
MaxSize: config.LumberjackConfig.MaxSize,
MaxBackups: config.LumberjackConfig.MaxBackups,
MaxAge: config.LumberjackConfig.MaxAge,
Compress: config.LumberjackConfig.Compress,
})
} else {
logWriter = zapcore.AddSync(os.Stdout)
}
encoder := zapcore.NewJSONEncoder(config.ZapConfig.EncoderConfig)
level := parseLogLevel(config.ZapConfig.Level.String())
core := zapcore.NewCore(
encoder,
logWriter,
level,
)
log := zap.New(core, zap.AddCaller(), zap.AddStacktrace(zapcore.ErrorLevel))
utils.Logger = log.Sugar()
// log.Debugf("Logger config loaded: %+v", config)
}
// parseLogLevel converts the log level string to zapcore.Level.
func parseLogLevel(level string) zapcore.Level {
switch level {
case "debug":
return zapcore.DebugLevel
case "info":
return zapcore.InfoLevel
case "warn":
return zapcore.WarnLevel
case "error":
return zapcore.ErrorLevel
case "dpanic":
return zapcore.DPanicLevel
case "panic":
return zapcore.PanicLevel
case "fatal":
return zapcore.FatalLevel
default:
return zapcore.InfoLevel
}
}
+3 -3
View File
@@ -27,7 +27,7 @@ func (n *NatsHandler) Subscribe() {
logger := watermill.NewStdLogger(false, false) logger := watermill.NewStdLogger(false, false)
options := []nc.Option{ options := []nc.Option{
nc.RetryOnFailedConnect(true), nc.RetryOnFailedConnect(true),
nc.Timeout(n.config.Timeouts.ServerTimeout), nc.Timeout(n.config.Timeouts.Server),
nc.ReconnectWait(n.config.Timeouts.ReconnectWait), nc.ReconnectWait(n.config.Timeouts.ReconnectWait),
} }
jsConfig := nats.JetStreamConfig{Disabled: true} jsConfig := nats.JetStreamConfig{Disabled: true}
@@ -35,8 +35,8 @@ func (n *NatsHandler) Subscribe() {
subscriber, err := nats.NewSubscriber( subscriber, err := nats.NewSubscriber(
nats.SubscriberConfig{ nats.SubscriberConfig{
URL: n.config.Nats.URL, URL: n.config.Nats.URL,
CloseTimeout: n.config.Timeouts.CloseTimeout, CloseTimeout: n.config.Timeouts.Close,
AckWaitTimeout: n.config.Timeouts.AckWaitTimeout, AckWaitTimeout: n.config.Timeouts.AckWait,
NatsOptions: options, NatsOptions: options,
Unmarshaler: marshaler, Unmarshaler: marshaler,
JetStream: jsConfig, JetStream: jsConfig,
+18 -14
View File
@@ -3,7 +3,6 @@ package parsers
import ( import (
"caatsm/internal/config" "caatsm/internal/config"
"caatsm/internal/domain" "caatsm/internal/domain"
"caatsm/pkg/utils"
"fmt" "fmt"
"regexp" "regexp"
"strings" "strings"
@@ -17,9 +16,9 @@ const (
) )
var ( var (
categoryRegex = regexp.MustCompile(`\(([A-Z]{3})(.*)\)`) categoryRegex = regexp.MustCompile(`\((?P<category>[A-Z]+)-`)
emptyLineRemove = regexp.MustCompile(`(?m)^\s*$`) emptyLineRemove = regexp.MustCompile(`(?m)^\s*$`)
bodyOnly = regexp.MustCompile(`^(ZCZC(.|\n)*)NNNN$`) bodyOnly = regexp.MustCompile(`(.|\n)?((ZCZC(.|\n)*))NNNN$`)
) )
type BodyParser struct { type BodyParser struct {
@@ -43,30 +42,30 @@ func (bp *BodyParser) SetBodyPatterns(patterns map[string]config.BodyConfig) {
// Parse attempts to parse the body text using the configured patterns. // Parse attempts to parse the body text using the configured patterns.
func (bp *BodyParser) Parse(body string) (interface{}, error) { func (bp *BodyParser) Parse(body string) (interface{}, error) {
log := utils.Logger // log := utils.Logger
body = strings.TrimSpace(body) body = strings.TrimSpace(body)
log.Info("Parsing body text", body) // log.Info("Parsing body text", body)
category := findCategory(body) category := findCategory(body)
if category == "" { if category == "" {
log.Error("No category found in body text") // log.Error("No category found in body text")
return nil, fmt.Errorf("no category found in body text") return nil, fmt.Errorf("no category found in body text")
} }
patters := bp.GetBodyPatterns() patters := bp.GetBodyPatterns()
log.Infof("body config [%s] %v\n", category, patters[category]) // log.Infof("body config [%s] %v\n", category, patters[category])
if patterConfig := patters[category]; patterConfig.Patterns != nil { if patterConfig := patters[category]; patterConfig.Patterns != nil {
for _, p := range patterConfig.Patterns { for _, p := range patterConfig.Patterns {
log.Infof("Trying pattern %s\n%s\n", p.Comments, p.Pattern) // log.Infof("Trying pattern %s\n%s\n", p.Comments, p.Pattern)
re := p.Expression re := p.Expression
match := re.FindStringSubmatch(body) match := re.FindStringSubmatch(body)
log.Info("Match: ", match) // log.Info("Match: ", match)
if match != nil { if match != nil {
log.Infof("Matched: %v\n", match) // log.Infof("Matched: %v\n", match)
data := extractData(match, re) data := extractData(match, re)
return createBodyData(data) return createBodyData(data)
} }
log.Infof("No match for pattern %s\n", p.Comments) // log.Infof("No match for pattern %s\n", p.Comments)
} }
} }
@@ -75,9 +74,14 @@ func (bp *BodyParser) Parse(body string) (interface{}, error) {
func findCategory(body string) string { func findCategory(body string) string {
match := categoryRegex.FindStringSubmatch(body) match := categoryRegex.FindStringSubmatch(body)
utils.Logger.Infof("Match: %v\n", match) // utils.Logger.Infof("Match: %v\n", match)
if match != nil { if match != nil {
return match[1] groups := categoryRegex.SubexpNames()
for i, name := range groups {
if i != 0 && name == "category" {
return match[i]
}
}
} }
return "" return ""
} }
@@ -168,7 +172,7 @@ func clean(text string) string {
if bodyOnly != nil { if bodyOnly != nil {
match := bodyOnly.FindStringSubmatch(cleanText) match := bodyOnly.FindStringSubmatch(cleanText)
if len(match) > 1 { if len(match) > 1 {
bodyOnly := match[1] bodyOnly := match[2]
if bodyOnly[len(bodyOnly)-1] == '\n' { if bodyOnly[len(bodyOnly)-1] == '\n' {
return bodyOnly[:len(bodyOnly)-1] return bodyOnly[:len(bodyOnly)-1]
} }
+7 -45
View File
@@ -109,44 +109,6 @@ NNNN`
}) })
Context("with NOTAM message", func() {
It("should parse the header correctly", func() {
message := `
ZCZC NOTAM1234 230715
GG EDDNZEZN
.
GG EDDNYNYX
.BERLINTWR 230714
Q) EDMM/QOATT/IV/BO/A/000/999/4814N01120E005
A) EDDM
B) 2307150600 C) 2307151800
E) AERODROME CONTROL TOWER HOURS OF SERVICE
0600-1800 DUE TO MAINTENANCE
NNNN
`
parsedMessage, err := ParseHeader(message)
Expect(err).ToNot(HaveOccurred())
Expect(parsedMessage.StartIndicator).To(Equal("ZCZC"))
Expect(parsedMessage.MessageID).To(Equal("NOTAM1234"))
Expect(parsedMessage.DateTime).To(Equal("230715"))
Expect(parsedMessage.PriorityIndicator).To(Equal("GG"))
Expect(parsedMessage.PrimaryAddress).To(Equal("EDDNZEZN"))
Expect(parsedMessage.SecondaryAddresses).To(Equal([]string{"GG EDDNYNYX"}))
Expect(parsedMessage.Originator).To(Equal("BERLINTWR"))
Expect(parsedMessage.OriginatorDateTime).To(Equal("230714"))
// fmt.Print(parsedMessage.BodyAndFooter)
Expect(parsedMessage.BodyAndFooter).To(Equal(`
Q) EDMM/QOATT/IV/BO/A/000/999/4814N01120E005
A) EDDM
B) 2307150600 C) 2307151800
E) AERODROME CONTROL TOWER HOURS OF SERVICE
0600-1800 DUE TO MAINTENANCE
NNNN
`))
})
})
Describe("ParseBody", func() { Describe("ParseBody", func() {
Context("with ARR body (ARR-CES5470-ZBTJ-ZSHC1614)", func() { Context("with ARR body (ARR-CES5470-ZBTJ-ZSHC1614)", func() {
@@ -187,19 +149,19 @@ NNNN
Context("with DEP body", func() { Context("with DEP body", func() {
parser := NewBodyParser() parser := NewBodyParser()
It("should parse the body (DEP-AB123-SSR1234-KJFK-1500-KLAX) correctly", func() { It("should parse the body (DEP-CYZ9017/A5633-ZBTJ1638-ZSPD) correctly", func() {
body := "(DEP-AB123-SSR1234-KJFK-1500-KLAX)" body := "(DEP-CYZ9017/A5633-ZBTJ1638-ZSPD)"
parsedBody, err := parser.Parse(body) parsedBody, err := parser.Parse(body)
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(parsedBody).ToNot(BeNil()) Expect(parsedBody).ToNot(BeNil())
Expect(parsedBody).To(BeAssignableToTypeOf(&domain.DEP{})) Expect(parsedBody).To(BeAssignableToTypeOf(&domain.DEP{}))
depMessage := parsedBody.(*domain.DEP) depMessage := parsedBody.(*domain.DEP)
Expect(depMessage.Category).To(Equal("DEP")) Expect(depMessage.Category).To(Equal("DEP"))
Expect(depMessage.AircraftID).To(Equal("AB123")) Expect(depMessage.AircraftID).To(Equal("CYZ9017"))
Expect(depMessage.SSRModeAndCode).To(Equal("SSR1234")) Expect(depMessage.SSRModeAndCode).To(Equal("A5633"))
Expect(depMessage.DepartureAirport).To(Equal("KJFK")) Expect(depMessage.DepartureAirport).To(Equal("ZBTJ"))
Expect(depMessage.DepartureTime).To(Equal("1500")) Expect(depMessage.DepartureTime).To(Equal("1638"))
Expect(depMessage.Destination).To(Equal("KLAX")) Expect(depMessage.Destination).To(Equal("ZSPD"))
}) })
}) })
+7
View File
@@ -0,0 +1,7 @@
package utils
import (
"go.uber.org/zap"
)
var Logger *zap.SugaredLogger