From 16bcc244dc217266ae6fd7f97ce48bd0ded5fb09 Mon Sep 17 00:00:00 2001 From: nabbar Date: Thu, 30 Mar 2023 17:57:18 +0200 Subject: [PATCH] Package Config: - rework & optimize listing of dependencies to start or reload component Package HttpServer: - fix bug with writing on channel without listen channel Bump dependencies --- config/components.go | 173 ++++++++++++++++++----------------- go.mod | 77 ++++++++-------- httpserver/run/waitNotify.go | 39 +++++--- 3 files changed, 154 insertions(+), 135 deletions(-) diff --git a/config/components.go b/config/components.go index 7a62b8ea..ec3b5890 100644 --- a/config/components.go +++ b/config/components.go @@ -32,6 +32,8 @@ import ( "fmt" "io" + "golang.org/x/exp/slices" + _const "github.com/nabbar/golib/config/const" cfgtps "github.com/nabbar/golib/config/types" @@ -80,6 +82,10 @@ func (c *configModel) ComponentSet(key string, cpt cfgtps.Component) { c.cpt.Store(key, cpt) } +func (c *configModel) componentUpdate(key string, cpt cfgtps.Component) { + c.cpt.Store(key, cpt) +} + func (c *configModel) ComponentList() map[string]cfgtps.Component { var res = make(map[string]cfgtps.Component, 0) c.cpt.Walk(func(key string, val interface{}) bool { @@ -109,53 +115,24 @@ func (c *configModel) ComponentKeys() []string { func (c *configModel) ComponentStart() liberr.Error { var err = ErrorComponentStart.Error(nil) - c.cpt.Walk(func(key string, val interface{}) bool { - - if v, k := val.(cfgtps.Component); !k { - c.cpt.Delete(key) - } else if v == nil { - c.cpt.Delete(key) - } else if e := c.startComponent(key, v); e != nil { - err.AddParent(e) + for _, key := range c.ComponentDependencies() { + if len(key) < 1 { + continue + } else if cpt := c.ComponentGet(key); cpt == nil { + continue + } else { + e := cpt.Start() + c.componentUpdate(key, cpt) + if e != nil { + err.AddParent(e) + } else if !cpt.IsStarted() { + err.AddParent(fmt.Errorf("component '%s' has been call to start, but is not started", key)) + } } - - return true - }) - - if err.HasParent() { - return err } - return nil -} - -func (c *configModel) startComponent(key string, cpt cfgtps.Component) liberr.Error { - if cpt.IsStarted() { - return nil - } else if err := c.startDependencies(cpt.Dependencies()); err != nil { - return err - } else if err = cpt.Start(); err != nil { + if err.HasParent() { return err - } else { - c.cpt.Store(key, cpt) - } - - return nil -} - -func (c *configModel) startDependencies(list []string) liberr.Error { - if len(list) < 1 { - return nil - } - - for _, d := range list { - if cpt := c.ComponentGet(d); cpt == nil { - return ErrorComponentNotFound.ErrorParent(fmt.Errorf("cvomponent '%s' not found", d)) - } else if cpt.IsStarted() { - continue - } else if err := c.startComponent(d, cpt); err != nil { - return err - } } return nil @@ -183,52 +160,24 @@ func (c *configModel) ComponentIsStarted() bool { func (c *configModel) ComponentReload() liberr.Error { var err = ErrorComponentReload.Error(nil) - c.cpt.Walk(func(key string, val interface{}) bool { - if v, k := val.(cfgtps.Component); !k { - c.cpt.Delete(key) - } else if v == nil { - c.cpt.Delete(key) - } else if e := c.reloadComponent(key, v); e != nil { - err.AddParent(e) + for _, key := range c.ComponentDependencies() { + if len(key) < 1 { + continue + } else if cpt := c.ComponentGet(key); cpt == nil { + continue + } else { + e := cpt.Reload() + c.componentUpdate(key, cpt) + if e != nil { + err.AddParent(e) + } else if !cpt.IsStarted() { + err.AddParent(fmt.Errorf("component '%s' has been call to reload, but is not started", key)) + } } - - return true - }) - - if err.HasParent() { - return err } - return nil -} - -func (c *configModel) reloadComponent(key string, cpt cfgtps.Component) liberr.Error { - if cpt.IsStarted() { - return nil - } else if err := c.reloadDependencies(cpt.Dependencies()); err != nil { - return err - } else if err = cpt.Start(); err != nil { + if err.HasParent() { return err - } else { - c.cpt.Store(key, cpt) - } - - return nil -} - -func (c *configModel) reloadDependencies(list []string) liberr.Error { - if len(list) < 1 { - return nil - } - - for _, d := range list { - if cpt := c.ComponentGet(d); cpt == nil { - return ErrorComponentNotFound.ErrorParent(fmt.Errorf("cvomponent '%s' not found", d)) - } else if cpt.IsStarted() { - continue - } else if err := c.startComponent(d, cpt); err != nil { - return err - } } return nil @@ -278,6 +227,60 @@ func (c *configModel) ComponentIsRunning(atLeast bool) bool { return isOk } +func (c *configModel) ComponentDependencies() []string { + var ( + list = make(map[string][]string, 0) + keys = make([]string, 0) + ) + + c.cpt.Walk(func(key string, val interface{}) bool { + + if v, k := val.(cfgtps.Component); !k { + c.cpt.Delete(key) + } else if v == nil { + c.cpt.Delete(key) + } else { + list[key] = v.Dependencies() + keys = append(keys, key) + } + + return true + }) + + return c.orderDependencies(list, keys) +} + +func (c *configModel) orderDependencies(list map[string][]string, dep []string) []string { + var res = make([]string, 0) + + if len(list) < 1 || len(dep) < 1 { + return res + } + + for _, d := range dep { + if _, ok := list[d]; !ok { + continue + } + + if len(list[d]) > 0 { + for _, j := range c.orderDependencies(list, list[d]) { + if len(j) < 1 { + continue + } else if slices.Contains(res, j) { + continue + } + res = append(res, j) + } + } + + if !slices.Contains(res, d) { + res = append(res, d) + } + } + + return res +} + func (c *configModel) DefaultConfig() io.Reader { var buffer = bytes.NewBuffer(make([]byte, 0)) diff --git a/go.mod b/go.mod index 1e49df6d..ee43a029 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,11 @@ module github.com/nabbar/golib go 1.20 require ( - github.com/aws/aws-sdk-go-v2 v1.17.6 - github.com/aws/aws-sdk-go-v2/config v1.18.17 - github.com/aws/aws-sdk-go-v2/credentials v1.13.17 - github.com/aws/aws-sdk-go-v2/service/iam v1.19.6 - github.com/aws/aws-sdk-go-v2/service/s3 v1.30.6 + github.com/aws/aws-sdk-go-v2 v1.17.7 + github.com/aws/aws-sdk-go-v2/config v1.18.19 + github.com/aws/aws-sdk-go-v2/credentials v1.13.18 + github.com/aws/aws-sdk-go-v2/service/iam v1.19.8 + github.com/aws/aws-sdk-go-v2/service/s3 v1.31.0 github.com/bits-and-blooms/bitset v1.5.0 github.com/c-bata/go-prompt v0.2.6 github.com/fatih/color v1.15.0 @@ -15,9 +15,9 @@ require ( github.com/fxamacker/cbor/v2 v2.4.0 github.com/gin-gonic/gin v1.9.0 github.com/go-ldap/ldap/v3 v3.4.4 - github.com/go-playground/validator/v10 v10.11.2 + github.com/go-playground/validator/v10 v10.12.0 github.com/google/go-github/v33 v33.0.0 - github.com/hashicorp/go-hclog v1.4.0 + github.com/hashicorp/go-hclog v1.5.0 github.com/hashicorp/go-retryablehttp v0.7.2 github.com/hashicorp/go-uuid v1.0.3 github.com/hashicorp/go-version v1.6.0 @@ -27,12 +27,12 @@ require ( github.com/mattn/go-colorable v0.1.13 github.com/mitchellh/go-homedir v1.1.0 github.com/mitchellh/mapstructure v1.5.0 - github.com/nats-io/jwt/v2 v2.3.0 + github.com/nats-io/jwt/v2 v2.4.1 github.com/nats-io/nats-server/v2 v2.9.15 - github.com/nats-io/nats.go v1.24.0 + github.com/nats-io/nats.go v1.25.0 github.com/nutsdb/nutsdb v0.12.0 - github.com/onsi/ginkgo/v2 v2.9.1 - github.com/onsi/gomega v1.27.4 + github.com/onsi/ginkgo/v2 v2.9.2 + github.com/onsi/gomega v1.27.6 github.com/pelletier/go-toml v1.9.5 github.com/prometheus/client_golang v1.14.0 github.com/shirou/gopsutil v3.21.11+incompatible @@ -44,7 +44,7 @@ require ( github.com/xanzy/go-gitlab v0.81.0 github.com/xhit/go-simple-mail v2.2.2+incompatible github.com/xujiajun/utils v0.0.0-20220904132955-5f7c5b914235 - golang.org/x/exp v0.0.0-20230314191032-db074128a8ec + golang.org/x/exp v0.0.0-20230321023759-10a507213a29 golang.org/x/net v0.8.0 golang.org/x/oauth2 v0.6.0 golang.org/x/sync v0.1.0 @@ -61,8 +61,9 @@ require ( require ( github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect - github.com/ClickHouse/ch-go v0.53.0 // indirect - github.com/ClickHouse/clickhouse-go/v2 v2.7.0 // indirect + github.com/ClickHouse/ch-go v0.54.0 // indirect + github.com/ClickHouse/clickhouse-go/v2 v2.8.1 // indirect + github.com/DataDog/zstd v1.5.2 // indirect github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/sprig v2.22.0+incompatible // indirect @@ -74,22 +75,22 @@ require ( github.com/andybalholm/cascadia v1.3.1 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.4.10 // indirect - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.30 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.24 // indirect - github.com/aws/aws-sdk-go-v2/internal/ini v1.3.31 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.22 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.1 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.31 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.25 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.3.32 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.25 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.24 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.13.24 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.12.5 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.5 // indirect - github.com/aws/aws-sdk-go-v2/service/sts v1.18.6 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.9.25 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.14.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.12.6 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.14.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.18.7 // indirect github.com/aws/smithy-go v1.13.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bwmarrin/snowflake v0.3.0 // indirect - github.com/bytedance/sonic v1.8.5 // indirect + github.com/bytedance/sonic v1.8.6 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/cockroachdb/errors v1.9.1 // indirect @@ -101,13 +102,13 @@ require ( github.com/go-asn1-ber/asn1-ber v1.5.4 // indirect github.com/go-faster/city v1.0.1 // indirect github.com/go-faster/errors v0.6.1 // indirect - github.com/go-logr/logr v1.2.3 // indirect + github.com/go-logr/logr v1.2.4 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-sql-driver/mysql v1.7.0 // indirect - github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect - github.com/goccy/go-json v0.10.1 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect + github.com/goccy/go-json v0.10.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect github.com/golang-sql/sqlexp v0.1.0 // indirect @@ -116,7 +117,7 @@ require ( github.com/google/btree v1.1.2 // indirect github.com/google/go-cmp v0.5.9 // indirect github.com/google/go-querystring v1.1.0 // indirect - github.com/google/pprof v0.0.0-20230309165930-d61513b1440d // indirect + github.com/google/pprof v0.0.0-20230323073829-e72429f035bd // indirect github.com/google/uuid v1.3.0 // indirect github.com/gorilla/css v1.0.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -129,12 +130,12 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/memberlist v0.5.0 // indirect github.com/huandu/xstrings v1.4.0 // indirect - github.com/imdario/mergo v0.3.13 // indirect + github.com/imdario/mergo v0.3.15 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgx/v5 v5.3.1 // indirect - github.com/jaytaylor/html2text v0.0.0-20211105163654-bc68cce691ba // indirect + github.com/jaytaylor/html2text v0.0.0-20230321000545-74c2419ad056 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -146,19 +147,19 @@ require ( github.com/leodido/go-urn v1.2.2 // indirect github.com/lni/goutils v1.3.0 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.18 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mattn/go-sqlite3 v1.14.16 // indirect github.com/mattn/go-tty v0.0.4 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect - github.com/microsoft/go-mssqldb v0.20.0 // indirect - github.com/miekg/dns v1.1.52 // indirect + github.com/microsoft/go-mssqldb v0.21.0 // indirect + github.com/miekg/dns v1.1.53 // indirect github.com/minio/highwayhash v1.0.2 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/nats-io/nkeys v0.3.0 // indirect + github.com/nats-io/nkeys v0.4.4 // indirect github.com/nats-io/nuid v1.0.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/paulmach/orb v0.9.0 // indirect @@ -170,7 +171,7 @@ require ( github.com/prometheus/common v0.42.0 // indirect github.com/prometheus/procfs v0.9.0 // indirect github.com/rivo/uniseg v0.4.4 // indirect - github.com/rogpeppe/go-internal v1.9.0 // indirect + github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 // indirect github.com/segmentio/asm v1.2.0 // indirect @@ -198,6 +199,6 @@ require ( golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.7.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.29.1 // indirect + google.golang.org/protobuf v1.30.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect ) diff --git a/httpserver/run/waitNotify.go b/httpserver/run/waitNotify.go index f2ba638c..e169f15a 100644 --- a/httpserver/run/waitNotify.go +++ b/httpserver/run/waitNotify.go @@ -46,24 +46,30 @@ func (o *sRun) StartWaitNotify(ctx context.Context) { signal.Notify(quit, syscall.SIGQUIT) o.initChan() - select { - case <-quit: - _ = o.Stop(ctx) - return - case <-o.getContext().Done(): - if o.IsRunning() { + defer o.delChan() + + for { + select { + case <-quit: _ = o.Stop(ctx) + return + case <-o.getContext().Done(): + if o.IsRunning() { + _ = o.Stop(ctx) + } + return + case <-o.getChan(): + return } - return - case <-o.getChan(): - return } } func (o *sRun) StopWaitNotify() { - o.m.Lock() - defer o.m.Unlock() - o.chn <- struct{}{} + o.m.RLock() + defer o.m.RUnlock() + if o.chn != nil { + o.chn <- struct{}{} + } } func (o *sRun) initChan() { @@ -77,3 +83,12 @@ func (o *sRun) getChan() <-chan struct{} { defer o.m.RUnlock() return o.chn } + +func (o *sRun) delChan() { + o.m.Lock() + defer o.m.Unlock() + if o.chn != nil { + close(o.chn) + } + o.chn = nil +}