diff --git a/client/client.go b/client/client.go index 919ed11..8f8bf46 100644 --- a/client/client.go +++ b/client/client.go @@ -170,7 +170,6 @@ Example - sending a notification asynchronously using the v3 model using a AKS n package client import ( - "context" "fmt" "log/slog" "sync/atomic" @@ -184,6 +183,7 @@ import ( modelmetrics "github.com/Azure/arn-sdk/models/metrics" "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy" + "github.com/gostdlib/base/context" "go.opentelemetry.io/otel/metric" ) @@ -457,7 +457,7 @@ func (a *ARN) Notify(ctx context.Context, n models.Notifications) error { } n = n.SetCtx(ctx) - n = n.SetPromise(conn.PromisePool.Get().(chan error)) + n = n.SetPromise(conn.PromisePool.Get(ctx)) defer n.Recycle() modelmetrics.ActivePromise(context.Background()) @@ -483,7 +483,7 @@ func (a *ARN) Notify(ctx context.Context, n models.Notifications) error { func (a *ARN) Async(ctx context.Context, n models.Notifications, promise bool) models.Notifications { n = n.SetCtx(ctx) if promise { - n = n.SetPromise(conn.PromisePool.Get().(chan error)) + n = n.SetPromise(conn.PromisePool.Get(ctx)) modelmetrics.ActivePromise(context.Background()) } diff --git a/client/client_test.go b/client/client_test.go index bfcba11..1628c8c 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -1,7 +1,6 @@ package client import ( - "context" "errors" "testing" @@ -11,6 +10,7 @@ import ( "github.com/Azure/arn-sdk/internal/conn/storage" "github.com/Azure/arn-sdk/models" "github.com/Azure/azure-sdk-for-go/sdk/azcore" + "github.com/gostdlib/base/context" ) func TestHTTPArgsValidate(t *testing.T) { @@ -138,7 +138,7 @@ func newFakeNotify(ctx context.Context, count int, eventErr bool) fakeNotify { } func (f fakeNotify) Recycle() { - conn.PromisePool.Put(f.ch) + conn.PromisePool.Put(context.Background(), f.ch) } func (f fakeNotify) SetCtx(ctx context.Context) models.Notifications { diff --git a/go.mod b/go.mod index a122b24..ff984c9 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/Azure/arn-sdk -go 1.24 +go 1.24.0 -toolchain go1.24.0 +toolchain go1.24.2 require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 @@ -10,35 +10,98 @@ require ( github.com/Azure/retry v0.0.0-20250221010952-92c9290cea0f github.com/go-json-experiment/json v0.0.0-20250417205406-170dfdcf87d1 github.com/google/uuid v1.6.0 - github.com/gostdlib/concurrency v0.0.0-20240403195145-a5b82e576be2 + github.com/gostdlib/base v0.0.0-20250609190732-4cf364d5a0c7 + github.com/gostdlib/concurrency v0.0.0-20241230205952-55ea9e292314 github.com/kylelemons/godebug v1.1.0 - github.com/prometheus/client_golang v1.20.1 - go.opentelemetry.io/otel v1.35.0 - go.opentelemetry.io/otel/exporters/prometheus v0.51.0 - go.opentelemetry.io/otel/metric v1.35.0 - go.opentelemetry.io/otel/sdk v1.29.0 - go.opentelemetry.io/otel/sdk/metric v1.29.0 + github.com/prometheus/client_golang v1.22.0 + go.opentelemetry.io/otel v1.37.0 + go.opentelemetry.io/otel/exporters/prometheus v0.59.1 + go.opentelemetry.io/otel/metric v1.37.0 + go.opentelemetry.io/otel/sdk v1.37.0 + go.opentelemetry.io/otel/sdk/metric v1.37.0 ) require ( github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect + github.com/andybalholm/brotli v1.1.1 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect - github.com/go-logr/logr v1.4.2 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/ebitengine/purego v0.8.2 // indirect + github.com/emicklei/go-restful/v3 v3.12.2 // indirect + github.com/fxamacker/cbor/v2 v2.8.0 // indirect + github.com/go-logr/logr v1.4.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/go-ole/go-ole v1.3.0 // indirect + github.com/go-openapi/jsonpointer v0.21.1 // indirect + github.com/go-openapi/jsonreference v0.21.0 // indirect + github.com/go-openapi/swag v0.23.1 // indirect + github.com/gofiber/fiber/v2 v2.52.6 // indirect + github.com/gogo/protobuf v1.3.2 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/gnostic-models v0.6.9 // indirect + github.com/google/go-cmp v0.7.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect github.com/gostdlib/internals v0.0.0-20240319155855-57c259c0554f // indirect + github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect github.com/jedib0t/go-pretty/v6 v6.6.7 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.18.0 // indirect + github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect + github.com/mailru/easyjson v0.9.0 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect + github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/prometheus/client_model v0.6.1 // indirect - github.com/prometheus/common v0.55.0 // indirect - github.com/prometheus/procfs v0.15.1 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect + github.com/prometheus/client_model v0.6.2 // indirect + github.com/prometheus/common v0.65.0 // indirect + github.com/prometheus/otlptranslator v0.0.0-20250717125610-8549f4ab4f8f // indirect + github.com/prometheus/procfs v0.17.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/sanity-io/litter v1.5.8 // indirect + github.com/shirou/gopsutil/v4 v4.25.3 // indirect + github.com/tklauser/go-sysconf v0.3.15 // indirect + github.com/tklauser/numcpus v0.10.0 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.60.0 // indirect + github.com/x448/float16 v0.8.4 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect - go.opentelemetry.io/otel/trace v1.35.0 // indirect - golang.org/x/net v0.39.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/text v0.24.0 // indirect - google.golang.org/protobuf v1.34.2 // indirect + go.opentelemetry.io/contrib/instrumentation/host v0.60.0 // indirect + go.opentelemetry.io/contrib/instrumentation/runtime v0.60.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 // indirect + go.opentelemetry.io/otel/trace v1.37.0 // indirect + go.opentelemetry.io/proto/otlp v1.5.0 // indirect + golang.org/x/net v0.40.0 // indirect + golang.org/x/oauth2 v0.30.0 // indirect + golang.org/x/sys v0.34.0 // indirect + golang.org/x/term v0.32.0 // indirect + golang.org/x/text v0.25.0 // indirect + golang.org/x/time v0.11.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e // indirect + google.golang.org/grpc v1.71.1 // indirect + google.golang.org/protobuf v1.36.6 // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/api v0.32.3 // indirect + k8s.io/apimachinery v0.32.3 // indirect + k8s.io/client-go v0.32.3 // indirect + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect + k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e // indirect + sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect + sigs.k8s.io/randfill v1.0.0 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/go.sum b/go.sum index 78d0cb9..7a7d0fb 100644 --- a/go.sum +++ b/go.sum @@ -12,84 +12,272 @@ github.com/Azure/retry v0.0.0-20250221010952-92c9290cea0f h1:XjKfallhRhddiRmBG0u github.com/Azure/retry v0.0.0-20250221010952-92c9290cea0f/go.mod h1:4FpEaBWwrdI8kVPeNESpqzIYAZipu7K6MCGCCC6bJ/A= github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs= github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= +github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA= +github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +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/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= +github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU= +github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= +github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU= +github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/go-json-experiment/json v0.0.0-20250417205406-170dfdcf87d1 h1:+VexzzkMLb1tnvpuQdGT/DicIRW7MN8ozsXqBMgp0Hk= github.com/go-json-experiment/json v0.0.0-20250417205406-170dfdcf87d1/go.mod h1:TiCD2a1pcmjd7YnhGH0f/zKNcCD06B029pHhzV23c2M= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= +github.com/go-openapi/jsonpointer v0.21.1 h1:whnzv/pNXtK2FbX/W9yJfRmE2gsmkfahjMKB0fZvcic= +github.com/go-openapi/jsonpointer v0.21.1/go.mod h1:50I1STOfbY1ycR8jGz8DaMeLCdXiI6aDteEdRNNzpdk= +github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= +github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= +github.com/go-openapi/swag v0.23.1 h1:lpsStH0n2ittzTnbaSloVZLuB5+fvSY/+hnagBjSNZU= +github.com/go-openapi/swag v0.23.1/go.mod h1:STZs8TbRvEQQKUA+JZNAm3EWlgaOBGpyFDqQnDHMef0= +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/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI= +github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= +github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo= +github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gostdlib/concurrency v0.0.0-20240403195145-a5b82e576be2 h1:U+9EgLDAj9sZpS1P/q7URMdyg562HOvv5pPLR7usb18= -github.com/gostdlib/concurrency v0.0.0-20240403195145-a5b82e576be2/go.mod h1:zsE6qg45OyHpxbyNdQ9rD1GQCAZwn3XSE6i8T+PuHIk= +github.com/gostdlib/base v0.0.0-20250609190732-4cf364d5a0c7 h1:bnTTbSqP9Cr0YwpMqoAwOok/47ZvT/8C235qsLeZDeo= +github.com/gostdlib/base v0.0.0-20250609190732-4cf364d5a0c7/go.mod h1:ftJViYVO1MS4KDtM3XSFJqEJ0ttlppGV8qMcn72NeWg= +github.com/gostdlib/concurrency v0.0.0-20241230205952-55ea9e292314 h1:J1/Ivspw+MnVsXkue3utKNu/82rt9Vp2Yg89XTpcIgA= +github.com/gostdlib/concurrency v0.0.0-20241230205952-55ea9e292314/go.mod h1:dmv3X4RlbpTKviAWCvIS2j2uE6Zq3Kzz5asm8G9UZik= github.com/gostdlib/internals v0.0.0-20240319155855-57c259c0554f h1:qn6pnJHPcKGQqAzEOkgOlNQByQp/3jLvtsRr0USoJr4= github.com/gostdlib/internals v0.0.0-20240319155855-57c259c0554f/go.mod h1:6I+k3gGnSAg+3uYKO1oqlVREtYqqGOXISbcgrCRDuL4= +github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc h1:GN2Lv3MGO7AS6PrRoT6yV5+wkrOpcszoIsO4+4ds248= +github.com/grafana/regexp v0.0.0-20240518133315-a468a5bfb3bc/go.mod h1:+JKpmjMGhpgPL+rXZ5nsZieVzvarn86asRlBg4uNGnk= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/jedib0t/go-pretty/v6 v6.6.7 h1:m+LbHpm0aIAPLzLbMfn8dc3Ht8MW7lsSO4MPItz/Uuo= github.com/jedib0t/go-pretty/v6 v6.6.7/go.mod h1:YwC5CE4fJ1HFUDeivSV1r//AmANFHyqczZk+U6BDALU= -github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= -github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= +github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= +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/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 h1:PpXWgLPs+Fqr325bN2FD2ISlRRztXibcX6e8f5FR5Dc= +github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg= +github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= +github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM= +github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo= +github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4= +github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= +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 v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -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/prometheus/client_golang v1.20.1 h1:IMJXHOD6eARkQpxo8KkhgEVFlBNm+nkrFUyGlIu7Na8= -github.com/prometheus/client_golang v1.20.1/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= -github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= -github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= -github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= -github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= -github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= -github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +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/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= +github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q= +github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0= +github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk= +github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE= +github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE= +github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8= +github.com/prometheus/otlptranslator v0.0.0-20250717125610-8549f4ab4f8f h1:QQB6SuvGZjK8kdc2YaLJpYhV8fxauOsjE6jgcL6YJ8Q= +github.com/prometheus/otlptranslator v0.0.0-20250717125610-8549f4ab4f8f/go.mod h1:P8AwMgdD7XEr6QRUJ2QWLpiAZTgTE2UYgjlu3svompI= +github.com/prometheus/procfs v0.17.0 h1:FuLQ+05u4ZI+SS/w9+BWEM2TXiHKsUQ9TADiRH7DuK0= +github.com/prometheus/procfs v0.17.0/go.mod h1:oPQLaDAMRbA+u8H5Pbfq+dl3VDAvHxMUOVhe0wYB2zw= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= +github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/sanity-io/litter v1.5.8 h1:uM/2lKrWdGbRXDrIq08Lh9XtVYoeGtcQxk9rtQ7+rYg= github.com/sanity-io/litter v1.5.8/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U= +github.com/shirou/gopsutil/v4 v4.25.3 h1:SeA68lsu8gLggyMbmCn8cmp97V1TI9ld9sVzAUcKcKE= +github.com/shirou/gopsutil/v4 v4.25.3/go.mod h1:xbuxyoZj+UsgnZrENu3lQivsngRR5BdjbJwf2fv4szA= +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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tidwall/lotsa v1.0.3 h1:lFAp3PIsS58FPmz+LzhE1mcZ67tBBCRPv5j66g6y7sg= +github.com/tidwall/lotsa v1.0.3/go.mod h1:cPF+z88hamDNDjvE+u3suxCtRMVw24Gvze9eeWGYook= +github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4= +github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4= +github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso= +github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.60.0 h1:kBRYS0lOhVJ6V+bYN8PqAHELKHtXqwq9zNMLKx1MBsw= +github.com/valyala/fasthttp v1.60.0/go.mod h1:iY4kDgV3Gc6EqhRZ8icqcmlG6bqhcDXfuHgTO4FXCvc= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= +github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU= +github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= -go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= -go.opentelemetry.io/otel/exporters/prometheus v0.51.0 h1:G7uexXb/K3T+T9fNLCCKncweEtNEBMTO+46hKX5EdKw= -go.opentelemetry.io/otel/exporters/prometheus v0.51.0/go.mod h1:v0mFe5Kk7woIh938mrZBJBmENYquyA0IICrlYm4Y0t4= -go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= -go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE= -go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo= -go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok= -go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY= -go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ= -go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs= -go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc= -golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= -golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= -google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= +go.opentelemetry.io/contrib/instrumentation/host v0.60.0 h1:LD6TMRg2hfNzkMD36Pq0jeYBcSP9W0aJt41Zmje43Ig= +go.opentelemetry.io/contrib/instrumentation/host v0.60.0/go.mod h1:GN4xnih1u2OQeRs8rNJ13XR8XsTqFopc57e/3Kf0h6c= +go.opentelemetry.io/contrib/instrumentation/runtime v0.60.0 h1:0NgN/3SYkqYJ9NBlDfl/2lzVlwos/YQLvi8sUrzJRBE= +go.opentelemetry.io/contrib/instrumentation/runtime v0.60.0/go.mod h1:oxpUfhTkhgQaYIjtBt3T3w135dLoxq//qo3WPlPIKkE= +go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= +go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0 h1:1fTNlAIJZGWLP5FVu0fikVry1IsiUnXjf7QFvoNN3Xw= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.35.0/go.mod h1:zjPK58DtkqQFn+YUMbx0M2XV3QgKU0gS9LeGohREyK4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0 h1:m639+BofXTvcY1q8CGs4ItwQarYtJPOWmVobfM1HpVI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.35.0/go.mod h1:LjReUci/F4BUyv+y4dwnq3h/26iNOeC3wAIqgvTIZVo= +go.opentelemetry.io/otel/exporters/prometheus v0.59.1 h1:HcpSkTkJbggT8bjYP+BjyqPWlD17BH9C5CYNKeDzmcA= +go.opentelemetry.io/otel/exporters/prometheus v0.59.1/go.mod h1:0FJL+gjuUoM07xzik3KPBaN+nz/CoB15kV6WLMiXZag= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0 h1:T0Ec2E+3YZf5bgTNQVet8iTDW7oIk03tXHq+wkwIDnE= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.35.0/go.mod h1:30v2gqH+vYGJsesLWFov8u47EpYTcIQcBjKpI6pJThg= +go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= +go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= +go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= +go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= +go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= +go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= +go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= +go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4= +go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +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.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8= +golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY= +golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= +golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg= +golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4= +golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA= +golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0= +golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +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.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= +golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e h1:UdXH7Kzbj+Vzastr5nVfccbmFsmYNygVLSPk1pEfDoY= +google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e/go.mod h1:085qFyf2+XaZlRdCgKNCIZ3afY2p4HHZdoIRpId8F4A= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e h1:ztQaXfzEXTmCBvbtWYRhJxW+0iJcz2qXfd38/e9l7bA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= +google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +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/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= +gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= +gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls= +k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k= +k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U= +k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE= +k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU= +k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4= +k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8= +k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e h1:KqK5c/ghOm8xkHYhlodbp6i6+r+ChV2vuAuVRdFbLro= +k8s.io/utils v0.0.0-20250321185631-1f6e0b77f77e/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= +sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= +sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU= +sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY= +sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI= +sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/internal/conn/conn.go b/internal/conn/conn.go index 0575c9d..0df2882 100644 --- a/internal/conn/conn.go +++ b/internal/conn/conn.go @@ -4,20 +4,24 @@ package conn import ( "fmt" "log/slog" - "sync" "sync/atomic" "github.com/Azure/arn-sdk/internal/conn/http" "github.com/Azure/arn-sdk/internal/conn/storage" "github.com/Azure/arn-sdk/models" + "github.com/gostdlib/base/concurrency/sync" + "github.com/gostdlib/base/context" ) // PromisePool is a pool of promises to use for notifications. -var PromisePool = sync.Pool{ - New: func() any { +var PromisePool = sync.NewPool( + context.Background(), + "promisePool", + func() chan error { return make(chan error, 1) }, -} + sync.WithBuffer(10), +) // Reset provides a REST connection to the ARN service. type Service struct { @@ -32,6 +36,7 @@ type Service struct { log *slog.Logger } +// Option is an option for the New constructor. type Option func(*Service) error // WithLogger sets the logger on the client. By default it uses slog.Default(). @@ -98,7 +103,6 @@ func (s *Service) Send(notify models.Notifications) { notify.SendPromise(notify.Ctx().Err(), s.clientErrs) case s.in <- notify: } - return } // sender sends notifications to the ARN service. diff --git a/internal/conn/http/http.go b/internal/conn/http/http.go index cfb955f..1ec8c7e 100644 --- a/internal/conn/http/http.go +++ b/internal/conn/http/http.go @@ -5,15 +5,15 @@ package http import ( "bytes" "compress/zlib" - "context" "fmt" "io" "net/http" "path" - "sync" "testing" "github.com/Azure/arn-sdk/internal/build" + "github.com/gostdlib/base/concurrency/sync" + "github.com/gostdlib/base/context" "github.com/Azure/azure-sdk-for-go/sdk/azcore" "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud" @@ -43,17 +43,23 @@ var changeScope = map[string]bool{ cloud.AzurePublic.ActiveDirectoryAuthorityHost: true, } -var readerPool = sync.Pool{ - New: func() any { +var readerPool = sync.NewPool( + context.Background(), + "readerPool", + func() *bytes.Reader { return bytes.NewReader(nil) }, -} + sync.WithBuffer(10), +) -var flatePool = sync.Pool{ - New: func() any { +var flatePool = sync.NewPool( + context.Background(), + "flatePool", + func() *bytes.Buffer { return &bytes.Buffer{} }, -} + sync.WithBuffer(10), +) // zlibTransport is a custom RoundTripper that applies Deflate compression at the desired level. type zlibTransport struct { @@ -69,6 +75,8 @@ func newFlateTransport() *zlibTransport { // Do performs the actual request and compresses the body using Deflate. func (t *zlibTransport) Do(req *policy.Request) (*http.Response, error) { + ctx := req.Raw().Context() + // Get the underlying http.Request httpReq := req.Raw() @@ -82,10 +90,9 @@ func (t *zlibTransport) Do(req *policy.Request) (*http.Response, error) { } // Compress the content using Deflate at the specified level. - compressedBuffer := flatePool.Get().(*bytes.Buffer) + compressedBuffer := flatePool.Get(ctx) defer func() { - compressedBuffer.Reset() - flatePool.Put(compressedBuffer) + flatePool.Put(ctx, compressedBuffer) }() var writer *zlib.Writer @@ -102,7 +109,9 @@ func (t *zlibTransport) Do(req *policy.Request) (*http.Response, error) { if err != nil { return nil, err } - writer.Close() + if err := writer.Close(); err != nil { + return nil, err + } select { case t.flatePool <- writer: default: @@ -213,9 +222,9 @@ func (c *Client) Send(ctx context.Context, event []byte, headers []string) error return fmt.Errorf("headers must be key-value pairs") } - read := readerPool.Get().(*bytes.Reader) + read := readerPool.Get(ctx) read.Reset(event) - defer readerPool.Put(read) + defer readerPool.Put(ctx, read) req, err := c.setup(ctx, read, headers) if err != nil { diff --git a/internal/conn/storage/credcache.go b/internal/conn/storage/credcache.go index 324de76..ebc108c 100644 --- a/internal/conn/storage/credcache.go +++ b/internal/conn/storage/credcache.go @@ -115,7 +115,7 @@ func (c *credCache) refresher() { ctx := context.Background() for { - next := time.Now().Add(nextRefresh) + next := c.now().Add(nextRefresh) // This will block until the next refresh time. // An error will only be returned if the cache is closed, so it can be ignored. if err := c.refresh(ctx, boff, next); err != nil { diff --git a/internal/conn/storage/fakes_test.go b/internal/conn/storage/fakes_test.go index a26b9e8..46caca7 100644 --- a/internal/conn/storage/fakes_test.go +++ b/internal/conn/storage/fakes_test.go @@ -27,6 +27,30 @@ func (f *fakeUploader) UploadBuffer(ctx context.Context, buffer []byte, o *block return blockblob.UploadBufferResponse{}, f.err } +type fakeTrackingUploader struct { + uploadCount int + data [][]byte + err error + errOnFirst bool // If true, only return error on first call +} + +func (f *fakeTrackingUploader) UploadBuffer(ctx context.Context, buffer []byte, o *blockblob.UploadBufferOptions) (blockblob.UploadBufferResponse, error) { + f.uploadCount++ + // Copy the buffer to track what was uploaded + dataCopy := make([]byte, len(buffer)) + copy(dataCopy, buffer) + f.data = append(f.data, dataCopy) + + // If errOnFirst is true, only return error on first call + if f.errOnFirst && f.uploadCount == 1 { + return blockblob.UploadBufferResponse{}, f.err + } + if !f.errOnFirst { + return blockblob.UploadBufferResponse{}, f.err + } + return blockblob.UploadBufferResponse{}, nil +} + type fakeCreder struct { err error } diff --git a/internal/conn/storage/storage.go b/internal/conn/storage/storage.go index 549212a..c9b6854 100644 --- a/internal/conn/storage/storage.go +++ b/internal/conn/storage/storage.go @@ -29,7 +29,6 @@ Changes from the original: package storage import ( - "context" "fmt" "log/slog" "net/url" @@ -44,6 +43,7 @@ import ( "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/sas" "github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/service" + "github.com/gostdlib/base/context" ) // Client is a client for interacting with Azure Blob Storage for pushing and pulling data @@ -180,7 +180,7 @@ func (c *Client) Upload(ctx context.Context, id string, b []byte) (*url.URL, err u, err := url.Parse(bClient.URL()) if err != nil { - return nil, fmt.Errorf("URL returend by blob client is not a valid URL: %w", err) + return nil, fmt.Errorf("URL returned by blob client is not a valid URL: %w", err) } args := uploadArgs{ @@ -228,16 +228,15 @@ type uploadArgs struct { b []byte } +// upload uploads the the data (args.b) to a container. If the container doesn't exist, it creates it. +// It then returns the URL with an SAS token and returns it. This is used to signal ARN of the blob location. func (c *Client) upload(ctx context.Context, args uploadArgs) (*url.URL, error) { cred, err := c.creds.get(ctx) if err != nil { return nil, err } - // TODO: It would be better if we check for the existence of the container - // before trying to create it. It wasn't immediately obvious how to do that. - _, err = args.upload.UploadBuffer(ctx, args.b, nil) - if err := handleUploadErr(ctx, err, args.create); err != nil { + if err := upload(ctx, args); err != nil { return nil, err } @@ -279,20 +278,21 @@ func (c *Client) signParams(sigVals sas.BlobSignatureValues, cred *service.UserD return ¶ms, nil } -// handleUploadErr handles the error returned by the upload operation. -func handleUploadErr(ctx context.Context, err error, client createContainer) error { - if err == nil { - return nil - } - - if bloberror.HasCode(err, bloberror.ContainerNotFound) { - _, err = client.Create(ctx, nil) - if err == nil || bloberror.HasCode(err, bloberror.ContainerAlreadyExists) { - return nil +func upload(ctx context.Context, args uploadArgs) error { + _, err := args.upload.UploadBuffer(ctx, args.b, nil) + if err != nil { + if bloberror.HasCode(err, bloberror.ContainerNotFound) { + _, err = args.create.Create(ctx, nil) + if err != nil && !bloberror.HasCode(err, bloberror.ContainerAlreadyExists) { + return err + } + // Retry upload after container creation + _, err = args.upload.UploadBuffer(ctx, args.b, nil) + return err } return err } - return err + return nil } // toPtr returns a pointer to any value. Do not replace this with the various diff --git a/internal/conn/storage/storage_test.go b/internal/conn/storage/storage_test.go index ed9b244..bd2c545 100644 --- a/internal/conn/storage/storage_test.go +++ b/internal/conn/storage/storage_test.go @@ -173,78 +173,104 @@ func TestUploadPrivate(t *testing.T) { } } -func TestHandleUploadErr(t *testing.T) { +func TestUploadContainerBug(t *testing.T) { t.Parallel() - cnfErr := &azcore.ResponseError{ - ErrorCode: string(bloberror.ContainerNotFound), - } - contExistErr := &azcore.ResponseError{ - ErrorCode: string(bloberror.ContainerAlreadyExists), - } + ctx := t.Context() + testData := []byte("test data for upload") tests := []struct { - name string - fakeContClient fakeContClient - err error - wantErr bool - wantTryCreate bool + name string + uploaderErr error + errOnFirst bool + containerErr error + wantUploadCount int + wantErr bool }{ { - name: "nil error", - err: nil, - wantErr: false, + name: "Success: should upload only once when successful", + uploaderErr: nil, + containerErr: nil, + wantUploadCount: 1, + wantErr: false, }, { - name: "normal error, not a create container error", - err: errors.New("normal error"), - wantErr: true, + name: "Success: container not found, create succeeds, should retry upload", + uploaderErr: &azcore.ResponseError{ + ErrorCode: string(bloberror.ContainerNotFound), + }, + errOnFirst: true, + containerErr: nil, + wantUploadCount: 2, + wantErr: false, }, { - name: "Container not found, Create() returns a normal error", - fakeContClient: fakeContClient{ - err: errors.New("normal error"), + name: "Success: container not found, already exists, should retry upload", + uploaderErr: &azcore.ResponseError{ + ErrorCode: string(bloberror.ContainerNotFound), + }, + errOnFirst: true, + containerErr: &azcore.ResponseError{ + ErrorCode: string(bloberror.ContainerAlreadyExists), }, - err: cnfErr, - wantTryCreate: true, - wantErr: true, + wantUploadCount: 2, + wantErr: false, }, { - name: "Container not found, Create() returns no error", - fakeContClient: fakeContClient{ - err: nil, + name: "Error: container not found, create fails with other error", + uploaderErr: &azcore.ResponseError{ + ErrorCode: string(bloberror.ContainerNotFound), }, - err: cnfErr, - wantTryCreate: true, + containerErr: errors.New("create failed"), + wantUploadCount: 1, + wantErr: true, }, { - name: "Container not found, Create() returns ContainerAlreadyExists", - fakeContClient: fakeContClient{ - err: contExistErr, - }, - err: cnfErr, - wantTryCreate: true, + name: "Error: upload fails with non-container error", + uploaderErr: errors.New("network error"), + containerErr: nil, + wantUploadCount: 1, + wantErr: true, }, } for _, test := range tests { - fcc := &test.fakeContClient - err := handleUploadErr(context.Background(), test.err, fcc) + uploader := &fakeTrackingUploader{ + err: test.uploaderErr, + errOnFirst: test.errOnFirst, + } + container := &fakeContClient{ + err: test.containerErr, + } - if test.wantTryCreate != fcc.called { - t.Errorf("TestHandleUploadErr(%s): had test.wantTryCreate == %v, Create.called == %v", test.name, test.wantTryCreate, fcc.called) - continue + args := uploadArgs{ + b: testData, + upload: uploader, + create: container, } + + err := upload(ctx, args) + switch { case test.wantErr && err == nil: - t.Errorf("TestHandleUploadErr(%s): got err == nil, want err != nil", test.name) + t.Errorf("TestUploadContainerBug(%s): got err == nil, want err != nil", test.name) continue case !test.wantErr && err != nil: - t.Errorf("TestHandleUploadErr(%s): got err != nil, want err == nil", test.name) + t.Errorf("TestUploadContainerBug(%s): got err == %s, want err == nil", test.name, err) continue } - } + if uploader.uploadCount != test.wantUploadCount { + t.Errorf("TestUploadContainerBug(%s): upload called %d times, want %d times", test.name, uploader.uploadCount, test.wantUploadCount) + } + + // Verify that the same data was uploaded each time + for i, data := range uploader.data { + if string(data) != string(testData) { + t.Errorf("TestUploadContainerBug(%s): upload %d had wrong data: got %q, want %q", test.name, i+1, string(data), string(testData)) + } + } + } } func TestCName(t *testing.T) { diff --git a/models/metrics/metrics.go b/models/metrics/metrics.go index 9da137f..866c18a 100644 --- a/models/metrics/metrics.go +++ b/models/metrics/metrics.go @@ -1,11 +1,11 @@ package metrics import ( - "context" "errors" "fmt" "time" + "github.com/gostdlib/base/context" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" @@ -13,7 +13,7 @@ import ( ) const ( - subsystem = "arn-sdk" + subsystem = "arn_sdk" successLabel = "success" errorLabel = "error" inlineLabel = "inline" @@ -43,12 +43,12 @@ func metricName(name string) string { // Init initializes the arn sdk model metrics. This should only be called by the tattler constructor or tests. func Init(meter metric.Meter) error { var err error - events.sent, err = meter.Int64Counter(metricName("event_sent_total"), metric.WithDescription("total number of events sent by the ARN client")) + events.sent, err = meter.Int64Counter(metricName("event_sent"), metric.WithDescription("total number of events sent by the ARN client")) if err != nil { return err } - events.bytes, err = meter.Int64Counter(metricName("event_sent_bytes_total"), metric.WithDescription("total number of bytes in event data sent by the ARN client")) + events.bytes, err = meter.Int64Counter(metricName("event_sent_bytes"), metric.WithDescription("total number of bytes in event data sent by the ARN client")) if err != nil { return err } @@ -63,7 +63,7 @@ func Init(meter metric.Meter) error { return err } - promises.completed, err = meter.Int64Counter(metricName("promise_total"), metric.WithDescription("total number of promises made by the ARN client")) + promises.completed, err = meter.Int64Counter(metricName("promise"), metric.WithDescription("total number of promises made by the ARN client")) if err != nil { return err } diff --git a/models/metrics/testdata/models_happy.txt b/models/metrics/testdata/models_happy.txt index 53c5fa1..e779d75 100644 --- a/models/metrics/testdata/models_happy.txt +++ b/models/metrics/testdata/models_happy.txt @@ -1,64 +1,61 @@ # HELP arn_sdk_current_promise_count current number of promises made by the ARN client # TYPE arn_sdk_current_promise_count gauge -arn_sdk_current_promise_count{otel_scope_name="testmeter",otel_scope_version="v0.1.0"} 0 +arn_sdk_current_promise_count{otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0"} 0 # HELP arn_sdk_event_sent_bytes_total total number of bytes in event data sent by the ARN client # TYPE arn_sdk_event_sent_bytes_total counter -arn_sdk_event_sent_bytes_total{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false"} 0 -arn_sdk_event_sent_bytes_total{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true"} 40000 +arn_sdk_event_sent_bytes_total{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false"} 0 +arn_sdk_event_sent_bytes_total{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true"} 40000 # HELP arn_sdk_event_sent_ms time spent to send ARN event # TYPE arn_sdk_event_sent_ms histogram -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="50"} 0 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="100"} 0 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="200"} 0 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="400"} 0 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="600"} 0 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="800"} 0 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="1000"} 1 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="1250"} 1 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="1500"} 1 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="2000"} 1 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="3000"} 1 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="4000"} 1 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="5000"} 1 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="10000"} 1 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="60000"} 1 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="300000"} 1 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="600000"} 1 -arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false",le="+Inf"} 1 -arn_sdk_event_sent_ms_sum{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false"} 1000 -arn_sdk_event_sent_ms_count{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false"} 1 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="50"} 0 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="100"} 0 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="200"} 0 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="400"} 0 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="600"} 0 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="800"} 0 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="1000"} 1 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="1250"} 1 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="1500"} 1 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="2000"} 1 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="3000"} 1 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="4000"} 1 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="5000"} 1 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="10000"} 1 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="60000"} 1 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="300000"} 1 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="600000"} 1 -arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true",le="+Inf"} 1 -arn_sdk_event_sent_ms_sum{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true"} 1000 -arn_sdk_event_sent_ms_count{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true"} 1 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="50"} 0 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="100"} 0 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="200"} 0 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="400"} 0 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="600"} 0 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="800"} 0 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="1000"} 1 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="1250"} 1 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="1500"} 1 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="2000"} 1 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="3000"} 1 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="4000"} 1 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="5000"} 1 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="10000"} 1 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="60000"} 1 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="300000"} 1 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="600000"} 1 +arn_sdk_event_sent_ms_bucket{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false",le="+Inf"} 1 +arn_sdk_event_sent_ms_sum{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false"} 1000 +arn_sdk_event_sent_ms_count{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false"} 1 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="50"} 0 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="100"} 0 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="200"} 0 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="400"} 0 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="600"} 0 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="800"} 0 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="1000"} 1 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="1250"} 1 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="1500"} 1 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="2000"} 1 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="3000"} 1 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="4000"} 1 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="5000"} 1 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="10000"} 1 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="60000"} 1 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="300000"} 1 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="600000"} 1 +arn_sdk_event_sent_ms_bucket{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true",le="+Inf"} 1 +arn_sdk_event_sent_ms_sum{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true"} 1000 +arn_sdk_event_sent_ms_count{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true"} 1 # HELP arn_sdk_event_sent_total total number of events sent by the ARN client # TYPE arn_sdk_event_sent_total counter -arn_sdk_event_sent_total{inline="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="false"} 1 -arn_sdk_event_sent_total{inline="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",success="true"} 1 +arn_sdk_event_sent_total{inline="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="false"} 1 +arn_sdk_event_sent_total{inline="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",success="true"} 1 # HELP arn_sdk_promise_total total number of promises made by the ARN client # TYPE arn_sdk_promise_total counter -arn_sdk_promise_total{error="false",otel_scope_name="testmeter",otel_scope_version="v0.1.0",timeout="false"} 1 -arn_sdk_promise_total{error="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",timeout="false"} 1 -arn_sdk_promise_total{error="true",otel_scope_name="testmeter",otel_scope_version="v0.1.0",timeout="true"} 1 -# HELP otel_scope_info Instrumentation Scope metadata -# TYPE otel_scope_info gauge -otel_scope_info{otel_scope_name="testmeter",otel_scope_version="v0.1.0"} 1 +arn_sdk_promise_total{error="false",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",timeout="false"} 1 +arn_sdk_promise_total{error="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",timeout="false"} 1 +arn_sdk_promise_total{error="true",otel_scope_name="testmeter",otel_scope_schema_url="",otel_scope_version="v0.1.0",timeout="true"} 1 # HELP target_info Target metadata # TYPE target_info gauge -target_info{service_name="arn_test",telemetry_sdk_language="go",telemetry_sdk_name="opentelemetry",telemetry_sdk_version="latest"} 1 +target_info{"service.name"="arn_test","telemetry.sdk.language"="go","telemetry.sdk.name"="opentelemetry","telemetry.sdk.version"="latest"} 1 diff --git a/models/metrics/testdata/models_nometrics.txt b/models/metrics/testdata/models_nometrics.txt index bcd25e9..f122e07 100644 --- a/models/metrics/testdata/models_nometrics.txt +++ b/models/metrics/testdata/models_nometrics.txt @@ -1,4 +1,4 @@ # HELP target_info Target metadata # TYPE target_info gauge -target_info{service_name="arn_test",telemetry_sdk_language="go",telemetry_sdk_name="opentelemetry",telemetry_sdk_version="latest"} 1 +target_info{"service.name"="arn_test","telemetry.sdk.language"="go","telemetry.sdk.name"="opentelemetry","telemetry.sdk.version"="latest"} 1 diff --git a/models/v3/msgs/msgs.go b/models/v3/msgs/msgs.go index 3d46f22..d7cf5e0 100644 --- a/models/v3/msgs/msgs.go +++ b/models/v3/msgs/msgs.go @@ -1,13 +1,12 @@ +// Package msgs provides the Notifications type which is used to send notifications to the ARN service. package msgs import ( - "context" "errors" "fmt" "log/slog" "math" "net/url" - "sync" "time" "github.com/Azure/arn-sdk/internal/conn" @@ -19,6 +18,8 @@ import ( "github.com/Azure/arn-sdk/models/v3/schema/envelope" "github.com/Azure/arn-sdk/models/v3/schema/types" "github.com/Azure/arn-sdk/models/version" + "github.com/gostdlib/base/concurrency/sync" + "github.com/gostdlib/base/context" "github.com/go-json-experiment/json" "github.com/google/uuid" @@ -64,7 +65,7 @@ func (n Notifications) Promise(ctx context.Context) error { return nil } defer func() { - conn.PromisePool.Put(n.promise) + conn.PromisePool.Put(ctx, n.promise) }() if ctx.Err() != nil { @@ -91,11 +92,14 @@ func (n Notifications) Recycle() { case <-n.promise: default: } - conn.PromisePool.Put(n.promise) + conn.PromisePool.Put(context.Background(), n.promise) } } func (n Notifications) Ctx() context.Context { + if n.ctx == nil { + return context.Background() + } return n.ctx } @@ -263,11 +267,14 @@ func (n Notifications) toEvent() ([]byte, envelope.Event, error) { }, nil } -var headerPool = sync.Pool{ - New: func() any { - return make([]string, 2) +var headerPool = sync.NewPool( + context.Background(), + "headerPool", + func() []string { + return make([]string, 2) // Two headers: "publisherinfo" and the actual publisher info. }, -} + sync.WithBuffer(100), // Preallocate a pool of 100 header slices to avoid allocations during sendHTTP. +) func (n Notifications) sendHTTP(hc *http.Client, event envelope.Event) error { if n.testSendHTTP != nil { @@ -279,12 +286,12 @@ func (n Notifications) sendHTTP(hc *http.Client, event envelope.Event) error { return err } - headers := headerPool.Get().([]string) + headers := headerPool.Get(n.Ctx()) headers[0] = "publisherinfo" headers[1] = event.Data.PublisherInfo - defer headerPool.Put(headers) + defer headerPool.Put(n.Ctx(), headers) - return hc.Send(n.ctx, b, headers) + return hc.Send(n.Ctx(), b, headers) } func (n Notifications) sendBlob(store *storage.Client, dataJSON []byte) (*url.URL, error) { diff --git a/models/v3/schema/types/types.go b/models/v3/schema/types/types.go index 5b9071c..d524118 100644 --- a/models/v3/schema/types/types.go +++ b/models/v3/schema/types/types.go @@ -79,7 +79,7 @@ type Data struct { // TODO: Need to write some tests for this. func (d Data) Validate() error { if d.ResourcesContainer == 0 || d.ResourcesContainer >= ResourcesContainer(len(_ResourcesContainer_index)-1) { - return fmt.Errorf(".ChangedAction(%d) is invalid", d.ResourcesContainer) + return fmt.Errorf(".ResourcesContainer(%d) is invalid", d.ResourcesContainer) } switch d.ResourcesContainer {