├── .github ├── dependabot.yml └── workflows │ ├── go.yml │ └── release.yml ├── .gitignore ├── .travis.yml ├── Dockerfile ├── LICENSE ├── README.md ├── go.mod ├── go.sum ├── kod_gen.go ├── main.go └── tools.go /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | - package-ecosystem: gomod 5 | directory: / 6 | labels: 7 | - dependencies 8 | schedule: 9 | interval: "weekly" 10 | groups: 11 | gomod-normal-deps: 12 | update-types: 13 | - patch 14 | - minor 15 | gomod-breaking-deps: 16 | update-types: 17 | - major 18 | 19 | - package-ecosystem: "github-actions" 20 | directory: "/" 21 | labels: 22 | - dependencies 23 | schedule: 24 | interval: "weekly" 25 | groups: 26 | actions-deps: 27 | patterns: 28 | - "*" 29 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | branches: 6 | - "master" 7 | pull_request: 8 | branches: 9 | - "master" 10 | 11 | jobs: 12 | build: 13 | name: Build 14 | runs-on: ubuntu-latest 15 | strategy: 16 | fail-fast: true 17 | matrix: 18 | go: ["1.21.x"] 19 | 20 | steps: 21 | - name: Set up Go ${{ matrix.go }} 22 | uses: actions/setup-go@v5 23 | with: 24 | go-version: ${{ matrix.go }} 25 | id: go 26 | 27 | - name: Check out code into the Go module directory 28 | uses: actions/checkout@v4.2.2 29 | 30 | - uses: actions/cache@v4 31 | with: 32 | path: | 33 | ~/go/pkg/mod 34 | ~/.cache/go-build 35 | key: ${{ runner.os }}-go-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }} 36 | restore-keys: | 37 | ${{ runner.os }}-go-${{ matrix.go-version }}- 38 | 39 | - name: Run GoReleaser 40 | uses: goreleaser/goreleaser-action@v6 41 | with: 42 | # either 'goreleaser' (default) or 'goreleaser-pro' 43 | distribution: goreleaser 44 | version: latest 45 | args: release --snapshot 46 | env: 47 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 48 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v**" 7 | 8 | jobs: 9 | build: 10 | name: Build 11 | runs-on: ubuntu-latest 12 | strategy: 13 | fail-fast: true 14 | matrix: 15 | go: ["1.21.x"] 16 | 17 | steps: 18 | - name: Set up Go ${{ matrix.go }} 19 | uses: actions/setup-go@v5 20 | with: 21 | go-version: ${{ matrix.go }} 22 | id: go 23 | 24 | - name: Check out code into the Go module directory 25 | uses: actions/checkout@v4.2.2 26 | 27 | - uses: actions/cache@v4 28 | with: 29 | path: | 30 | ~/go/pkg/mod 31 | ~/.cache/go-build 32 | key: ${{ runner.os }}-go-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }} 33 | restore-keys: | 34 | ${{ runner.os }}-go-${{ matrix.go-version }}- 35 | 36 | - name: Run GoReleaser 37 | uses: goreleaser/goreleaser-action@v6 38 | with: 39 | # either 'goreleaser' (default) or 'goreleaser-pro' 40 | distribution: goreleaser 41 | version: latest 42 | args: release 43 | env: 44 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 45 | 46 | - name: Build and push Docker image to docker.io 47 | uses: mr-smithers-excellent/docker-build-push@v6.4 48 | with: 49 | registry: docker.io 50 | image: sophos/nginx-vtx-exporter 51 | multiPlatform: true 52 | addLatest: true 53 | directory: . 54 | dockerfile: Dockerfile 55 | username: ${{ secrets.DOCKER_USER }} 56 | password: ${{ secrets.DOCKER_PASS }} 57 | 58 | - name: Build and push Docker image to ghcr.io 59 | uses: mr-smithers-excellent/docker-build-push@v6.4 60 | with: 61 | registry: ghcr.io 62 | image: nginx-vtx-exporter 63 | multiPlatform: true 64 | addLatest: true 65 | directory: . 66 | dockerfile: Dockerfile 67 | username: ${{ github.actor }} 68 | password: ${{ secrets.GITHUB_TOKEN }} 69 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files, Static and Dynamic libs (Shared Objects) 2 | *.o 3 | *.a 4 | *.so 5 | 6 | # Folders 7 | _obj 8 | _test 9 | 10 | # Architecture specific extensions/prefixes 11 | *.[568vq] 12 | [568vq].out 13 | 14 | *.cgo1.go 15 | *.cgo2.c 16 | _cgo_defun.c 17 | _cgo_gotypes.go 18 | _cgo_export.* 19 | 20 | _testmain.go 21 | 22 | *.exe 23 | *.test 24 | *.prof 25 | level.db/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | services: 4 | - docker 5 | 6 | language: go 7 | 8 | go: 9 | - 1.9.4 10 | 11 | after_success: 12 | - env GOOS=linux GOARCH=386 go build 13 | - echo $DOCKER_PASS | docker login -u "$DOCKER_USER" --password-stdin 14 | - export REPO=sophos/httpmq 15 | - export TAG=`if [ "$TRAVIS_BRANCH" == "master" ]; then echo "latest"; else echo $TRAVIS_BRANCH ; fi` 16 | - echo $REPO:$TAG 17 | - docker build -f Dockerfile -t $REPO:$TRAVIS_COMMIT . 18 | - docker tag $REPO:$TRAVIS_COMMIT $REPO:$TAG 19 | - docker push $REPO:$TAG -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:latest 2 | 3 | COPY httpmq /bin/httpmq 4 | 5 | EXPOSE 1218 6 | CMD [ "httpmq" ] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Sophos 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | httpmq 2 | ====== 3 | [![Build Status](https://travis-ci.org/sysulq/httpmq.svg?branch=master)](https://travis-ci.org/sysulq/httpmq) 4 | [![Docker Pulls](https://img.shields.io/docker/pulls/sophos/httpmq.svg)](https://hub.docker.com/r/sophos/httpmq/) 5 | [![Go Report Card](https://goreportcard.com/badge/github.com/sysulq/httpmq)](https://goreportcard.com/report/github.com/sysulq/httpmq) 6 | 7 | > httpmq is powered by [Kod](https://github.com/go-kod/kod), which is a dependency injection framework for Go. 8 | > It is designed to be simple and easy to use, and to provide a consistent way to manage dependencies across your application. 9 | 10 | Httpmq is a simple HTTP message queue written in Go with goleveldb, just like httpsqs wriiten in C with Tokyo Cabinet. 11 | 12 | Also, you can refer to [github.com/sysulq/httpmq-rs#benchmark](https://github.com/sysulq/httpmq-rs#benchmark) for the benchmark of **Rust** implementation. 13 | 14 | Feature 15 | ====== 16 | 17 | * Very simple, less than 300 lines Go code. 18 | * Very fast, more than 10000 requests/sec. 19 | * High concurrency, support the tens of thousands of concurrent connections. 20 | * Multiple queue. 21 | * Low memory consumption, mass data storage, storage dozens of GB of data takes less than 100MB of physical memory buffer. 22 | * Convenient to change the maximum queue length of per-queue. 23 | * Queue status view. 24 | * Be able to view the contents of the specified queue ID. 25 | * Multi-Character encoding support. 26 | 27 | Usage 28 | ====== 29 | Docker 30 | ``` 31 | docker run -d -it -p 1218:1218 sophos/httpmq 32 | ``` 33 | 34 | Binary 35 | ``` 36 | Usage of ./httpmq: 37 | -auth string 38 | auth password to access httpmq 39 | -buffer int 40 | write buffer(MB) (default 32) 41 | -cache int 42 | cache size(MB) (default 64) 43 | -cpu int 44 | cpu number for httpmq (default 4) 45 | -db string 46 | database path (default "level.db") 47 | -ip string 48 | ip address to listen on (default "0.0.0.0") 49 | -k int 50 | keepalive timeout for httpmq (default 60) 51 | -maxqueue int 52 | the max queue length (default 1000000) 53 | -port string 54 | port to listen on (default "1218") 55 | ``` 56 | 57 | 1. PUT text message into a queue 58 | 59 | HTTP GET protocol (Using curl for example): 60 | ``` 61 | curl "http://host:port/?name=your_queue_name&opt=put&data=url_encoded_text_message&auth=mypass123" 62 | ``` 63 | HTTP POST protocol (Using curl for example): 64 | ``` 65 | curl -d "url_encoded_text_message" "http://host:port/?name=your_queue_name&opt=put&auth=mypass123" 66 | ``` 67 | 68 | 2. GET text message from a queue 69 | 70 | HTTP GET protocol (Using curl for example): 71 | ``` 72 | curl "http://host:port/?charset=utf-8&name=your_queue_name&opt=get&auth=mypass123" 73 | ``` 74 | 75 | 3. View queue status 76 | 77 | HTTP GET protocol (Using curl for example): 78 | ``` 79 | curl "http://host:port/?name=your_queue_name&opt=status&auth=mypass123" 80 | ``` 81 | 4. View queue details 82 | 83 | HTTP GET protocol (Using curl for example): 84 | ``` 85 | curl "http://host:port/?name=your_queue_name&opt=view&pos=1&auth=mypass123" 86 | ``` 87 | 5. Reset queue 88 | 89 | HTTP GET protocol (Using curl for example): 90 | ``` 91 | curl "http://host:port/?name=your_queue_name&opt=reset&pos=1&auth=mypass123" 92 | ``` 93 | 94 | Benchmark 95 | ======== 96 | 97 | Test machine(Hackintosh): 98 | 99 | ```text 100 | 'c. 101 | ,xNMM. ----------------------- 102 | .OMMMMo OS: macOS 11.6.1 20G224 x86_64 103 | OMMM0, Host: Hackintosh (SMBIOS: iMac20,1) 104 | .;loddo:' loolloddol;. Kernel: 20.6.0 105 | cKMMMMMMMMMMNWMMMMMMMMMM0: Uptime: 13 hours, 16 mins 106 | .KMMMMMMMMMMMMMMMMMMMMMMMWd. Packages: 45 (brew) 107 | XMMMMMMMMMMMMMMMMMMMMMMMX. Shell: zsh 5.8 108 | ;MMMMMMMMMMMMMMMMMMMMMMMM: Resolution: 1920x1080@2x 109 | :MMMMMMMMMMMMMMMMMMMMMMMM: DE: Aqua 110 | .MMMMMMMMMMMMMMMMMMMMMMMMX. WM: Quartz Compositor 111 | kMMMMMMMMMMMMMMMMMMMMMMMMWd. WM Theme: Blue (Dark) 112 | .XMMMMMMMMMMMMMMMMMMMMMMMMMMk Terminal: vscode 113 | .XMMMMMMMMMMMMMMMMMMMMMMMMK. CPU: Intel i5-10600K (12) @ 4.10GHz 114 | kMMMMMMMMMMMMMMMMMMMMMMd GPU: Radeon Pro W5500X 115 | ;KMMMMMMMWXXWMMMMMMMk. Memory: 17549MiB / 32768MiB 116 | .cooc,. .,coo:. 117 | ``` 118 | 119 | fasthttp 120 | -------- 121 | ### PUT queue: 122 | 123 | ```bash 124 | wrk -c 10 -t 2 -d 10s "http://127.0.0.1:1218/?name=xoyo&opt=put&data=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 125 | Running 10s test @ http://127.0.0.1:1218/?name=xoyo&opt=put&data=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa 126 | 2 threads and 10 connections 127 | Thread Stats Avg Stdev Max +/- Stdev 128 | Latency 211.87us 169.58us 4.97ms 98.28% 129 | Req/Sec 24.36k 2.23k 27.87k 64.36% 130 | 489524 requests in 10.10s, 82.64MB read 131 | Requests/sec: 48459.16 132 | Transfer/sec: 8.18MB 133 | ``` 134 | 135 | ### GET queue: 136 | 137 | ```bash 138 | wrk -c 10 -t 2 -d 10s "http://127.0.0.1:1218/?name=xoyo&opt=get" 139 | Running 10s test @ http://127.0.0.1:1218/?name=xoyo&opt=get 140 | 2 threads and 10 connections 141 | Thread Stats Avg Stdev Max +/- Stdev 142 | Latency 218.26us 251.84us 11.56ms 99.22% 143 | Req/Sec 23.37k 1.06k 24.70k 90.59% 144 | 469685 requests in 10.10s, 303.14MB read 145 | Requests/sec: 46504.02 146 | Transfer/sec: 30.01MB 147 | ``` 148 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/sysulq/httpmq 2 | 3 | go 1.21.7 4 | 5 | toolchain go1.22.4 6 | 7 | require ( 8 | github.com/go-kod/kod v0.14.0 9 | github.com/syndtr/goleveldb v0.0.0-20210819022825-2ae1ddf74ef7 10 | ) 11 | 12 | require ( 13 | github.com/beorn7/perks v1.0.1 // indirect 14 | github.com/cenkalti/backoff/v4 v4.3.0 // indirect 15 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 16 | github.com/dominikbraun/graph v0.23.0 // indirect 17 | github.com/fsnotify/fsnotify v1.7.0 // indirect 18 | github.com/go-logr/logr v1.4.2 // indirect 19 | github.com/go-logr/stdr v1.2.2 // indirect 20 | github.com/go-ole/go-ole v1.3.0 // indirect 21 | github.com/golang/snappy v0.0.4 // indirect 22 | github.com/google/uuid v1.6.0 // indirect 23 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 // indirect 24 | github.com/hashicorp/hcl v1.0.0 // indirect 25 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 26 | github.com/klauspost/compress v1.17.9 // indirect 27 | github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7 // indirect 28 | github.com/magiconair/properties v1.8.7 // indirect 29 | github.com/mitchellh/mapstructure v1.5.0 // indirect 30 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 31 | github.com/onsi/ginkgo v1.16.5 // indirect 32 | github.com/onsi/gomega v1.17.0 // indirect 33 | github.com/pelletier/go-toml/v2 v2.2.2 // indirect 34 | github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect 35 | github.com/prometheus/client_golang v1.20.1 // indirect 36 | github.com/prometheus/client_model v0.6.1 // indirect 37 | github.com/prometheus/common v0.55.0 // indirect 38 | github.com/prometheus/procfs v0.15.1 // indirect 39 | github.com/sagikazarmark/locafero v0.6.0 // indirect 40 | github.com/sagikazarmark/slog-shim v0.1.0 // indirect 41 | github.com/samber/lo v1.47.0 // indirect 42 | github.com/shirou/gopsutil/v4 v4.24.7 // indirect 43 | github.com/shoenig/go-m1cpu v0.1.6 // indirect 44 | github.com/sourcegraph/conc v0.3.0 // indirect 45 | github.com/spf13/afero v1.11.0 // indirect 46 | github.com/spf13/cast v1.6.0 // indirect 47 | github.com/spf13/cobra v1.8.1 // indirect 48 | github.com/spf13/pflag v1.0.5 // indirect 49 | github.com/spf13/viper v1.19.0 // indirect 50 | github.com/subosito/gotenv v1.6.0 // indirect 51 | github.com/tklauser/go-sysconf v0.3.14 // indirect 52 | github.com/tklauser/numcpus v0.8.0 // indirect 53 | github.com/yusufpapurcu/wmi v1.2.4 // indirect 54 | go.opentelemetry.io/contrib/bridges/otelslog v0.4.0 // indirect 55 | go.opentelemetry.io/contrib/bridges/prometheus v0.54.0 // indirect 56 | go.opentelemetry.io/contrib/exporters/autoexport v0.54.0 // indirect 57 | go.opentelemetry.io/contrib/instrumentation/host v0.54.0 // indirect 58 | go.opentelemetry.io/contrib/instrumentation/runtime v0.54.0 // indirect 59 | go.opentelemetry.io/otel v1.29.0 // indirect 60 | go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.5.0 // indirect 61 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 // indirect 62 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0 // indirect 63 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 // indirect 64 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 // indirect 65 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0 // indirect 66 | go.opentelemetry.io/otel/exporters/prometheus v0.51.0 // indirect 67 | go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.5.0 // indirect 68 | go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 // indirect 69 | go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.29.0 // indirect 70 | go.opentelemetry.io/otel/log v0.5.0 // indirect 71 | go.opentelemetry.io/otel/metric v1.29.0 // indirect 72 | go.opentelemetry.io/otel/sdk v1.29.0 // indirect 73 | go.opentelemetry.io/otel/sdk/log v0.5.0 // indirect 74 | go.opentelemetry.io/otel/sdk/metric v1.29.0 // indirect 75 | go.opentelemetry.io/otel/trace v1.29.0 // indirect 76 | go.opentelemetry.io/proto/otlp v1.3.1 // indirect 77 | go.uber.org/multierr v1.11.0 // indirect 78 | golang.org/x/exp v0.0.0-20240707233637-46b078467d37 // indirect 79 | golang.org/x/mod v0.20.0 // indirect 80 | golang.org/x/net v0.28.0 // indirect 81 | golang.org/x/sync v0.8.0 // indirect 82 | golang.org/x/sys v0.24.0 // indirect 83 | golang.org/x/text v0.17.0 // indirect 84 | golang.org/x/tools v0.24.0 // indirect 85 | google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd // indirect 86 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd // indirect 87 | google.golang.org/grpc v1.65.0 // indirect 88 | google.golang.org/protobuf v1.34.2 // indirect 89 | gopkg.in/ini.v1 v1.67.0 // indirect 90 | gopkg.in/yaml.v3 v3.0.1 // indirect 91 | ) 92 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 2 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 3 | github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= 4 | github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= 5 | github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= 6 | github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 7 | github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 8 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 10 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= 11 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 12 | github.com/dominikbraun/graph v0.23.0 h1:TdZB4pPqCLFxYhdyMFb1TBdFxp8XLcJfTTBQucVPgCo= 13 | github.com/dominikbraun/graph v0.23.0/go.mod h1:yOjYyogZLY1LSG9E33JWZJiq5k83Qy2C6POAuiViluc= 14 | github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= 15 | github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= 16 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 17 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 18 | github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= 19 | github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= 20 | github.com/go-kod/kod v0.14.0 h1:/Jk1AwdOJHYbES61tyTb571BvTdCbsaog9VjCPixE+M= 21 | github.com/go-kod/kod v0.14.0/go.mod h1:vMZaI5XcDwXf8paya7V7NREiyfgG9GFokezb3ohEEd8= 22 | github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 23 | github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= 24 | github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 25 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 26 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 27 | github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= 28 | github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= 29 | github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= 30 | github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= 31 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 32 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 33 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 34 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 35 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 36 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 37 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 38 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 39 | github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 40 | github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= 41 | github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 42 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 43 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 44 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 45 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 46 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 47 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 48 | github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= 49 | github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 50 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0 h1:asbCHRVmodnJTuQ3qamDwqVOIjwqUPTYmYuemVOx+Ys= 51 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.22.0/go.mod h1:ggCgvZ2r7uOoQjOyu2Y1NhHmEPPzzuhWgcza5M1Ji1I= 52 | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= 53 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= 54 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 55 | github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= 56 | github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 57 | github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= 58 | github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= 59 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 60 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 61 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 62 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 63 | github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= 64 | github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= 65 | github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7 h1:5RK988zAqB3/AN3opGfRpoQgAVqr6/A5+qRTi67VUZY= 66 | github.com/lufia/plan9stats v0.0.0-20240819163618-b1d8f4d146e7/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k= 67 | github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= 68 | github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= 69 | github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= 70 | github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 71 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= 72 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 73 | github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= 74 | github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= 75 | github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= 76 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 77 | github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= 78 | github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= 79 | github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= 80 | github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= 81 | github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= 82 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 83 | github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= 84 | github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE= 85 | github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= 86 | github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= 87 | github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= 88 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 89 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= 90 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 91 | github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU= 92 | github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= 93 | github.com/prometheus/client_golang v1.20.1 h1:IMJXHOD6eARkQpxo8KkhgEVFlBNm+nkrFUyGlIu7Na8= 94 | github.com/prometheus/client_golang v1.20.1/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE= 95 | github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= 96 | github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= 97 | github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= 98 | github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= 99 | github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= 100 | github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= 101 | github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= 102 | github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= 103 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 104 | github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk= 105 | github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0= 106 | github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= 107 | github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= 108 | github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc= 109 | github.com/samber/lo v1.47.0/go.mod h1:RmDH9Ct32Qy3gduHQuKJ3gW1fMHAnE/fAzQuf6He5cU= 110 | github.com/shirou/gopsutil/v4 v4.24.7 h1:V9UGTK4gQ8HvcnPKf6Zt3XHyQq/peaekfxpJ2HSocJk= 111 | github.com/shirou/gopsutil/v4 v4.24.7/go.mod h1:0uW/073rP7FYLOkvxolUQM5rMOLTNmRXnFKafpb71rw= 112 | github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= 113 | github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= 114 | github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= 115 | github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= 116 | github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= 117 | github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= 118 | github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= 119 | github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= 120 | github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= 121 | github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= 122 | github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= 123 | github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= 124 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 125 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 126 | github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= 127 | github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= 128 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 129 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 130 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 131 | github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= 132 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 133 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 134 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 135 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 136 | github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= 137 | github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 138 | github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= 139 | github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= 140 | github.com/syndtr/goleveldb v0.0.0-20210819022825-2ae1ddf74ef7 h1:xJagxODKlf7bGNoyZzg2nFkzvVfFdK/eJbikhCVBm3s= 141 | github.com/syndtr/goleveldb v0.0.0-20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= 142 | github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU= 143 | github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY= 144 | github.com/tklauser/numcpus v0.8.0 h1:Mx4Wwe/FjZLeQsK/6kt2EOepwwSl7SmJrK5bV/dXYgY= 145 | github.com/tklauser/numcpus v0.8.0/go.mod h1:ZJZlAY+dmR4eut8epnzf0u/VwodKmryxR8txiloSqBE= 146 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 147 | github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= 148 | github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= 149 | go.opentelemetry.io/contrib/bridges/otelslog v0.4.0 h1:i66F95zqmrf3EyN5gu0E2pjTvCRZo/p8XIYidG3vOP8= 150 | go.opentelemetry.io/contrib/bridges/otelslog v0.4.0/go.mod h1:JuCiVizZ6ovLZLnYk1nGRUEAnmRJLKGh5v8DmwiKlhY= 151 | go.opentelemetry.io/contrib/bridges/prometheus v0.54.0 h1:WWL67oxtknNVMb70lJXxXruf8UyK/a9hmIE1XO3Uedg= 152 | go.opentelemetry.io/contrib/bridges/prometheus v0.54.0/go.mod h1:LqNcnXmyULp8ertk4hUTVtSUvKXj4h1Mx7gUCSSr/q0= 153 | go.opentelemetry.io/contrib/exporters/autoexport v0.54.0 h1:dTmcmVm4J54IRPGm5oVjLci1uYat4UDea84E2tyBaAk= 154 | go.opentelemetry.io/contrib/exporters/autoexport v0.54.0/go.mod h1:zPp5Fwpq2Hc7xMtVttg6GhZMcfTESjVbY9ONw2o/Dc4= 155 | go.opentelemetry.io/contrib/instrumentation/host v0.54.0 h1:ForLwWOQDIhZZdaf09H0Cy82jBWIQhWLn/tqzclD36E= 156 | go.opentelemetry.io/contrib/instrumentation/host v0.54.0/go.mod h1:LV9KQI6PdSf+TTg4npgD7FzPo/80CuyLekiHiCd1nt8= 157 | go.opentelemetry.io/contrib/instrumentation/runtime v0.54.0 h1:KD+8SJvRaW9n0vE0UgkytT207J3CmV1hGf9GYYU73ns= 158 | go.opentelemetry.io/contrib/instrumentation/runtime v0.54.0/go.mod h1:/CsTuLR28IN3Vn13YEc72HljfHiGOMXiCbl4xiCSDhA= 159 | go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw= 160 | go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8= 161 | go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.5.0 h1:4d++HQ+Ihdl+53zSjtsCUFDmNMju2FC9qFkUlTxPLqo= 162 | go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.5.0/go.mod h1:mQX5dTO3Mh5ZF7bPKDkt5c/7C41u/SiDr9XgTpzXXn8= 163 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0 h1:k6fQVDQexDE+3jG2SfCQjnHS7OamcP73YMoxEVq5B6k= 164 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.29.0/go.mod h1:t4BrYLHU450Zo9fnydWlIuswB1bm7rM8havDpWOJeDo= 165 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0 h1:xvhQxJ/C9+RTnAj5DpTg7LSM1vbbMTiXt7e9hsfqHNw= 166 | go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.29.0/go.mod h1:Fcvs2Bz1jkDM+Wf5/ozBGmi3tQ/c9zPKLnsipnfhGAo= 167 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrTgKIMLkus6jEFa7x5SOKcyR7E= 168 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI= 169 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0 h1:nSiV3s7wiCam610XcLbYOmMfJxB9gO4uK3Xgv5gmTgg= 170 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.29.0/go.mod h1:hKn/e/Nmd19/x1gvIHwtOwVWM+VhuITSWip3JUDghj0= 171 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0 h1:JAv0Jwtl01UFiyWZEMiJZBiTlv5A50zNs8lsthXqIio= 172 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.29.0/go.mod h1:QNKLmUEAq2QUbPQUfvw4fmv0bgbK7UlOSFCnXyfvSNc= 173 | go.opentelemetry.io/otel/exporters/prometheus v0.51.0 h1:G7uexXb/K3T+T9fNLCCKncweEtNEBMTO+46hKX5EdKw= 174 | go.opentelemetry.io/otel/exporters/prometheus v0.51.0/go.mod h1:v0mFe5Kk7woIh938mrZBJBmENYquyA0IICrlYm4Y0t4= 175 | go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.5.0 h1:ThVXnEsdwNcxdBO+r96ci1xbF+PgNjwlk457VNuJODo= 176 | go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.5.0/go.mod h1:rHWcSmC4q2h3gje/yOq6sAOaq8+UHxN/Ru3BbmDXOfY= 177 | go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc= 178 | go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I= 179 | go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.29.0 h1:X3ZjNp36/WlkSYx0ul2jw4PtbNEDDeLskw3VPsrpYM0= 180 | go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.29.0/go.mod h1:2uL/xnOXh0CHOBFCWXz5u1A4GXLiW+0IQIzVbeOEQ0U= 181 | go.opentelemetry.io/otel/log v0.5.0 h1:x1Pr6Y3gnXgl1iFBwtGy1W/mnzENoK0w0ZoaeOI3i30= 182 | go.opentelemetry.io/otel/log v0.5.0/go.mod h1:NU/ozXeGuOR5/mjCRXYbTC00NFJ3NYuraV/7O78F0rE= 183 | go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc= 184 | go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8= 185 | go.opentelemetry.io/otel/sdk v1.29.0 h1:vkqKjk7gwhS8VaWb0POZKmIEDimRCMsopNYnriHyryo= 186 | go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok= 187 | go.opentelemetry.io/otel/sdk/log v0.5.0 h1:A+9lSjlZGxkQOr7QSBJcuyyYBw79CufQ69saiJLey7o= 188 | go.opentelemetry.io/otel/sdk/log v0.5.0/go.mod h1:zjxIW7sw1IHolZL2KlSAtrUi8JHttoeiQy43Yl3WuVQ= 189 | go.opentelemetry.io/otel/sdk/metric v1.29.0 h1:K2CfmJohnRgvZ9UAj2/FhIf/okdWcNdBwe1m8xFXiSY= 190 | go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ= 191 | go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4= 192 | go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ= 193 | go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= 194 | go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= 195 | go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= 196 | go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 197 | go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= 198 | go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= 199 | go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= 200 | go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= 201 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 202 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 203 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 204 | golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= 205 | golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= 206 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 207 | golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= 208 | golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 209 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 210 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 211 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 212 | golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 213 | golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 214 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 215 | golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= 216 | golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= 217 | golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= 218 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 219 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 220 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 221 | golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= 222 | golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 223 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 224 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 225 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 226 | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 227 | golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 228 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 229 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 230 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 231 | golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 232 | golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 233 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 234 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 235 | golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 236 | golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 237 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 238 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 239 | golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= 240 | golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 241 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 242 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 243 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 244 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 245 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 246 | golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= 247 | golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= 248 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 249 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 250 | golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 251 | golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= 252 | golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= 253 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 254 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 255 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 256 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 257 | google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd h1:BBOTEWLuuEGQy9n1y9MhVJ9Qt0BDu21X8qZs71/uPZo= 258 | google.golang.org/genproto/googleapis/api v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:fO8wJzT2zbQbAjbIoos1285VfEIYKDDY+Dt+WpTkh6g= 259 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd h1:6TEm2ZxXoQmFWFlt1vNxvVOa1Q0dXFQD1m/rYjXmS0E= 260 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240822170219-fc7c04adadcd/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU= 261 | google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= 262 | google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= 263 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 264 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 265 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 266 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 267 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 268 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 269 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 270 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 271 | google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= 272 | google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= 273 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 274 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 275 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 276 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 277 | gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= 278 | gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= 279 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 280 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 281 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 282 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 283 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 284 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 285 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 286 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 287 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 288 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 289 | -------------------------------------------------------------------------------- /kod_gen.go: -------------------------------------------------------------------------------- 1 | // Code generated by "kod generate". DO NOT EDIT. 2 | //go:build !ignoreKodGen 3 | 4 | package main 5 | 6 | import ( 7 | "context" 8 | "github.com/go-kod/kod" 9 | "github.com/go-kod/kod/interceptor" 10 | "reflect" 11 | ) 12 | 13 | func init() { 14 | kod.Register(&kod.Registration{ 15 | Name: "github.com/go-kod/kod/Main", 16 | Interface: reflect.TypeOf((*kod.Main)(nil)).Elem(), 17 | Impl: reflect.TypeOf(app{}), 18 | Refs: ``, 19 | LocalStubFn: func(ctx context.Context, info *kod.LocalStubFnInfo) any { 20 | interceptors := info.Interceptors 21 | if h, ok := info.Impl.(interface { 22 | Interceptors() []interceptor.Interceptor 23 | }); ok { 24 | interceptors = append(interceptors, h.Interceptors()...) 25 | } 26 | 27 | return main_local_stub{ 28 | impl: info.Impl.(kod.Main), 29 | interceptor: interceptor.Chain(interceptors), 30 | name: info.Name, 31 | } 32 | }, 33 | }) 34 | } 35 | 36 | // kod.InstanceOf checks. 37 | var _ kod.InstanceOf[kod.Main] = (*app)(nil) 38 | 39 | // Local stub implementations. 40 | 41 | type main_local_stub struct { 42 | impl kod.Main 43 | name string 44 | interceptor interceptor.Interceptor 45 | } 46 | 47 | // Check that main_local_stub implements the kod.Main interface. 48 | var _ kod.Main = (*main_local_stub)(nil) 49 | 50 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | // Copyright 2014 httpmq Author. All Rights Reserved. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | // httpmq is an open-source, lightweight and high-performance message queue. 16 | 17 | package main 18 | 19 | import ( 20 | "context" 21 | "flag" 22 | "fmt" 23 | "io" 24 | "log" 25 | "math" 26 | "net/http" 27 | _ "net/http/pprof" 28 | "runtime" 29 | "strconv" 30 | 31 | "github.com/go-kod/kod" 32 | "github.com/syndtr/goleveldb/leveldb" 33 | "github.com/syndtr/goleveldb/leveldb/opt" 34 | ) 35 | 36 | // VERSION of httpmq 37 | const VERSION = "0.5" 38 | 39 | var db *leveldb.DB 40 | var defaultMaxqueue, cpu, cacheSize, writeBuffer *int 41 | var ip, port, defaultAuth, dbPath *string 42 | 43 | // httpmq read metadata api 44 | // retrieve from leveldb 45 | // name.maxqueue - maxqueue 46 | // name.putpos - putpos 47 | // name.getpos - getpos 48 | func httpmqReadMetadata(name string) []string { 49 | maxqueue := name + ".maxqueue" 50 | data1, _ := db.Get([]byte(maxqueue), nil) 51 | if len(data1) == 0 { 52 | data1 = []byte(strconv.Itoa(*defaultMaxqueue)) 53 | } 54 | putpos := name + ".putpos" 55 | data2, _ := db.Get([]byte(putpos), nil) 56 | getpos := name + ".getpos" 57 | data3, _ := db.Get([]byte(getpos), nil) 58 | return []string{string(data1), string(data2), string(data3)} 59 | } 60 | 61 | // httpmq now getpos api 62 | // get the current getpos of httpmq for request 63 | func httpmqNowGetpos(name string) string { 64 | metadata := httpmqReadMetadata(name) 65 | maxqueue, _ := strconv.Atoi(metadata[0]) 66 | putpos, _ := strconv.Atoi(metadata[1]) 67 | getpos, _ := strconv.Atoi(metadata[2]) 68 | 69 | if getpos == 0 && putpos > 0 { 70 | getpos = 1 // first get operation, set getpos 1 71 | } else if getpos < putpos { 72 | getpos++ // 1nd lap, increase getpos 73 | } else if getpos > putpos && getpos < maxqueue { 74 | getpos++ // 2nd lap 75 | } else if getpos > putpos && getpos == maxqueue { 76 | getpos = 1 // 2nd first operation, set getpos 1 77 | } else { 78 | return "0" // all data in queue has been get 79 | } 80 | 81 | data := strconv.Itoa(getpos) 82 | _ = db.Put([]byte(name+".getpos"), []byte(data), nil) 83 | return data 84 | } 85 | 86 | // httpmq now putpos api 87 | // get the current putpos of httpmq for request 88 | func httpmqNowPutpos(name string) string { 89 | metadata := httpmqReadMetadata(name) 90 | maxqueue, _ := strconv.Atoi(metadata[0]) 91 | putpos, _ := strconv.Atoi(metadata[1]) 92 | getpos, _ := strconv.Atoi(metadata[2]) 93 | 94 | putpos++ // increase put queue pos 95 | if putpos == getpos { // queue is full 96 | return "0" // return 0 to reject put operation 97 | } else if getpos <= 1 && putpos > maxqueue { // get operation less than 1 98 | return "0" // and queue is full, just reject it 99 | } else if putpos > maxqueue { // 2nd lap 100 | metadata[1] = "1" // reset putpos as 1 and write to leveldb 101 | } else { // 1nd lap, convert int to string and write to leveldb 102 | metadata[1] = strconv.Itoa(putpos) 103 | } 104 | 105 | _ = db.Put([]byte(name+".putpos"), []byte(metadata[1]), nil) 106 | 107 | return metadata[1] 108 | } 109 | 110 | func init() { 111 | defaultMaxqueue = flag.Int("maxqueue", 1000000, "the max queue length") 112 | ip = flag.String("ip", "0.0.0.0", "ip address to listen on") 113 | port = flag.String("port", "1218", "port to listen on") 114 | defaultAuth = flag.String("auth", "", "auth password to access httpmq") 115 | dbPath = flag.String("db", "level.db", "database path") 116 | cacheSize = flag.Int("cache", 64, "cache size(MB)") 117 | writeBuffer = flag.Int("buffer", 32, "write buffer(MB)") 118 | cpu = flag.Int("cpu", runtime.NumCPU(), "cpu number for httpmq") 119 | flag.Parse() 120 | 121 | var err error 122 | db, err = leveldb.OpenFile(*dbPath, &opt.Options{BlockCacheCapacity: *cacheSize, 123 | WriteBuffer: *writeBuffer * 1024 * 1024}) 124 | if err != nil { 125 | log.Fatalln("db.Get(), err:", err) 126 | } 127 | } 128 | 129 | type app struct { 130 | kod.Implements[kod.Main] 131 | } 132 | 133 | func (*app) run() { 134 | runtime.GOMAXPROCS(*cpu) 135 | 136 | sync := &opt.WriteOptions{Sync: true} 137 | 138 | putnamechan := make(chan string, 100) 139 | putposchan := make(chan string, 100) 140 | getnamechan := make(chan string, 100) 141 | getposchan := make(chan string, 100) 142 | 143 | go func(chan string, chan string) { 144 | for { 145 | name := <-putnamechan 146 | putpos := httpmqNowPutpos(name) 147 | putposchan <- putpos 148 | } 149 | }(putnamechan, putposchan) 150 | 151 | go func(chan string, chan string) { 152 | for { 153 | name := <-getnamechan 154 | getpos := httpmqNowGetpos(name) 155 | getposchan <- getpos 156 | } 157 | }(getnamechan, getposchan) 158 | 159 | m := &http.ServeMux{} 160 | m.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { 161 | var data string 162 | var buf []byte 163 | auth := string(r.FormValue("auth")) 164 | name := string(r.FormValue("name")) 165 | opt := string(r.FormValue("opt")) 166 | pos := string(r.FormValue("pos")) 167 | num := string(r.FormValue("num")) 168 | charset := string(r.FormValue("charset")) 169 | 170 | if *defaultAuth != "" && *defaultAuth != auth { 171 | _, _ = rw.Write([]byte("HTTPMQ_AUTH_FAILED")) 172 | return 173 | } 174 | 175 | method := string(r.Method) 176 | if method == "GET" { 177 | data = string(r.FormValue("data")) 178 | } else if method == "POST" { 179 | if string(r.Header.Get("Content-Type")) == "application/x-www-form-urlencoded" { 180 | data = string(r.FormValue("data")) 181 | } else { 182 | buf, _ = io.ReadAll(r.Body) 183 | defer r.Body.Close() 184 | } 185 | } 186 | 187 | if len(name) == 0 || len(opt) == 0 { 188 | _, _ = rw.Write([]byte("HTTPMQ_ERROR")) 189 | return 190 | } 191 | 192 | rw.Header().Set("Connection", "keep-alive") 193 | rw.Header().Set("Cache-Control", "no-cache") 194 | rw.Header().Set("Content-type", "text/plain") 195 | if len(charset) > 0 { 196 | rw.Header().Set("Content-type", "text/plain; charset="+charset) 197 | } 198 | 199 | if opt == "put" { 200 | if len(data) == 0 && len(buf) == 0 { 201 | _, _ = rw.Write([]byte("HTTPMQ_PUT_ERROR")) 202 | return 203 | } 204 | 205 | putnamechan <- name 206 | putpos := <-putposchan 207 | 208 | if putpos != "0" { 209 | queueName := name + putpos 210 | if data != "" { 211 | _ = db.Put([]byte(queueName), []byte(data), nil) 212 | } else if len(buf) > 0 { 213 | _ = db.Put([]byte(queueName), buf, nil) 214 | } 215 | rw.Header().Set("Pos", putpos) 216 | _, _ = rw.Write([]byte("HTTPMQ_PUT_OK")) 217 | } else { 218 | _, _ = rw.Write([]byte("HTTPMQ_PUT_END")) 219 | } 220 | } else if opt == "get" { 221 | getnamechan <- name 222 | getpos := <-getposchan 223 | 224 | if getpos == "0" { 225 | _, _ = rw.Write([]byte("HTTPMQ_GET_END")) 226 | } else { 227 | queueName := name + getpos 228 | v, err := db.Get([]byte(queueName), nil) 229 | if err == nil { 230 | rw.Header().Set("Pos", getpos) 231 | _, _ = rw.Write(v) 232 | } else { 233 | _, _ = rw.Write([]byte("HTTPMQ_GET_ERROR")) 234 | } 235 | } 236 | } else if opt == "status" { 237 | metadata := httpmqReadMetadata(name) 238 | maxqueue, _ := strconv.Atoi(metadata[0]) 239 | putpos, _ := strconv.Atoi(metadata[1]) 240 | getpos, _ := strconv.Atoi(metadata[2]) 241 | 242 | var ungetnum float64 243 | var putTimes, getTimes string 244 | if putpos >= getpos { 245 | ungetnum = math.Abs(float64(putpos - getpos)) 246 | putTimes = "1st lap" 247 | getTimes = "1st lap" 248 | } else if putpos < getpos { 249 | ungetnum = math.Abs(float64(maxqueue - getpos + putpos)) 250 | putTimes = "2nd lap" 251 | getTimes = "1st lap" 252 | } 253 | 254 | buf := fmt.Sprintf("HTTP Simple Queue Service v%s\n", VERSION) 255 | buf += "------------------------------\n" 256 | buf += fmt.Sprintf("Queue Name: %s\n", name) 257 | buf += fmt.Sprintf("Maximum number of queues: %d\n", maxqueue) 258 | buf += fmt.Sprintf("Put position of queue (%s): %d\n", putTimes, putpos) 259 | buf += fmt.Sprintf("Get position of queue (%s): %d\n", getTimes, getpos) 260 | buf += fmt.Sprintf("Number of unread queue: %g\n\n", ungetnum) 261 | 262 | _, _ = rw.Write([]byte(buf)) 263 | } else if opt == "view" { 264 | v, err := db.Get([]byte(name+pos), nil) 265 | if err == nil { 266 | _, _ = rw.Write([]byte(v)) 267 | } else { 268 | _, _ = rw.Write([]byte("HTTPMQ_VIEW_ERROR")) 269 | } 270 | } else if opt == "reset" { 271 | maxqueue := strconv.Itoa(*defaultMaxqueue) 272 | _ = db.Put([]byte(name+".maxqueue"), []byte(maxqueue), sync) 273 | _ = db.Put([]byte(name+".putpos"), []byte("0"), sync) 274 | _ = db.Put([]byte(name+".getpos"), []byte("0"), sync) 275 | _, _ = rw.Write([]byte("HTTPMQ_RESET_OK")) 276 | } else if opt == "maxqueue" { 277 | maxqueue, _ := strconv.Atoi(num) 278 | if maxqueue > 0 && maxqueue <= 10000000 { 279 | _ = db.Put([]byte(name+".maxqueue"), []byte(num), sync) 280 | _, _ = rw.Write([]byte("HTTPMQ_MAXQUEUE_OK")) 281 | } else { 282 | _, _ = rw.Write([]byte("HTTPMQ_MAXQUEUE_CANCLE")) 283 | } 284 | } 285 | }) 286 | 287 | log.Fatal(http.ListenAndServe(*ip+":"+*port, m)) 288 | } 289 | 290 | //go:generate go run github.com/go-kod/kod/cmd/kod generate 291 | 292 | func main() { 293 | _ = kod.Run(context.Background(), func(ctx context.Context, app *app) error { 294 | app.run() 295 | return nil 296 | }) 297 | } 298 | -------------------------------------------------------------------------------- /tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | // +build tools 3 | 4 | package main 5 | 6 | import ( 7 | _ "github.com/go-kod/kod/cmd/kod" 8 | ) 9 | --------------------------------------------------------------------------------