From c764a946ff9c5d09bbce2339966a94721279eb63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Schw=C3=B6rer?= Date: Sat, 20 Sep 2025 15:13:02 +0200 Subject: [PATCH] v0.0.602 add listener to DelayedCombiningInvoker --- .idea/copilot.data.migration.ask.xml | 6 +++ .idea/copilot.data.migration.ask2agent.xml | 6 +++ dataext/delayedCombiningInvoker.go | 61 +++++++++++++++++++++- go.mod | 8 ++- go.sum | 14 +++++ goextVersion.go | 4 +- 6 files changed, 94 insertions(+), 5 deletions(-) create mode 100644 .idea/copilot.data.migration.ask.xml create mode 100644 .idea/copilot.data.migration.ask2agent.xml diff --git a/.idea/copilot.data.migration.ask.xml b/.idea/copilot.data.migration.ask.xml new file mode 100644 index 0000000..7ef04e2 --- /dev/null +++ b/.idea/copilot.data.migration.ask.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/copilot.data.migration.ask2agent.xml b/.idea/copilot.data.migration.ask2agent.xml new file mode 100644 index 0000000..1f2ea11 --- /dev/null +++ b/.idea/copilot.data.migration.ask2agent.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/dataext/delayedCombiningInvoker.go b/dataext/delayedCombiningInvoker.go index 9cd5778..dde330a 100644 --- a/dataext/delayedCombiningInvoker.go +++ b/dataext/delayedCombiningInvoker.go @@ -2,10 +2,11 @@ package dataext import ( "context" - "git.blackforestbytes.com/BlackForestBytes/goext/langext" - "git.blackforestbytes.com/BlackForestBytes/goext/syncext" "sync" "time" + + "git.blackforestbytes.com/BlackForestBytes/goext/langext" + "git.blackforestbytes.com/BlackForestBytes/goext/syncext" ) type DelayedCombiningInvoker struct { @@ -17,8 +18,13 @@ type DelayedCombiningInvoker struct { delay time.Duration maxDelay time.Duration executorRunning *syncext.AtomicBool + pendingRequests *syncext.Atomic[int] lastRequestTime time.Time initialRequestTime time.Time + + onExecutionStart []func(immediately bool) // listener ( actual execution of action starts ) + onExecutionDone []func() // listener ( actual execution of action finished ) + onRequest []func(pending int, initial bool) // listener ( a request came in, waiting for execution ) } func NewDelayedCombiningInvoker(action func(), delay time.Duration, maxDelay time.Duration) *DelayedCombiningInvoker { @@ -27,11 +33,15 @@ func NewDelayedCombiningInvoker(action func(), delay time.Duration, maxDelay tim delay: delay, maxDelay: maxDelay, executorRunning: syncext.NewAtomicBool(false), + pendingRequests: syncext.NewAtomic[int](0), triggerChan: make(chan bool), cancelChan: make(chan bool, 1), execNowChan: make(chan bool, 1), lastRequestTime: time.Now(), initialRequestTime: time.Now(), + onExecutionStart: make([]func(bool), 0), + onExecutionDone: make([]func(), 0), + onRequest: make([]func(int, bool), 0), } } @@ -43,6 +53,11 @@ func (d *DelayedCombiningInvoker) Request() { if d.executorRunning.Get() { d.lastRequestTime = now + d.pendingRequests.Update(func(v int) int { return v + 1 }) + + for _, fn := range d.onRequest { + _ = langext.RunPanicSafe(func() { fn(d.pendingRequests.Get(), true) }) + } d.triggerChan <- true } else { @@ -50,9 +65,15 @@ func (d *DelayedCombiningInvoker) Request() { d.lastRequestTime = now d.executorRunning.Set(true) + d.pendingRequests.Set(1) syncext.ReadNonBlocking(d.triggerChan) // clear the channel syncext.ReadNonBlocking(d.cancelChan) // clear the channel syncext.ReadNonBlocking(d.execNowChan) // clear the channel + + for _, fn := range d.onRequest { + _ = langext.RunPanicSafe(func() { fn(d.pendingRequests.Get(), false) }) + } + go d.run() } } @@ -98,8 +119,22 @@ func (d *DelayedCombiningInvoker) run() { continue } + d.pendingRequests.Set(0) + + for _, fn := range d.onExecutionStart { + _ = langext.RunPanicSafe(func() { fn(immediately) }) + } + + // ================================================= _ = langext.RunPanicSafe(d.action) + // ================================================= + + for _, fn := range d.onExecutionDone { + _ = langext.RunPanicSafe(fn) + } + d.syncLock.Unlock() + return } } @@ -115,6 +150,10 @@ func (d *DelayedCombiningInvoker) HasPendingRequests() bool { return d.executorRunning.Get() } +func (d *DelayedCombiningInvoker) CountPendingRequests() int { + return d.pendingRequests.Get() +} + func (d *DelayedCombiningInvoker) ExecuteNow() bool { d.syncLock.Lock() defer d.syncLock.Unlock() @@ -130,3 +169,21 @@ func (d *DelayedCombiningInvoker) ExecuteNow() bool { func (d *DelayedCombiningInvoker) WaitForCompletion(ctx context.Context) error { return d.executorRunning.WaitWithContext(ctx, false) } + +func (d *DelayedCombiningInvoker) RegisterOnExecutionStart(fn func(immediately bool)) { + d.syncLock.Lock() + defer d.syncLock.Unlock() + d.onExecutionStart = append(d.onExecutionStart, fn) +} + +func (d *DelayedCombiningInvoker) RegisterOnExecutionDone(fn func()) { + d.syncLock.Lock() + defer d.syncLock.Unlock() + d.onExecutionDone = append(d.onExecutionDone, fn) +} + +func (d *DelayedCombiningInvoker) RegisterOnRequest(fn func(pending int, initial bool)) { + d.syncLock.Lock() + defer d.syncLock.Unlock() + d.onRequest = append(d.onRequest, fn) +} diff --git a/go.mod b/go.mod index 99cf86b..4d83215 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module git.blackforestbytes.com/BlackForestBytes/goext go 1.24.0 require ( - github.com/gin-gonic/gin v1.10.1 + github.com/gin-gonic/gin v1.11.0 github.com/glebarez/go-sqlite v1.22.0 // only needed for tests -.- github.com/jmoiron/sqlx v1.4.0 github.com/rs/xid v1.6.0 @@ -34,6 +34,7 @@ require ( github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.27.0 // indirect github.com/goccy/go-json v0.10.5 // indirect + github.com/goccy/go-yaml v1.18.0 // indirect github.com/golang/snappy v1.0.0 // indirect github.com/google/uuid v1.5.0 // indirect github.com/json-iterator/go v1.1.12 // indirect @@ -46,6 +47,8 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/montanaflynn/stats v0.7.1 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect + github.com/quic-go/qpack v0.5.1 // indirect + github.com/quic-go/quic-go v0.54.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.3.0 // indirect @@ -53,9 +56,12 @@ require ( github.com/xdg-go/scram v1.1.2 // indirect github.com/xdg-go/stringprep v1.0.4 // indirect github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect + go.uber.org/mock v0.6.0 // indirect golang.org/x/arch v0.21.0 // indirect golang.org/x/image v0.31.0 // indirect + golang.org/x/mod v0.28.0 // indirect golang.org/x/text v0.29.0 // indirect + golang.org/x/tools v0.37.0 // indirect google.golang.org/protobuf v1.36.9 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/libc v1.37.6 // indirect diff --git a/go.sum b/go.sum index f1ebd07..5139416 100644 --- a/go.sum +++ b/go.sum @@ -80,6 +80,8 @@ github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/gin-gonic/gin v1.10.1 h1:T0ujvqyCSqRopADpgPgiTT63DUQVSfojyME59Ei63pQ= github.com/gin-gonic/gin v1.10.1/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= +github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk= +github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls= github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ= github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= @@ -108,6 +110,8 @@ github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM= github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= +github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= +github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= @@ -175,6 +179,10 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= +github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= +github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg= +github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= @@ -224,6 +232,8 @@ go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeH go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= go.mongodb.org/mongo-driver v1.17.4 h1:jUorfmVzljjr0FLzYQsGP8cgN/qzzxlY9Vh0C9KFXVw= go.mongodb.org/mongo-driver v1.17.4/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ= +go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= +go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= golang.org/x/arch v0.11.0 h1:KXV8WWKCXm6tRpLirl2szsO5j/oOODwZf4hATmGVNs4= golang.org/x/arch v0.11.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/arch v0.12.0 h1:UsYJhbzPYGsT0HbEdmYcqtCv8UNGvnaL561NnIUvaKg= @@ -301,6 +311,8 @@ golang.org/x/image v0.30.0/go.mod h1:SAEUTxCCMWSrJcCy/4HwavEsfZZJlYxeHLc6tTiAe/c golang.org/x/image v0.31.0 h1:mLChjE2MV6g1S7oqbXC0/UcKijjm5fnJLUYKIYrLESA= golang.org/x/image v0.31.0/go.mod h1:R9ec5Lcp96v9FTF+ajwaH3uGxPH4fKfHHAVbUILxghA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.28.0 h1:gQBtGhjxykdjY9YhZpSlZIsbnaE2+PgjfLWUQTnoZ1U= +golang.org/x/mod v0.28.0/go.mod h1:yfB/L0NOf/kmEbXjzCPOx1iK1fRutOydrCMsqRhEBxI= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -438,6 +450,8 @@ golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.37.0 h1:DVSRzp7FwePZW356yEAChSdNcQo6Nsp+fex1SUW09lE= +golang.org/x/tools v0.37.0/go.mod h1:MBN5QPQtLMHVdvsbtarmTNukZDdgwdwlO5qGacAzF0w= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= diff --git a/goextVersion.go b/goextVersion.go index 0a02cc1..6094180 100644 --- a/goextVersion.go +++ b/goextVersion.go @@ -1,5 +1,5 @@ package goext -const GoextVersion = "0.0.601" +const GoextVersion = "0.0.602" -const GoextVersionTimestamp = "2025-09-13T19:04:52+0200" +const GoextVersionTimestamp = "2025-09-20T15:13:02+0200"