Compare commits
5 Commits
14a0902e2b
...
master
Author | SHA1 | Date | |
---|---|---|---|
070934d66a
|
|||
0f8d6b39fb
|
|||
fef404f1a7
|
|||
55719b4399
|
|||
6a743cf5c4
|
7
.env.dist
Normal file
7
.env.dist
Normal file
@ -0,0 +1,7 @@
|
||||
COMPOSE_PROJECT_NAME=h-skills
|
||||
ALPINE_VER=3.19
|
||||
GOVERTER_VER=v1.4.0
|
||||
GOLANGCI_LINT_VER=v1.56.2
|
||||
POSTGRES_VER=16.2
|
||||
AIR_VER=1.52.0
|
||||
SQLC_VER=1.26.0
|
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/.task
|
||||
/.env
|
||||
/bin/env
|
||||
/tmp/
|
2
.golangci.yml
Normal file
2
.golangci.yml
Normal file
@ -0,0 +1,2 @@
|
||||
# golangci-lint configuration file.
|
||||
# Read more at: https://github.com/golangci/golangci-lint#config-file
|
20
Dockerfile
Normal file
20
Dockerfile
Normal file
@ -0,0 +1,20 @@
|
||||
ARG POSTGRES_VER
|
||||
ARG GO_VER
|
||||
ARG ALPINE_VER
|
||||
|
||||
FROM postgres:${POSTGRES_VER} AS postgres
|
||||
|
||||
COPY ./string-unpack/internal/db/* /docker-entrypoint-initdb.d/
|
||||
|
||||
RUN set -ex \
|
||||
&& chmod 1777 /tmp
|
||||
|
||||
FROM golang:${GO_VER}-alpine${ALPINE_VER} AS golang
|
||||
|
||||
ARG AIR_VER
|
||||
RUN set -ex \
|
||||
&& chmod 1777 /tmp \
|
||||
&& apk add --no-cache \
|
||||
git \
|
||||
tzdata \
|
||||
&& go install github.com/cosmtrek/air@v${AIR_VER}
|
129
Taskfile.go.yaml
Normal file
129
Taskfile.go.yaml
Normal file
@ -0,0 +1,129 @@
|
||||
version: '3'
|
||||
|
||||
vars:
|
||||
GOFUMPT_VER: '{{.GOFUMPT_VER | default "latest"}}'
|
||||
GOIMPORTS_LOCAL: '{{.GOIMPORTS_LOCAL | default nil}}'
|
||||
GOIMPORT_VER: '{{.GOIMPORT_VER | default "latest"}}'
|
||||
GOLANGCI_LINT_VER: '{{.GOLANGCI_LINT_VER | default "latest"}}'
|
||||
GOVULNCHECK_VER: '{{.GOVULNCHECK_VER | default "latest"}}'
|
||||
PROTOLINT_VER: '{{.PROTOLINT_VER | default "latest"}}'
|
||||
STATICCHECK_VER: '{{.STATICCHECK_VER | default "latest"}}'
|
||||
TMP_DIR: '{{.TMP_DIR | default "./tmp"}}'
|
||||
|
||||
tasks:
|
||||
# =======
|
||||
# HELPERS
|
||||
# =======
|
||||
|
||||
lint:
|
||||
desc: golangci-lint + protolint.
|
||||
cmds:
|
||||
- task: govulncheck
|
||||
- task: staticcheck
|
||||
- task: golangci-lint
|
||||
- task: protolint
|
||||
|
||||
cs:
|
||||
desc: fmt + goimports.
|
||||
cmds:
|
||||
- task: fmt
|
||||
- task: goimports
|
||||
|
||||
# ===============
|
||||
# QUALITY CONTROL
|
||||
# ===============
|
||||
|
||||
fmt:
|
||||
desc: format code using gofumpt.
|
||||
cmds:
|
||||
- >-
|
||||
go run mvdan.cc/gofumpt@{{.GOFUMPT_VER}} -l -w .
|
||||
sources:
|
||||
- ./**/*.go
|
||||
|
||||
goimports:
|
||||
desc: format imports using goimports.
|
||||
cmds:
|
||||
- >-
|
||||
go run golang.org/x/tools/cmd/goimports@{{.GOIMPORT_VER}}
|
||||
{{if .GOIMPORTS_LOCAL}} -local="{{.GOIMPORTS_LOCAL}}"{{end}}
|
||||
-w .
|
||||
sources:
|
||||
- ./**/*.go
|
||||
|
||||
tidy:
|
||||
desc: go mod tidy + go mod verify.
|
||||
cmds:
|
||||
- go mod tidy -v
|
||||
- go mod verify
|
||||
sources:
|
||||
- ./**/*.go
|
||||
- go.mod
|
||||
- go.sum
|
||||
|
||||
golangci-lint:
|
||||
desc: golangci-lint.
|
||||
cmds:
|
||||
- go run github.com/golangci/golangci-lint/cmd/golangci-lint@{{.GOLANGCI_LINT_VER}} run -v ./...
|
||||
sources:
|
||||
- ./**/*.go
|
||||
|
||||
govulncheck:
|
||||
desc: govulncheck.
|
||||
cmds:
|
||||
- go run golang.org/x/vuln/cmd/govulncheck@{{.GOVULNCHECK_VER}} ./...
|
||||
sources:
|
||||
- ./**/*.go
|
||||
|
||||
staticcheck:
|
||||
desc: staticcheck.
|
||||
cmds:
|
||||
- go run honnef.co/go/tools/cmd/staticcheck@{{.STATICCHECK_VER}} -checks=all,-ST1000 ./...
|
||||
sources:
|
||||
- ./**/*.go
|
||||
|
||||
protolint:
|
||||
desc: protolint -fix.
|
||||
cmds:
|
||||
- cmd: go run github.com/yoheimuta/protolint/cmd/protolint@{{.PROTOLINT_VER}} lint -fix .
|
||||
ignore_error: true
|
||||
sources: &protolint_sources
|
||||
- ./**/*.proto
|
||||
|
||||
protolint:check:
|
||||
desc: protolint check.
|
||||
cmds:
|
||||
- go run github.com/yoheimuta/protolint/cmd/protolint@{{.PROTOLINT_VER}} lint .
|
||||
sources: *protolint_sources
|
||||
|
||||
# ===========
|
||||
# DEVELOPMENT
|
||||
# ===========
|
||||
|
||||
generate:
|
||||
desc: go generate
|
||||
cmds:
|
||||
- go generate ./...
|
||||
sources:
|
||||
- ./**/*.go
|
||||
|
||||
vendor:
|
||||
desc: go mod vendor.
|
||||
cmds:
|
||||
- go mod vendor -v
|
||||
sources:
|
||||
- go.mod
|
||||
- go.sum
|
||||
generates:
|
||||
- vendor
|
||||
|
||||
test:
|
||||
desc: go tests ./...
|
||||
cmds:
|
||||
- go test -race -buildvcs -coverprofile={{.TMP_DIR}}/coverage.out -vet=off ./...
|
||||
|
||||
test:cover:
|
||||
desc: tests and display coverage.
|
||||
deps: [ test ]
|
||||
cmds:
|
||||
- go tool cover -html={{.TMP_DIR}}/coverage.out
|
192
Taskfile.yaml
Normal file
192
Taskfile.yaml
Normal file
@ -0,0 +1,192 @@
|
||||
version: '3'
|
||||
|
||||
includes:
|
||||
go:
|
||||
taskfile: ./Taskfile.go.yaml
|
||||
|
||||
output: prefixed
|
||||
|
||||
silent: true
|
||||
interval: 1s
|
||||
|
||||
dotenv:
|
||||
- ./.env
|
||||
|
||||
vars:
|
||||
NEWLINE_EXCLUDE: >-
|
||||
-not -path "./.git/*"
|
||||
-not -path "./.idea/*"
|
||||
-not -path "./vendor/*"
|
||||
-not -path "./tmp/*"
|
||||
-not -name "*.ico"
|
||||
-not -name "*.png"
|
||||
-not -name "*.svg"
|
||||
|
||||
tasks:
|
||||
# =======
|
||||
# HELPERS
|
||||
# =======
|
||||
|
||||
all:
|
||||
desc: generate + tidy + lint + test.
|
||||
cmds:
|
||||
- task: generate
|
||||
- task: go:tidy
|
||||
- task: go:lint
|
||||
- task: go:test
|
||||
|
||||
generate:
|
||||
desc: all generators + cs.
|
||||
cmds:
|
||||
- task: sqlc
|
||||
- task: goverter
|
||||
- task: go:generate
|
||||
- task: cs
|
||||
|
||||
cs:
|
||||
desc: go:cs + newline.
|
||||
cmds:
|
||||
- task: go:cs
|
||||
- task: newline
|
||||
|
||||
# ===============
|
||||
# QUALITY CONTROL
|
||||
# ===============
|
||||
|
||||
newline:
|
||||
desc: add newline at end file.
|
||||
cmds:
|
||||
- >-
|
||||
find .
|
||||
{{.NEWLINE_EXCLUDE}}
|
||||
-type f -exec grep -Iq . {} \; -and -print0
|
||||
| xargs -0 -n 1 sh -c 'test -z "$(tail -c 1 "$0")"
|
||||
|| (echo "" >> $0 && echo $0)'
|
||||
|| exit 1
|
||||
sources: &newline_sources
|
||||
- ./**/*
|
||||
- exclude: "*.ico"
|
||||
- exclude: "*.png"
|
||||
- exclude: "*.svg"
|
||||
|
||||
newline:check:
|
||||
desc: check newline at end file.
|
||||
cmds:
|
||||
- find .
|
||||
{{.NEWLINE_EXCLUDE}}
|
||||
-type f -exec grep -Iq . {} \; -and -print0
|
||||
| xargs -0 -n 1 sh -c 'test -z "$(tail -c 1 "$0")"
|
||||
|| (echo "No new line at end of $0" && exit 1)'
|
||||
|| exit 1
|
||||
sources: *newline_sources
|
||||
|
||||
# ===========
|
||||
# DEVELOPMENT
|
||||
# ===========
|
||||
|
||||
dotenv:install:
|
||||
internal: true
|
||||
cmds:
|
||||
- mkdir -p bin
|
||||
- curl -o bin/env https://raw.githubusercontent.com/bashup/dotenv/master/dotenv
|
||||
- chmod +x bin/env
|
||||
status:
|
||||
- test -f bin/env
|
||||
|
||||
dotenv:
|
||||
deps: [ dotenv:install ]
|
||||
desc: fill .env file.
|
||||
vars:
|
||||
UID:
|
||||
sh: id -u
|
||||
GID:
|
||||
sh: id -g
|
||||
GO_VER:
|
||||
sh: go mod edit -json | jq -r .Go
|
||||
GOIMPORTS_LOCAL:
|
||||
sh: go list -m | awk -F/ '{print $1}'
|
||||
ENV_DIST:
|
||||
sh: cat .env.dist|tr '\n' ' '
|
||||
GOPATH:
|
||||
sh: go env GOPATH
|
||||
cmds:
|
||||
- bin/env set GROUP_ID={{.UID}} USER_ID={{.GID}} GO_VER={{.GO_VER}} GOPATH={{.GOPATH}} {{.ENV_DIST}}
|
||||
sources:
|
||||
- .env.dist
|
||||
- Taskfile.yaml
|
||||
generates:
|
||||
- .env
|
||||
|
||||
goverter:
|
||||
desc: go run goverter
|
||||
deps: [ dotenv ]
|
||||
cmds:
|
||||
- go run github.com/jmattheis/goverter/cmd/goverter@{{.GOVERTER_VER}} gen ./...
|
||||
sources:
|
||||
- ./**/*.go
|
||||
|
||||
sqlc:
|
||||
desc: go run sqlc.
|
||||
deps: [ dotenv ]
|
||||
cmds:
|
||||
- go run github.com/sqlc-dev/sqlc/cmd/sqlc@v{{.SQLC_VER}} generate
|
||||
sources:
|
||||
- sqlc.yaml
|
||||
- ./**/sql/**/*
|
||||
- ./**/db/**/*
|
||||
|
||||
# =========
|
||||
# OPERATION
|
||||
# =========
|
||||
|
||||
up:
|
||||
desc: up all services.
|
||||
cmds:
|
||||
- task: postgres:up
|
||||
- task: api:up
|
||||
|
||||
down:
|
||||
desc: docker compose down.
|
||||
deps: [ dotenv ]
|
||||
cmds:
|
||||
- docker compose down -v --remove-orphans
|
||||
|
||||
postgres:build:
|
||||
internal: true
|
||||
desc: docker compose build postgres.
|
||||
deps: [ dotenv ]
|
||||
cmds:
|
||||
- docker compose build postgres
|
||||
sources:
|
||||
- ./**/db/**/*
|
||||
- Dockerfile
|
||||
- docker-compose.yml
|
||||
|
||||
postgres:up:
|
||||
desc: docker compose up postgres.
|
||||
deps: [ dotenv, postgres:build ]
|
||||
cmds:
|
||||
- docker compose up -d --force-recreate postgres
|
||||
|
||||
postgres:push:
|
||||
desc: docker compose push postgres.
|
||||
deps: [ dotenv, postgres:build ]
|
||||
cmds:
|
||||
- docker compose push postgres
|
||||
|
||||
api:build:
|
||||
internal: true
|
||||
desc: docker compose build api image.
|
||||
deps: [ dotenv ]
|
||||
cmds:
|
||||
- docker compose build api
|
||||
sources:
|
||||
- .env
|
||||
- Dockerfile
|
||||
- docker-compose.yml
|
||||
|
||||
api:up:
|
||||
desc: docker compose up api.
|
||||
deps: [ dotenv, api:build ]
|
||||
cmds:
|
||||
- docker compose up -d --force-recreate api
|
24
cmd/api/config.go
Normal file
24
cmd/api/config.go
Normal file
@ -0,0 +1,24 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"time"
|
||||
|
||||
"github.com/kelseyhightower/envconfig"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
DSN string `envconfig:"DSN" default:"postgresql://postgres:postgres@postgres:5432/postgres?sslmode=disable"`
|
||||
ReconnectTimeout time.Duration `envconfig:"RECONNECT_TIMEOUT" default:"2s"`
|
||||
}
|
||||
|
||||
func (c *Config) Parse() error {
|
||||
flag.StringVar(&c.DSN, "DSN", "", "postgresql DSN")
|
||||
flag.Parse()
|
||||
|
||||
if err := envconfig.Process("", c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
113
cmd/api/main.go
Normal file
113
cmd/api/main.go
Normal file
@ -0,0 +1,113 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
|
||||
stringunpack "git.grachevko.ru/grachevko/h/string-unpack"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
collector "github.com/prometheus/client_golang/prometheus/collectors/version"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
func main() {
|
||||
logger, _ := zap.NewProduction()
|
||||
defer func(logger *zap.Logger) {
|
||||
_ = logger.Sync()
|
||||
}(logger) // flushes buffer, if any
|
||||
|
||||
cfg := Config{}
|
||||
if err := cfg.Parse(); err != nil {
|
||||
logger.Fatal("config parse", zap.Error(err))
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
ctx, stop := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
|
||||
defer stop()
|
||||
|
||||
var metricServer *http.Server
|
||||
{ // Metrics
|
||||
prometheus.MustRegister(collector.NewCollector("unpack"))
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle("/metrics", promhttp.Handler())
|
||||
metricServer = &http.Server{
|
||||
Handler: mux,
|
||||
Addr: ":8089",
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := metricServer.ListenAndServe(); err != nil {
|
||||
logger.Error("metric server failed", zap.Error(err))
|
||||
}
|
||||
}()
|
||||
} // Metrics
|
||||
|
||||
pgconn:
|
||||
conn, err := pgx.Connect(ctx, cfg.DSN)
|
||||
if err != nil {
|
||||
logger.Error("pgx", zap.Error(err))
|
||||
|
||||
logger.Info("Wait before reconnect", zap.Duration("after", cfg.ReconnectTimeout))
|
||||
<-time.After(cfg.ReconnectTimeout)
|
||||
logger.Info("Retrying connection")
|
||||
goto pgconn
|
||||
}
|
||||
defer func(conn *pgx.Conn, ctx context.Context) {
|
||||
if err = conn.Close(ctx); err != nil {
|
||||
logger.Error("pgx close", zap.Error(err))
|
||||
}
|
||||
}(conn, ctx)
|
||||
|
||||
var httpServer *http.Server
|
||||
{ // Http
|
||||
r := gin.Default()
|
||||
|
||||
stringunpack.Setup(ctx, logger, r.Group("unpack"), conn)
|
||||
|
||||
httpServer = &http.Server{
|
||||
Addr: ":8080",
|
||||
Handler: r,
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := httpServer.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||
logger.Error("http server failed", zap.Error(err))
|
||||
}
|
||||
}()
|
||||
} // Http
|
||||
|
||||
// Listen for the interrupt signal.
|
||||
<-ctx.Done()
|
||||
|
||||
{ // Graceful shutdown
|
||||
// Restore default behavior on the interrupt signal and notify user of shutdown.
|
||||
stop()
|
||||
logger.Info("shutting down gracefully, press Ctrl+C again to force")
|
||||
|
||||
// The context is used to inform the server it has 5 seconds to finish
|
||||
// the request it is currently handling
|
||||
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
||||
defer cancel()
|
||||
|
||||
g, ctx := errgroup.WithContext(ctx)
|
||||
g.Go(func() error { return metricServer.Shutdown(ctx) })
|
||||
g.Go(func() error { return httpServer.Shutdown(ctx) })
|
||||
|
||||
if err := g.Wait(); err != nil {
|
||||
logger.Error("graceful shutdown failed", zap.Error(err))
|
||||
}
|
||||
} // Graceful shutdown
|
||||
|
||||
logger.Info("Server exiting")
|
||||
}
|
@ -2,8 +2,6 @@ package main
|
||||
|
||||
import "flag"
|
||||
|
||||
const stdin = "-"
|
||||
|
||||
type Config struct {
|
||||
Key int
|
||||
Numeric bool
|
||||
@ -23,6 +21,6 @@ func (c *Config) ParseFlags() {
|
||||
c.Sources = flag.Args()
|
||||
|
||||
if len(c.Sources) == 0 {
|
||||
c.Sources = []string{stdin}
|
||||
c.Sources = []string{"-"}
|
||||
}
|
||||
}
|
@ -2,6 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
sortcli "git.grachevko.ru/grachevko/h/sort-cli"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -18,8 +20,8 @@ func run() string {
|
||||
cfg := &Config{}
|
||||
cfg.ParseFlags()
|
||||
|
||||
lines := content{}
|
||||
lines.Load(open(cfg.Sources))
|
||||
lines := sortcli.Content{}
|
||||
lines.Load(sortcli.Open(cfg.Sources))
|
||||
|
||||
if cfg.Unique {
|
||||
lines.Uniques()
|
@ -2,10 +2,11 @@ package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestFlags(t *testing.T) {
|
||||
@ -20,22 +21,26 @@ func TestFlags(t *testing.T) {
|
||||
ExpectedExit int
|
||||
ExpectedOutput string
|
||||
}{
|
||||
{"No flags",
|
||||
{
|
||||
"No flags",
|
||||
[]string{"testdata/first"},
|
||||
0,
|
||||
"alabama barcelona\nbarcelona california\ncalifornia denver\ncalifornia denver\nамур брянск\nбелгород волгоград\nволгоград геленджик",
|
||||
},
|
||||
{"Reverse",
|
||||
{
|
||||
"Reverse",
|
||||
[]string{"-r", "testdata/first"},
|
||||
0,
|
||||
"волгоград геленджик\nбелгород волгоград\nамур брянск\ncalifornia denver\ncalifornia denver\nbarcelona california\nalabama barcelona",
|
||||
},
|
||||
{"Unique",
|
||||
{
|
||||
"Unique",
|
||||
[]string{"-u", "testdata/first"},
|
||||
0,
|
||||
"alabama barcelona\nbarcelona california\ncalifornia denver\nамур брянск\nбелгород волгоград\nволгоград геленджик",
|
||||
},
|
||||
{"Column 2",
|
||||
{
|
||||
"Column 2",
|
||||
[]string{"-k=2", "testdata/first"},
|
||||
0,
|
||||
"alabama barcelona\nbarcelona california\ncalifornia denver\ncalifornia denver\nамур брянск\nбелгород волгоград\nволгоград геленджик",
|
41
docker-compose.yml
Normal file
41
docker-compose.yml
Normal file
@ -0,0 +1,41 @@
|
||||
services:
|
||||
postgres:
|
||||
build:
|
||||
target: postgres
|
||||
context: .
|
||||
args: &args
|
||||
AIR_VER: ${AIR_VER}
|
||||
ALPINE_VER: ${ALPINE_VER}
|
||||
GO_VER: ${GO_VER}
|
||||
POSTGRES_VER: ${POSTGRES_VER}
|
||||
image: harbor.grachevko.ru/grachevko/h-skills/postgres:dev
|
||||
labels:
|
||||
ru.grachevko.dhu: 'postgres.h-skills.local'
|
||||
environment:
|
||||
POSTGRES_DB: postgres
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: postgres
|
||||
PGDATABASE: postgres
|
||||
PGUSER: postgres
|
||||
PGPASSWORD: postgres
|
||||
volumes:
|
||||
- type: tmpfs
|
||||
target: /var/lib/postgresql/data
|
||||
tmpfs:
|
||||
size: 4294967296
|
||||
|
||||
api:
|
||||
build:
|
||||
target: golang
|
||||
args: *args
|
||||
command: air --build.cmd "go build -o ./tmp/api ./cmd/api/" --build.bin "./tmp/api"
|
||||
labels:
|
||||
ru.grachevko.dhu: 'api.h-skills.local'
|
||||
environment:
|
||||
GOPATH: ${GOPATH}
|
||||
working_dir: /app
|
||||
volumes:
|
||||
- ./:/app
|
||||
- ${GOPATH}:${GOPATH}
|
||||
- ${HOME}/.cache/go-build:/.cache/go-build
|
||||
user: ${USER_ID}:${GROUP_ID}
|
53
go.mod
Normal file
53
go.mod
Normal file
@ -0,0 +1,53 @@
|
||||
module git.grachevko.ru/grachevko/h
|
||||
|
||||
go 1.22.3
|
||||
|
||||
require (
|
||||
github.com/gin-gonic/gin v1.10.0
|
||||
github.com/jackc/pgx/v5 v5.5.5
|
||||
github.com/kelseyhightower/envconfig v1.4.0
|
||||
github.com/prometheus/client_golang v1.19.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842
|
||||
golang.org/x/sync v0.7.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bytedance/sonic v1.11.6 // indirect
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.0 // indirect
|
||||
github.com/prometheus/common v0.53.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
go.uber.org/multierr v1.10.0 // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/crypto v0.23.0 // indirect
|
||||
golang.org/x/net v0.25.0 // indirect
|
||||
golang.org/x/sys v0.20.0 // indirect
|
||||
golang.org/x/text v0.15.0 // indirect
|
||||
google.golang.org/protobuf v1.34.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
126
go.sum
Normal file
126
go.sum
Normal file
@ -0,0 +1,126 @@
|
||||
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/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||
github.com/davecgh/go-spew v1.1.0/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.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
|
||||
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.5.5 h1:amBjrZVmksIdNjxGW/IiIMzxMKZFelXbUoPNb+8sjQw=
|
||||
github.com/jackc/pgx/v5 v5.5.5/go.mod h1:ez9gk+OAat140fv9ErkZDYFWmXLfV+++K0uAOiwgm1A=
|
||||
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
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/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
|
||||
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
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/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
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/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/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
github.com/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.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
||||
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||
github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
|
||||
github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8=
|
||||
github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE=
|
||||
github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
||||
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM=
|
||||
golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc=
|
||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
48
lru/Makefile
48
lru/Makefile
@ -1,48 +0,0 @@
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
# ==================================================================================== #
|
||||
# HELPERS
|
||||
# ==================================================================================== #
|
||||
|
||||
## help: print this help message
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo 'Usage:'
|
||||
@sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /'
|
||||
|
||||
|
||||
# ==================================================================================== #
|
||||
# QUALITY CONTROL
|
||||
# ==================================================================================== #
|
||||
|
||||
## tidy: format code and tidy modfile
|
||||
.PHONY: tidy
|
||||
tidy:
|
||||
go fmt ./...
|
||||
go mod tidy -v
|
||||
|
||||
## audit: run quality control checks
|
||||
.PHONY: audit
|
||||
audit:
|
||||
go mod verify
|
||||
go vet ./...
|
||||
go run honnef.co/go/tools/cmd/staticcheck@latest -checks=all,-ST1000,-U1000 ./...
|
||||
go run golang.org/x/vuln/cmd/govulncheck@latest ./...
|
||||
go test -race -buildvcs -vet=off ./...
|
||||
go run github.com/golangci/golangci-lint/cmd/golangci-lint@latest run -v ./...
|
||||
|
||||
|
||||
# ==================================================================================== #
|
||||
# DEVELOPMENT
|
||||
# ==================================================================================== #
|
||||
|
||||
## test: run all tests
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -v -race -buildvcs ./...
|
||||
|
||||
## test/cover: run all tests and display coverage
|
||||
.PHONY: test/cover
|
||||
test/cover:
|
||||
go test -v -race -buildvcs -coverprofile=/tmp/coverage.out ./...
|
||||
go tool cover -html=/tmp/coverage.out
|
11
lru/go.mod
11
lru/go.mod
@ -1,11 +0,0 @@
|
||||
module lru
|
||||
|
||||
go 1.21.6
|
||||
|
||||
require github.com/stretchr/testify v1.8.4
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
10
lru/go.sum
10
lru/go.sum
@ -1,10 +0,0 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
@ -2,9 +2,10 @@ package lru
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestTtl(t *testing.T) {
|
||||
|
@ -1,53 +0,0 @@
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
# ==================================================================================== #
|
||||
# HELPERS
|
||||
# ==================================================================================== #
|
||||
|
||||
## help: print this help message
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo 'Usage:'
|
||||
@sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /'
|
||||
|
||||
## all: tidy + audit + test/cover
|
||||
all: generate tidy test lint test/cover
|
||||
|
||||
|
||||
# ==================================================================================== #
|
||||
# QUALITY CONTROL
|
||||
# ==================================================================================== #
|
||||
|
||||
## tidy: format code and tidy modfile
|
||||
.PHONY: tidy
|
||||
tidy:
|
||||
go fmt ./...
|
||||
goimports -local=$(shell cat go.mod | grep module | awk '{print $$2}')/ -w .
|
||||
go mod tidy -v
|
||||
|
||||
## audit: run quality control checks
|
||||
.PHONY: lint
|
||||
lint:
|
||||
go mod verify
|
||||
go run github.com/golangci/golangci-lint/cmd/golangci-lint@latest run -v ./...
|
||||
|
||||
|
||||
# ==================================================================================== #
|
||||
# DEVELOPMENT
|
||||
# ==================================================================================== #
|
||||
|
||||
## generate: run all generators
|
||||
.PHONY: generate
|
||||
generate:
|
||||
go generate ./...
|
||||
|
||||
## test: run all tests
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -race -buildvcs ./...
|
||||
|
||||
## test/cover: run all tests and display coverage
|
||||
.PHONY: test/cover
|
||||
test/cover:
|
||||
go test -race -buildvcs -coverprofile=/tmp/coverage.out ./...
|
||||
go tool cover -html=/tmp/coverage.out
|
@ -1,11 +0,0 @@
|
||||
module merge-channel
|
||||
|
||||
go 1.21.6
|
||||
|
||||
require github.com/stretchr/testify v1.8.4
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
@ -1,10 +0,0 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
@ -1,11 +1,11 @@
|
||||
package main
|
||||
package mergechannel
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var InsufficientChannelsErr = errors.New("channels count must be >2")
|
||||
var ErrInsufficientChannels = errors.New("channels count must be >2")
|
||||
|
||||
func merge[T any](channels ...<-chan T) (<-chan T, error) {
|
||||
out := make(chan T)
|
||||
@ -13,7 +13,7 @@ func merge[T any](channels ...<-chan T) (<-chan T, error) {
|
||||
if len(channels) < 2 {
|
||||
close(out)
|
||||
|
||||
return out, InsufficientChannelsErr
|
||||
return out, ErrInsufficientChannels
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package mergechannel
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@ -32,5 +32,5 @@ func TestInsufficient(t *testing.T) {
|
||||
a := make(chan int)
|
||||
|
||||
_, err := merge(a)
|
||||
assert.Equal(t, err, InsufficientChannelsErr)
|
||||
assert.Equal(t, err, ErrInsufficientChannels)
|
||||
}
|
||||
|
@ -1,53 +0,0 @@
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
# ==================================================================================== #
|
||||
# HELPERS
|
||||
# ==================================================================================== #
|
||||
|
||||
## help: print this help message
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo 'Usage:'
|
||||
@sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /'
|
||||
|
||||
## all: tidy + audit + test/cover
|
||||
all: generate tidy test lint test/cover
|
||||
|
||||
|
||||
# ==================================================================================== #
|
||||
# QUALITY CONTROL
|
||||
# ==================================================================================== #
|
||||
|
||||
## tidy: format code and tidy modfile
|
||||
.PHONY: tidy
|
||||
tidy:
|
||||
go fmt ./...
|
||||
goimports -local=$(shell cat go.mod | grep module | awk '{print $$2}')/ -w .
|
||||
go mod tidy -v
|
||||
|
||||
## audit: run quality control checks
|
||||
.PHONY: lint
|
||||
lint:
|
||||
go mod verify
|
||||
go run github.com/golangci/golangci-lint/cmd/golangci-lint@latest run -v ./...
|
||||
|
||||
|
||||
# ==================================================================================== #
|
||||
# DEVELOPMENT
|
||||
# ==================================================================================== #
|
||||
|
||||
## generate: run all generators
|
||||
.PHONY: generate
|
||||
generate:
|
||||
go generate ./...
|
||||
|
||||
## test: run all tests
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -race -buildvcs ./...
|
||||
|
||||
## test/cover: run all tests and display coverage
|
||||
.PHONY: test/cover
|
||||
test/cover:
|
||||
go test -race -buildvcs -coverprofile=/tmp/coverage.out ./...
|
||||
go tool cover -html=/tmp/coverage.out
|
@ -1,11 +0,0 @@
|
||||
module pipeline
|
||||
|
||||
go 1.21.6
|
||||
|
||||
require github.com/stretchr/testify v1.8.4
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
@ -1,10 +0,0 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package pipeline
|
||||
|
||||
func Pipe[In any, Out any](in <-chan In, pipe func(In) Out) <-chan Out {
|
||||
out := make(chan Out)
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package pipeline
|
||||
|
||||
import (
|
||||
"testing"
|
@ -1,53 +0,0 @@
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
# ==================================================================================== #
|
||||
# HELPERS
|
||||
# ==================================================================================== #
|
||||
|
||||
## help: print this help message
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo 'Usage:'
|
||||
@sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /'
|
||||
|
||||
## all: tidy + audit + test/cover
|
||||
all: generate tidy test lint test/cover
|
||||
|
||||
|
||||
# ==================================================================================== #
|
||||
# QUALITY CONTROL
|
||||
# ==================================================================================== #
|
||||
|
||||
## tidy: format code and tidy modfile
|
||||
.PHONY: tidy
|
||||
tidy:
|
||||
go fmt ./...
|
||||
goimports -local=$(shell cat go.mod | grep module | awk '{print $$2}')/ -w .
|
||||
go mod tidy -v
|
||||
|
||||
## audit: run quality control checks
|
||||
.PHONY: lint
|
||||
lint:
|
||||
go mod verify
|
||||
go run github.com/golangci/golangci-lint/cmd/golangci-lint@latest run -v ./...
|
||||
|
||||
|
||||
# ==================================================================================== #
|
||||
# DEVELOPMENT
|
||||
# ==================================================================================== #
|
||||
|
||||
## generate: run all generators
|
||||
.PHONY: generate
|
||||
generate:
|
||||
go generate ./...
|
||||
|
||||
## test: run all tests
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -race -buildvcs ./...
|
||||
|
||||
## test/cover: run all tests and display coverage
|
||||
.PHONY: test/cover
|
||||
test/cover:
|
||||
go test -race -buildvcs -coverprofile=/tmp/coverage.out ./...
|
||||
go tool cover -html=/tmp/coverage.out
|
@ -1,3 +0,0 @@
|
||||
module semaphore
|
||||
|
||||
go 1.21.6
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package semaphore
|
||||
|
||||
import (
|
||||
"context"
|
@ -1,9 +1,8 @@
|
||||
package main
|
||||
package semaphore
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPipe(t *testing.T) {
|
||||
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
# ==================================================================================== #
|
||||
# HELPERS
|
||||
# ==================================================================================== #
|
||||
|
||||
## help: print this help message
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo 'Usage:'
|
||||
@sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /'
|
||||
|
||||
## all: tidy + audit + test/cover
|
||||
all: tidy audit test/cover
|
||||
|
||||
# ==================================================================================== #
|
||||
# QUALITY CONTROL
|
||||
# ==================================================================================== #
|
||||
|
||||
## tidy: format code and tidy modfile
|
||||
.PHONY: tidy
|
||||
tidy:
|
||||
go fmt ./...
|
||||
go mod tidy -v
|
||||
|
||||
## audit: run quality control checks
|
||||
.PHONY: audit
|
||||
audit:
|
||||
go mod verify
|
||||
go vet ./...
|
||||
go run honnef.co/go/tools/cmd/staticcheck@latest -checks=all,-ST1000,-U1000 ./...
|
||||
go run golang.org/x/vuln/cmd/govulncheck@latest ./...
|
||||
go test -race -buildvcs -vet=off ./...
|
||||
go run github.com/golangci/golangci-lint/cmd/golangci-lint@latest run -v ./...
|
||||
|
||||
|
||||
# ==================================================================================== #
|
||||
# DEVELOPMENT
|
||||
# ==================================================================================== #
|
||||
|
||||
## test: run all tests
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -v -race -buildvcs ./...
|
||||
|
||||
## test/cover: run all tests and display coverage
|
||||
.PHONY: test/cover
|
||||
test/cover:
|
||||
go test -v -race -buildvcs -coverprofile=/tmp/coverage.out ./...
|
||||
go tool cover -html=/tmp/coverage.out
|
@ -1,20 +1,21 @@
|
||||
package main
|
||||
package sortcli
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"golang.org/x/exp/slices"
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
// NL New line constant
|
||||
const NL = "\n"
|
||||
|
||||
type content [][]byte
|
||||
type Content [][]byte
|
||||
|
||||
func (c *content) Sort(reverse bool) {
|
||||
func (c *Content) Sort(reverse bool) {
|
||||
slices.SortFunc(*c, func(a, b []byte) int {
|
||||
if reverse {
|
||||
a, b = b, a
|
||||
@ -24,10 +25,10 @@ func (c *content) Sort(reverse bool) {
|
||||
})
|
||||
}
|
||||
|
||||
func (c *content) Uniques() {
|
||||
func (c *Content) Uniques() {
|
||||
m := make(map[string]struct{}, len(*c))
|
||||
|
||||
*c = slices.DeleteFunc[content, []byte](*c, func(line []byte) bool {
|
||||
*c = slices.DeleteFunc[Content, []byte](*c, func(line []byte) bool {
|
||||
if _, ok := m[string(line)]; !ok {
|
||||
m[string(line)] = struct{}{}
|
||||
|
||||
@ -38,7 +39,7 @@ func (c *content) Uniques() {
|
||||
})
|
||||
}
|
||||
|
||||
func (c *content) String() string {
|
||||
func (c *Content) String() string {
|
||||
lines := *c
|
||||
|
||||
var n int
|
||||
@ -63,7 +64,7 @@ func (c *content) String() string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (c *content) Load(r io.Reader) {
|
||||
func (c *Content) Load(r io.Reader) {
|
||||
br := bufio.NewReader(r)
|
||||
|
||||
for {
|
||||
|
@ -1,9 +1,10 @@
|
||||
package main
|
||||
package sortcli
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const input = `
|
||||
@ -15,7 +16,7 @@ Africa
|
||||
`
|
||||
|
||||
func TestLoad(t *testing.T) {
|
||||
c := &content{}
|
||||
c := &Content{}
|
||||
c.Load(strings.NewReader(input))
|
||||
|
||||
assert.Equal(t, input, c.String())
|
||||
@ -27,7 +28,8 @@ func TestUnique(t *testing.T) {
|
||||
Content string
|
||||
Expected string
|
||||
}{
|
||||
{"Unique",
|
||||
{
|
||||
"Unique",
|
||||
input,
|
||||
`
|
||||
Zimbabwe
|
||||
@ -40,7 +42,7 @@ America`,
|
||||
tc := tc
|
||||
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
c := &content{}
|
||||
c := &Content{}
|
||||
c.Load(strings.NewReader(tc.Content))
|
||||
|
||||
c.Uniques()
|
||||
|
@ -1,14 +0,0 @@
|
||||
module sort-cli
|
||||
|
||||
go 1.21.6
|
||||
|
||||
require (
|
||||
github.com/stretchr/testify v1.8.4
|
||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
@ -1,12 +0,0 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu+kQvCqcsoVaQgSV60o=
|
||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package sortcli
|
||||
|
||||
import (
|
||||
"io"
|
||||
@ -6,13 +6,13 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
func open(sources []string) io.Reader {
|
||||
func Open(sources []string) io.Reader {
|
||||
rs := make([]io.Reader, 0, len(sources))
|
||||
|
||||
for _, source := range sources {
|
||||
var r io.Reader
|
||||
|
||||
if source == stdin {
|
||||
if source == "-" {
|
||||
r = os.Stdin
|
||||
} else {
|
||||
if _, err := os.Stat(source); err != nil {
|
||||
|
14
sqlc.yaml
Normal file
14
sqlc.yaml
Normal file
@ -0,0 +1,14 @@
|
||||
version: "2"
|
||||
sql:
|
||||
- engine: "postgresql"
|
||||
queries: "string-unpack/internal/sql/"
|
||||
schema: "string-unpack/internal/db/schema.sql"
|
||||
gen:
|
||||
go:
|
||||
out: "string-unpack/internal/sql"
|
||||
sql_package: "pgx/v5"
|
||||
emit_db_tags: true
|
||||
emit_interface: true
|
||||
emit_json_tags: true
|
||||
emit_methods_with_db_argument: false
|
||||
query_parameter_limit: 0
|
10
string-unpack/internal/db/schema.sql
Normal file
10
string-unpack/internal/db/schema.sql
Normal file
@ -0,0 +1,10 @@
|
||||
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
||||
|
||||
CREATE TABLE unpack_history
|
||||
(
|
||||
id uuid default gen_random_uuid() primary key,
|
||||
input text NOT NULL,
|
||||
result text NOT NULL,
|
||||
created_at timestamptz DEFAULT NOW()
|
||||
)
|
||||
;
|
32
string-unpack/internal/sql/db.go
Normal file
32
string-unpack/internal/sql/db.go
Normal file
@ -0,0 +1,32 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.26.0
|
||||
|
||||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/jackc/pgx/v5/pgconn"
|
||||
)
|
||||
|
||||
type DBTX interface {
|
||||
Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error)
|
||||
Query(context.Context, string, ...interface{}) (pgx.Rows, error)
|
||||
QueryRow(context.Context, string, ...interface{}) pgx.Row
|
||||
}
|
||||
|
||||
func New(db DBTX) *Queries {
|
||||
return &Queries{db: db}
|
||||
}
|
||||
|
||||
type Queries struct {
|
||||
db DBTX
|
||||
}
|
||||
|
||||
func (q *Queries) WithTx(tx pgx.Tx) *Queries {
|
||||
return &Queries{
|
||||
db: tx,
|
||||
}
|
||||
}
|
9
string-unpack/internal/sql/insert.sql
Normal file
9
string-unpack/internal/sql/insert.sql
Normal file
@ -0,0 +1,9 @@
|
||||
-- name: Insert :one
|
||||
INSERT INTO unpack_history (input, result)
|
||||
VALUES (@input, @result)
|
||||
RETURNING
|
||||
id,
|
||||
input,
|
||||
result,
|
||||
created_at
|
||||
;
|
37
string-unpack/internal/sql/insert.sql.go
Normal file
37
string-unpack/internal/sql/insert.sql.go
Normal file
@ -0,0 +1,37 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.26.0
|
||||
// source: insert.sql
|
||||
|
||||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const insert = `-- name: Insert :one
|
||||
INSERT INTO unpack_history (input, result)
|
||||
VALUES ($1, $2)
|
||||
RETURNING
|
||||
id,
|
||||
input,
|
||||
result,
|
||||
created_at
|
||||
`
|
||||
|
||||
type InsertParams struct {
|
||||
Input string `db:"input" json:"input"`
|
||||
Result string `db:"result" json:"result"`
|
||||
}
|
||||
|
||||
func (q *Queries) Insert(ctx context.Context, arg InsertParams) (UnpackHistory, error) {
|
||||
row := q.db.QueryRow(ctx, insert, arg.Input, arg.Result)
|
||||
var i UnpackHistory
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.Input,
|
||||
&i.Result,
|
||||
&i.CreatedAt,
|
||||
)
|
||||
return i, err
|
||||
}
|
9
string-unpack/internal/sql/latest.sql
Normal file
9
string-unpack/internal/sql/latest.sql
Normal file
@ -0,0 +1,9 @@
|
||||
-- name: Latest :many
|
||||
SELECT id,
|
||||
input,
|
||||
result,
|
||||
created_at
|
||||
FROM unpack_history
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 15
|
||||
;
|
45
string-unpack/internal/sql/latest.sql.go
Normal file
45
string-unpack/internal/sql/latest.sql.go
Normal file
@ -0,0 +1,45 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.26.0
|
||||
// source: latest.sql
|
||||
|
||||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
const latest = `-- name: Latest :many
|
||||
SELECT id,
|
||||
input,
|
||||
result,
|
||||
created_at
|
||||
FROM unpack_history
|
||||
ORDER BY created_at DESC
|
||||
LIMIT 15
|
||||
`
|
||||
|
||||
func (q *Queries) Latest(ctx context.Context) ([]UnpackHistory, error) {
|
||||
rows, err := q.db.Query(ctx, latest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []UnpackHistory
|
||||
for rows.Next() {
|
||||
var i UnpackHistory
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.Input,
|
||||
&i.Result,
|
||||
&i.CreatedAt,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
16
string-unpack/internal/sql/models.go
Normal file
16
string-unpack/internal/sql/models.go
Normal file
@ -0,0 +1,16 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.26.0
|
||||
|
||||
package sql
|
||||
|
||||
import (
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type UnpackHistory struct {
|
||||
ID pgtype.UUID `db:"id" json:"id"`
|
||||
Input string `db:"input" json:"input"`
|
||||
Result string `db:"result" json:"result"`
|
||||
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
||||
}
|
16
string-unpack/internal/sql/querier.go
Normal file
16
string-unpack/internal/sql/querier.go
Normal file
@ -0,0 +1,16 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.26.0
|
||||
|
||||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type Querier interface {
|
||||
Insert(ctx context.Context, arg InsertParams) (UnpackHistory, error)
|
||||
Latest(ctx context.Context) ([]UnpackHistory, error)
|
||||
}
|
||||
|
||||
var _ Querier = (*Queries)(nil)
|
78
string-unpack/server.go
Normal file
78
string-unpack/server.go
Normal file
@ -0,0 +1,78 @@
|
||||
package stringunpack
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"git.grachevko.ru/grachevko/h/string-unpack/internal/sql"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var queries sql.Querier
|
||||
|
||||
func Setup(ctx context.Context, logger *zap.Logger, r *gin.RouterGroup, conn *pgx.Conn) {
|
||||
if queries != nil {
|
||||
panic("Setup must call only once")
|
||||
}
|
||||
|
||||
queries = sql.New(conn)
|
||||
|
||||
unpack := func(input string) (r string, err error) {
|
||||
r, err = Unpack(input)
|
||||
|
||||
{ // history
|
||||
result := r
|
||||
if err != nil {
|
||||
result = fmt.Sprintf("err: %s", err.Error())
|
||||
}
|
||||
_, err := queries.Insert(ctx, sql.InsertParams{
|
||||
Input: input,
|
||||
Result: result,
|
||||
})
|
||||
if err != nil {
|
||||
logger.Error("pg insert", zap.Error(err))
|
||||
}
|
||||
} // history
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
r.GET("history", func(c *gin.Context) {
|
||||
latest, err := queries.Latest(ctx)
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
|
||||
"err": err.Error(),
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, latest)
|
||||
})
|
||||
|
||||
r.GET(":s", func(c *gin.Context) {
|
||||
s := c.Param("s")
|
||||
|
||||
result, err := unpack(s)
|
||||
if errors.Is(err, ErrIncorrectString) {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{
|
||||
"err": err.Error(),
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
logger.Error("unpack", zap.Error(err))
|
||||
|
||||
c.AbortWithStatus(http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"result": result,
|
||||
})
|
||||
})
|
||||
}
|
54
string-unpack/unpack.go
Normal file
54
string-unpack/unpack.go
Normal file
@ -0,0 +1,54 @@
|
||||
package stringunpack
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var ErrIncorrectString = errors.New("incorrect string")
|
||||
|
||||
func Unpack(s string) (string, error) {
|
||||
if s == "" {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
var sb strings.Builder
|
||||
sb.Grow(len(s))
|
||||
|
||||
var curSymbol rune
|
||||
for _, r := range s {
|
||||
isNumber := false
|
||||
number := 0
|
||||
if n, err := strconv.Atoi(string(r)); err == nil {
|
||||
number = n
|
||||
isNumber = true
|
||||
}
|
||||
|
||||
if curSymbol == rune(0) {
|
||||
switch {
|
||||
case isNumber:
|
||||
return "", ErrIncorrectString
|
||||
case !isNumber:
|
||||
curSymbol = r
|
||||
}
|
||||
} else {
|
||||
switch {
|
||||
case !isNumber:
|
||||
sb.WriteRune(curSymbol)
|
||||
curSymbol = r
|
||||
case isNumber:
|
||||
for i := 0; i < number; i++ {
|
||||
sb.WriteRune(curSymbol)
|
||||
}
|
||||
curSymbol = rune(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if curSymbol != rune(0) {
|
||||
sb.WriteRune(curSymbol)
|
||||
}
|
||||
|
||||
return sb.String(), nil
|
||||
}
|
44
string-unpack/unpack_test.go
Normal file
44
string-unpack/unpack_test.go
Normal file
@ -0,0 +1,44 @@
|
||||
package stringunpack_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
stringunpack "git.grachevko.ru/grachevko/h/string-unpack"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestUnpack(t *testing.T) {
|
||||
testcases := []struct {
|
||||
input string
|
||||
expected string
|
||||
}{
|
||||
{input: "a4bc2d5e", expected: "aaaabccddddde"},
|
||||
{input: "abcd", expected: "abcd"},
|
||||
{input: "aaa0b", expected: "aab"},
|
||||
{input: "", expected: ""},
|
||||
{input: "d\n5abc", expected: "d\n\n\n\n\nabc"},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.input, func(t *testing.T) {
|
||||
result, err := stringunpack.Unpack(tc.input)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnpackIncorrectString(t *testing.T) {
|
||||
testcases := []string{
|
||||
"3abc",
|
||||
"45",
|
||||
"aaa10b",
|
||||
}
|
||||
|
||||
for _, input := range testcases {
|
||||
t.Run(input, func(t *testing.T) {
|
||||
_, err := stringunpack.Unpack(input)
|
||||
assert.Equal(t, stringunpack.ErrIncorrectString, err)
|
||||
})
|
||||
}
|
||||
}
|
0
tmp/.gitkeep
Normal file
0
tmp/.gitkeep
Normal file
@ -1,48 +0,0 @@
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
# ==================================================================================== #
|
||||
# HELPERS
|
||||
# ==================================================================================== #
|
||||
|
||||
## help: print this help message
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo 'Usage:'
|
||||
@sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /'
|
||||
|
||||
|
||||
# ==================================================================================== #
|
||||
# QUALITY CONTROL
|
||||
# ==================================================================================== #
|
||||
|
||||
## tidy: format code and tidy modfile
|
||||
.PHONY: tidy
|
||||
tidy:
|
||||
go fmt ./...
|
||||
go mod tidy -v
|
||||
|
||||
## audit: run quality control checks
|
||||
.PHONY: audit
|
||||
audit:
|
||||
go mod verify
|
||||
go vet ./...
|
||||
go run honnef.co/go/tools/cmd/staticcheck@latest -checks=all,-ST1000,-U1000 ./...
|
||||
go run golang.org/x/vuln/cmd/govulncheck@latest ./...
|
||||
go test -race -buildvcs -vet=off ./...
|
||||
go run github.com/golangci/golangci-lint/cmd/golangci-lint@latest run -v ./...
|
||||
|
||||
|
||||
# ==================================================================================== #
|
||||
# DEVELOPMENT
|
||||
# ==================================================================================== #
|
||||
|
||||
## test: run all tests
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -v -race -buildvcs ./...
|
||||
|
||||
## test/cover: run all tests and display coverage
|
||||
.PHONY: test/cover
|
||||
test/cover:
|
||||
go test -v -race -buildvcs -coverprofile=/tmp/coverage.out ./...
|
||||
go tool cover -html=/tmp/coverage.out
|
@ -1,10 +0,0 @@
|
||||
module uniqueschars
|
||||
|
||||
go 1.21.6
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/testify v1.8.4 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
@ -1,9 +0,0 @@
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
@ -1,8 +1,9 @@
|
||||
package uniqueschars
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestUnique(t *testing.T) {
|
@ -1,53 +0,0 @@
|
||||
.DEFAULT_GOAL := help
|
||||
|
||||
# ==================================================================================== #
|
||||
# HELPERS
|
||||
# ==================================================================================== #
|
||||
|
||||
## help: print this help message
|
||||
.PHONY: help
|
||||
help:
|
||||
@echo 'Usage:'
|
||||
@sed -n 's/^##//p' ${MAKEFILE_LIST} | column -t -s ':' | sed -e 's/^/ /'
|
||||
|
||||
## all: tidy + audit + test/cover
|
||||
all: generate tidy test lint test/cover
|
||||
|
||||
|
||||
# ==================================================================================== #
|
||||
# QUALITY CONTROL
|
||||
# ==================================================================================== #
|
||||
|
||||
## tidy: format code and tidy modfile
|
||||
.PHONY: tidy
|
||||
tidy:
|
||||
go fmt ./...
|
||||
goimports -local=$(shell cat go.mod | grep module | awk '{print $$2}')/ -w .
|
||||
go mod tidy -v
|
||||
|
||||
## audit: run quality control checks
|
||||
.PHONY: lint
|
||||
lint:
|
||||
go mod verify
|
||||
go run github.com/golangci/golangci-lint/cmd/golangci-lint@latest run -v ./...
|
||||
|
||||
|
||||
# ==================================================================================== #
|
||||
# DEVELOPMENT
|
||||
# ==================================================================================== #
|
||||
|
||||
## generate: run all generators
|
||||
.PHONY: generate
|
||||
generate:
|
||||
go generate ./...
|
||||
|
||||
## test: run all tests
|
||||
.PHONY: test
|
||||
test:
|
||||
go test -race -buildvcs ./...
|
||||
|
||||
## test/cover: run all tests and display coverage
|
||||
.PHONY: test/cover
|
||||
test/cover:
|
||||
go test -race -buildvcs -coverprofile=/tmp/coverage.out ./...
|
||||
go tool cover -html=/tmp/coverage.out
|
@ -1,11 +0,0 @@
|
||||
module worker-pool
|
||||
|
||||
go 1.21.6
|
||||
|
||||
require github.com/stretchr/testify v1.8.4
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package workerpool
|
||||
|
||||
import (
|
||||
"fmt"
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package workerpool
|
||||
|
||||
import (
|
||||
"fmt"
|
Reference in New Issue
Block a user