Draft: big refactor
This commit is contained in:
3
Makefile
3
Makefile
@@ -3,6 +3,7 @@
|
||||
SWAG ?= ~/go/bin/swag
|
||||
|
||||
TARGET := $(shell find . -type f -name '*.go')
|
||||
DEST := server/docs
|
||||
|
||||
all: swagger docker install
|
||||
|
||||
@@ -17,7 +18,7 @@ game: $(TARGET)
|
||||
|
||||
swagger:
|
||||
$(SWAG) fmt
|
||||
$(SWAG) init -o backend/docs -g cmd/serve/backend.go -pdl 1
|
||||
$(SWAG) init -o $(DEST) -g cmd/serve/backend.go -pdl 1
|
||||
|
||||
clean:
|
||||
-rm -f game
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"gitea.konchin.com/ytshih/inp2025/game/backend/middlewares"
|
||||
"github.com/uptrace/bunrouter"
|
||||
)
|
||||
|
||||
// GetLobbyRooms
|
||||
//
|
||||
// @Router /api/lobby/rooms [get]
|
||||
func (self *Handlers) GetLobbyRooms(
|
||||
w http.ResponseWriter,
|
||||
req bunrouter.Request,
|
||||
) error {
|
||||
ctx := req.Context()
|
||||
|
||||
rooms, err := self.db.GetRooms(ctx)
|
||||
if err != nil {
|
||||
return middlewares.HTTPError{
|
||||
StatusCode: http.StatusInternalServerError,
|
||||
Message: "failed to get room",
|
||||
OriginError: err,
|
||||
}
|
||||
}
|
||||
|
||||
return bunrouter.JSON(w, rooms)
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/spf13/cobra"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var RootCmd = &cobra.Command{
|
||||
@@ -15,25 +16,35 @@ var RootCmd = &cobra.Command{
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
appname := "game-tui"
|
||||
tracing.InitTracer(appname)
|
||||
defer tracing.DeferTracer()
|
||||
|
||||
tracing.Logger.
|
||||
Info("client up")
|
||||
|
||||
client := resty.New().
|
||||
SetBaseURL(args[0]).
|
||||
SetDisableWarn(true)
|
||||
|
||||
queue := []*tea.Program{}
|
||||
queue = append(queue,
|
||||
tea.NewProgram(plays.NewLanding(plays.NewBase(client))))
|
||||
queue = append(queue, tea.NewProgram(
|
||||
plays.NewLanding(plays.NewBase(client))))
|
||||
|
||||
for len(queue) > 0 {
|
||||
program := queue[0]
|
||||
queue = queue[1:]
|
||||
|
||||
tracing.Logger.Info("run program")
|
||||
|
||||
res, err := program.Run()
|
||||
if err != nil {
|
||||
tracing.Logger.Error("program failed",
|
||||
zap.Error(err))
|
||||
panic(err)
|
||||
}
|
||||
err = res.(plays.Next).Next(&queue)
|
||||
if err != nil {
|
||||
tracing.Logger.Error("failed to generate next program",
|
||||
zap.Error(err))
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
@@ -41,4 +52,7 @@ var RootCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
func init() {
|
||||
RootCmd.Flags().
|
||||
String("otel-endpoint", "localhost:4317",
|
||||
"endpoint for otlp exporter to connect")
|
||||
}
|
||||
|
||||
@@ -16,35 +16,36 @@ import (
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
"go.uber.org/zap"
|
||||
|
||||
_ "gitea.konchin.com/ytshih/inp2025/game/backend/docs"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/backend/handlers/api"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/backend/handlers/auth"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/backend/middlewares"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/implements"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/server/backend/api"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/server/backend/auth"
|
||||
_ "gitea.konchin.com/ytshih/inp2025/game/server/docs"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/server/middlewares"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/tracing"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/utils"
|
||||
)
|
||||
|
||||
// @title Intro. to Network Programming Game
|
||||
// @version 0.0.1-alpha
|
||||
// @license.name 0BSD
|
||||
// @securityDefinitions.basic BasicAuth
|
||||
// @BasePath /
|
||||
// @title Intro. to Network Programming Game
|
||||
// @version 0.0.1-alpha
|
||||
// @license.name 0BSD
|
||||
// @securityDefinitions.basic BasicAuth
|
||||
// @BasePath /
|
||||
var backendCmd = &cobra.Command{
|
||||
Use: "backend",
|
||||
Short: "Game backend",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
ctx := cmd.Context()
|
||||
tracing.InitTracer("game backend")
|
||||
defer tracing.DeferTracer()
|
||||
|
||||
tracing.Logger.Ctx(ctx).
|
||||
tracing.Logger.
|
||||
Debug("connect to sql",
|
||||
zap.String("sql.url",
|
||||
"file:"+viper.GetString("sqlite-file")+"?cache=shared&mode=rwc"))
|
||||
sqldb, err := sql.Open(sqliteshim.ShimName,
|
||||
"file:"+viper.GetString("sqlite-file")+"?cache=shared&mode=rwc")
|
||||
if err != nil {
|
||||
tracing.Logger.Ctx(ctx).
|
||||
tracing.Logger.
|
||||
Panic("failed to init sqlite",
|
||||
zap.Error(err))
|
||||
panic(err)
|
||||
@@ -52,7 +53,7 @@ var backendCmd = &cobra.Command{
|
||||
bunDB := bun.NewDB(sqldb, sqlitedialect.New())
|
||||
bunDB.AddQueryHook(bunotel.NewQueryHook(bunotel.WithDBName("sqlite")))
|
||||
if err := utils.InitDB(ctx, bunDB); err != nil {
|
||||
tracing.Logger.Ctx(ctx).
|
||||
tracing.Logger.
|
||||
Panic("failed to init db schema",
|
||||
zap.Error(err))
|
||||
panic(err)
|
||||
@@ -91,7 +92,7 @@ var backendCmd = &cobra.Command{
|
||||
apiGroup.GET("/lobby/users",
|
||||
apiHandlers.GetLobbyUsers)
|
||||
|
||||
tracing.Logger.Ctx(ctx).
|
||||
tracing.Logger.
|
||||
Info("http server up",
|
||||
zap.String("http.port", viper.GetString("port")))
|
||||
|
||||
@@ -101,6 +102,8 @@ var backendCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
func init() {
|
||||
backendCmd.Flags().
|
||||
String("otel-endpoint", "backend-otelcol:4317", "otelcol endpoint")
|
||||
backendCmd.Flags().
|
||||
String("port", "8080", "Port to listen on")
|
||||
backendCmd.Flags().
|
||||
|
||||
@@ -1,9 +1,28 @@
|
||||
---
|
||||
services:
|
||||
backend-otelcol:
|
||||
image: otel/opentelemetry-collector-contrib
|
||||
command:
|
||||
- --config=/etc/otelcol/config.yaml
|
||||
volumes:
|
||||
- ./docker/otelcol/config.yaml:/etc/otelcol/config.yaml
|
||||
|
||||
backend:
|
||||
build:
|
||||
context: .
|
||||
env_file: ./backend/.env
|
||||
env_file: ./server/.env
|
||||
ports:
|
||||
- 8081:8080
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
- backend-otelcol
|
||||
|
||||
client-otelcol:
|
||||
image: otel/opentelemetry-collector-contrib
|
||||
command:
|
||||
- --config=/etc/otelcol/config.yaml
|
||||
ports:
|
||||
- 4317:4317
|
||||
- 4318:4318
|
||||
volumes:
|
||||
- ./docker/otelcol/config.yaml:/etc/otelcol/config.yaml
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
receivers:
|
||||
otlp:
|
||||
protocols:
|
||||
http: 0.0.0.0:4138
|
||||
grpc: 0.0.0.0:4137
|
||||
|
||||
processors:
|
||||
batch:
|
||||
grpc:
|
||||
endpoint: 0.0.0.0:4317
|
||||
http:
|
||||
endpoint: 0.0.0.0:4318
|
||||
|
||||
exporters:
|
||||
logging:
|
||||
loglevel: debug
|
||||
debug:
|
||||
verbosity: detailed
|
||||
|
||||
service:
|
||||
pipelines:
|
||||
logs:
|
||||
receivers: [otlp]
|
||||
processors: [batch]
|
||||
exporters: [logging]
|
||||
exporters: [debug]
|
||||
|
||||
26
go.mod
26
go.mod
@@ -23,7 +23,7 @@ require (
|
||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||
github.com/atotto/clipboard v0.1.4 // indirect
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.2 // indirect
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 // indirect
|
||||
github.com/charmbracelet/bubbles v0.21.0 // indirect
|
||||
github.com/charmbracelet/bubbletea v1.3.7 // indirect
|
||||
github.com/charmbracelet/colorprofile v0.3.2 // indirect
|
||||
@@ -44,7 +44,8 @@ require (
|
||||
github.com/go-resty/resty/v2 v2.16.5 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
@@ -77,28 +78,31 @@ require (
|
||||
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/bridges/otelzap v0.13.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/runtime v0.62.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.14.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.13.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 // indirect
|
||||
go.opentelemetry.io/otel/log v0.13.0 // indirect
|
||||
go.opentelemetry.io/otel/log v0.14.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/log v0.13.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/log v0.14.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.7.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v1.7.1 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250711185948-6ae5c78190dc // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/net v0.43.0 // indirect
|
||||
golang.org/x/sys v0.36.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
golang.org/x/tools v0.35.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
|
||||
google.golang.org/grpc v1.73.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect
|
||||
google.golang.org/grpc v1.75.0 // indirect
|
||||
google.golang.org/protobuf v1.36.8 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
modernc.org/libc v1.66.3 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
|
||||
30
go.sum
30
go.sum
@@ -6,6 +6,8 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||
github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8=
|
||||
github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3 h1:ZN+IMa753KfX5hd8vVaMixjnqRZ3y8CuJKRKj1xcsSM=
|
||||
github.com/cenkalti/backoff/v5 v5.0.3/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||
github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs=
|
||||
github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg=
|
||||
github.com/charmbracelet/bubbletea v1.3.7 h1:FNaEEFEenOEPnZsY9MI64thl2c84MI66+1QaQbxGOl4=
|
||||
@@ -67,8 +69,12 @@ github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17k
|
||||
github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 h1:X5VWvz21y3gzm9Nw/kaUeku/1+uBhcekkmy4IkffJww=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1/go.mod h1:Zanoh4+gvIgluNqcfMVTJueD4wSS5hT7zTt4Mrutd90=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2 h1:8Tjv8EJ+pM1xP8mK6egEbD1OgnVTyacbefKhmbLhIhU=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.2/go.mod h1:pkJQ2tZHJ0aFOVEEot6oZmaVEZcRme73eIFmhiVuRWs=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
@@ -181,18 +187,26 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavM
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/bridges/otelzap v0.13.0 h1:aBKdhLVieqvwWe9A79UHI/0vgp2t/s2euY8X59pGRlw=
|
||||
go.opentelemetry.io/contrib/bridges/otelzap v0.13.0/go.mod h1:SYqtxLQE7iINgh6WFuVi2AI70148B8EI35DSk0Wr8m4=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0 h1:RbKq8BG0FI8OiXhBfcRtqqHcZcka+gU3cskNuf05R18=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.63.0/go.mod h1:h06DGIukJOevXaj/xrNjhi/2098RZzcLTbc0jDAUbsg=
|
||||
go.opentelemetry.io/contrib/instrumentation/runtime v0.62.0 h1:ZIt0ya9/y4WyRIzfLC8hQRRsWg0J9M9GyaGtIMiElZI=
|
||||
go.opentelemetry.io/contrib/instrumentation/runtime v0.62.0/go.mod h1:F1aJ9VuiKWOlWwKdTYDUp1aoS0HzQxg38/VLxKmhm5U=
|
||||
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
||||
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.14.0 h1:OMqPldHt79PqWKOMYIAQs3CxAi7RLgPxwfFSwr4ZxtM=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.14.0/go.mod h1:1biG4qiqTxKiUCtoWDPpL3fB3KxVwCiGw81j3nKMuHE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.13.0 h1:zUfYw8cscHHLwaY8Xz3fiJu+R59xBnkgq2Zr1lwmK/0=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.13.0/go.mod h1:514JLMCcFLQFS8cnTepOk6I09cKWJ5nGHBxHrMJ8Yfg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.37.0 h1:9PgnL3QNlj10uGxExowIDIZu66aVBwWhXmbOp1pa6RA=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.37.0/go.mod h1:0ineDcLELf6JmKfuo0wvvhAVMuxWFYvkTin2iV4ydPQ=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 h1:Ahq7pZmv87yiyn3jeFz/LekZmPLLdKejuO3NcK9MssM=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0/go.mod h1:MJTqhM0im3mRLw1i8uGHnCvUEeS7VwRyxlLC78PA18M=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0 h1:GqRJVj7UmLjCVyVJ3ZFLdPRmhDUp2zFmQe3RHIOsw24=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.38.0/go.mod h1:ri3aaHSmCTVYu2AWv44YMauwAQc0aqI9gHKIcSbI1pU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0 h1:lwI4Dc5leUqENgGuQImwLo4WnuXFPetmPpkLi2IrX54=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.38.0/go.mod h1:Kz/oCE7z5wuyhPxsXDuaPteSWqjSBD5YaSdbxZYGbGk=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 h1:bDMKF3RUSxshZ5OjOTi8rsHGaPKsAt76FaqgvIUySLc=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0/go.mod h1:dDT67G/IkA46Mr2l9Uj7HsQVwsjASyV9SjGofsiUZDA=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 h1:SNhVp/9q4Go/XHBkQ1/d5u9P/U+L1yaGPoi0x+mStaI=
|
||||
@@ -201,18 +215,24 @@ go.opentelemetry.io/otel/log v0.6.0 h1:nH66tr+dmEgW5y+F9LanGJUBYPrRgP4g2EkmPE3Le
|
||||
go.opentelemetry.io/otel/log v0.6.0/go.mod h1:KdySypjQHhP069JX0z/t26VHwa8vSwzgaKmXtIB3fJM=
|
||||
go.opentelemetry.io/otel/log v0.13.0 h1:yoxRoIZcohB6Xf0lNv9QIyCzQvrtGZklVbdCoyb7dls=
|
||||
go.opentelemetry.io/otel/log v0.13.0/go.mod h1:INKfG4k1O9CL25BaM1qLe0zIedOpvlS5Z7XgSbmN83E=
|
||||
go.opentelemetry.io/otel/log v0.14.0 h1:2rzJ+pOAZ8qmZ3DDHg73NEKzSZkhkGIua9gXtxNGgrM=
|
||||
go.opentelemetry.io/otel/log v0.14.0/go.mod h1:5jRG92fEAgx0SU/vFPxmJvhIuDU9E1SUnEQrMlJpOno=
|
||||
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
||||
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
|
||||
go.opentelemetry.io/otel/sdk/log v0.13.0 h1:I3CGUszjM926OphK8ZdzF+kLqFvfRY/IIoFq/TjwfaQ=
|
||||
go.opentelemetry.io/otel/sdk/log v0.13.0/go.mod h1:lOrQyCCXmpZdN7NchXb6DOZZa1N5G1R2tm5GMMTpDBw=
|
||||
go.opentelemetry.io/otel/sdk/log v0.14.0 h1:JU/U3O7N6fsAXj0+CXz21Czg532dW2V4gG1HE/e8Zrg=
|
||||
go.opentelemetry.io/otel/sdk/log v0.14.0/go.mod h1:imQvII+0ZylXfKU7/wtOND8Hn4OpT3YUoIgqJVksUkM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
|
||||
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||
go.opentelemetry.io/proto/otlp v1.7.0 h1:jX1VolD6nHuFzOYso2E73H85i92Mv8JQYk0K9vz09os=
|
||||
go.opentelemetry.io/proto/otlp v1.7.0/go.mod h1:fSKjH6YJ7HDlwzltzyMj036AJ3ejJLCgCSHGj4efDDo=
|
||||
go.opentelemetry.io/proto/otlp v1.7.1 h1:gTOMpGDb0WTBOP8JaO72iL3auEZhVmAQg4ipjOVAtj4=
|
||||
go.opentelemetry.io/proto/otlp v1.7.1/go.mod h1:b2rVh6rfI/s2pHWNlB7ILJcRALpcNDzKhACevjI+ZnE=
|
||||
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.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
@@ -226,6 +246,8 @@ golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
|
||||
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
|
||||
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
|
||||
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -248,12 +270,20 @@ golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw
|
||||
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697 h1:ToEetK57OidYuqD4Q5w+vfEnPvPpuTwedCNVohYJfNk=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc=
|
||||
google.golang.org/grpc v1.73.0 h1:VIWSmpI2MegBtTuFt5/JWy2oXxtjJ/e89Z70ImfD2ok=
|
||||
google.golang.org/grpc v1.73.0/go.mod h1:50sbHOUqWoCQGI8V2HQLJM0B+LMlIUjNSZmow7EVBQc=
|
||||
google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4=
|
||||
google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
|
||||
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
13
go.work.sum
13
go.work.sum
@@ -1,6 +1,7 @@
|
||||
cel.dev/expr v0.16.1 h1:NR0+oFYzR1CqLFhTAqg3ql59G9VfN8fKq1TCHJ6gq1g=
|
||||
cel.dev/expr v0.16.1/go.mod h1:AsGA5zb3WruAEQeQng1RZdGEXmBj0jvMWh6l5SnNuC8=
|
||||
cel.dev/expr v0.23.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
|
||||
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
|
||||
cloud.google.com/go v0.116.0 h1:B3fRrSDkLRt5qSHWe40ERJvhvnQwdZiHu0bJOpldweE=
|
||||
cloud.google.com/go v0.116.0/go.mod h1:cEPSRWPzZEswwdr9BxE6ChEn01dWlTaF05LiC2Xs70U=
|
||||
cloud.google.com/go/auth v0.13.0 h1:8Fu8TZy167JkW8Tj3q7dIkr2v4cndv41ouecJx0PAHs=
|
||||
@@ -9,6 +10,7 @@ cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyT
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8=
|
||||
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
||||
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
||||
cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo=
|
||||
cloud.google.com/go/iam v1.2.2 h1:ozUSofHUGf/F4tCNy/mu9tHLTaxZFLOUiKzjcgWHGIA=
|
||||
cloud.google.com/go/iam v1.2.2/go.mod h1:0Ys8ccaZHdI1dEUilwzqng/6ps2YB6vRsjIe00/+6JY=
|
||||
cloud.google.com/go/monitoring v1.21.2 h1:FChwVtClH19E7pJ+e0xUhJPGksctZNVOk2UhMmblmdU=
|
||||
@@ -18,6 +20,7 @@ cloud.google.com/go/storage v1.49.0/go.mod h1:k1eHhhpLvrPjVGfo0mOUPEJ4Y2+a/Hv5Pi
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0/go.mod h1:yAZHSGnqScoU556rBOVkwLze6WP5N+U11RHuWaGVxwY=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0/go.mod h1:Cz6ft6Dkn3Et6l2v2a9/RpN7epQ1GtDlO6lj8bEcOvw=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1 h1:UQ0AhxogsIRZDkElkblfnwjc3IaltCm2HUMvezQaL7s=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.48.1/go.mod h1:jyqM3eLpJ3IbIFDTKVz2rF9T/xWGW0rIriGwnz8l9Tk=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.48.1 h1:8nn+rsCvTq9axyEh382S0PFLBeaFwNsT43IrPWzctRU=
|
||||
@@ -42,6 +45,7 @@ github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod
|
||||
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78 h1:QVw89YDxXxEe+l8gU8ETbOasdwEV+avkR75ZzsVV9WI=
|
||||
github.com/cncf/xds/go v0.0.0-20240905190251-b4127c9b8d78/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
|
||||
github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
|
||||
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
|
||||
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
|
||||
github.com/envoyproxy/go-control-plane v0.13.1 h1:vPfJZCkob6yTMEgS+0TwfTUfbHjfy/6vOJ8hUWX/uXE=
|
||||
@@ -55,7 +59,9 @@ github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2T
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
|
||||
github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA=
|
||||
github.com/golang/glog v1.2.4/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||
github.com/golang/glog v1.2.5/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
@@ -109,19 +115,24 @@ go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.29.0 h1:TiaiXB4DpGD3sdzNlYQxruQngn5Apwzi1X0DRhuGvDQ=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.29.0/go.mod h1:GW2aWZNwR2ZxDLdv8OyC2G8zkRoQBuURgV7RPQgcPoU=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.35.0/go.mod h1:qGWP8/+ILwMRIUf9uIVLloR1uo5ZYAslM4O6OqUi1DA=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.36.0/go.mod h1:IbBN8uAIIx734PTonTPxAxnjc2pQTxWNkwfstZ+6H2k=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 h1:r6I7RJCN86bpD/FQwedZ0vSixDpwuWREjW9oRMsmqDc=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0/go.mod h1:B9yO6b04uB80CzjedvewuqDhxJxi11s7/GtiGa8bAjI=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8=
|
||||
go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
|
||||
go.opentelemetry.io/otel/log/logtest v0.14.0/go.mod h1:IuguGt8XVP4XA4d2oEEDMVDBBCesMg8/tSGWDjuKfoA=
|
||||
go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
|
||||
go.opentelemetry.io/otel/sdk v1.29.0/go.mod h1:pM8Dx5WKnvxLCb+8lG1PRNIDxu9g9b9g59Qr7hfAAok=
|
||||
go.opentelemetry.io/otel/sdk/log/logtest v0.13.0/go.mod h1:QOGiAJHl+fob8Nu85ifXfuQYmJTFAvcrxL6w5/tu168=
|
||||
go.opentelemetry.io/otel/sdk/log/logtest v0.14.0/go.mod h1:dCU8aEL6q+L9cYTqcVOk8rM9Tp8WdnHOPLiBgp0SGOA=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.29.0/go.mod h1:6zZLdCl2fkauYoZIOn/soQIDSWFmNSRcICarHfuhNJQ=
|
||||
go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
|
||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
|
||||
golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
|
||||
golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
@@ -131,11 +142,13 @@ golang.org/x/telemetry v0.0.0-20250710130107-8d8967aff50b/go.mod h1:4ZwOYna0/zsO
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
|
||||
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
|
||||
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
|
||||
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools/go/expect v0.1.0-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
|
||||
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
|
||||
google.golang.org/api v0.215.0 h1:jdYF4qnyczlEz2ReWIsosNLDuzXyvFHJtI5gcr0J7t0=
|
||||
google.golang.org/api v0.215.0/go.mod h1:fta3CVtuJYOEdugLNWm6WodzOS8KdFckABwN4I40hzY=
|
||||
google.golang.org/genproto v0.0.0-20241118233622-e639e219e697/go.mod h1:JJrvXBWRZaFMxBufik1a4RpFw4HhgVtBBWQeQgUj2cc=
|
||||
|
||||
@@ -38,16 +38,6 @@ func (self *BunDatabase) GetUserStatuses(
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (self *BunDatabase) GetRooms(
|
||||
ctx context.Context,
|
||||
) ([]models.Room, error) {
|
||||
var ret []models.Room
|
||||
err := self.db.NewSelect().
|
||||
Model(&ret).
|
||||
Scan(ctx)
|
||||
return ret, err
|
||||
}
|
||||
|
||||
func (self *BunDatabase) InsertUser(
|
||||
ctx context.Context,
|
||||
user models.User,
|
||||
@@ -81,16 +71,6 @@ func (self *BunDatabase) InsertUserStatus(
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *BunDatabase) InsertRoom(
|
||||
ctx context.Context,
|
||||
room models.Room,
|
||||
) error {
|
||||
_, err := self.db.NewInsert().
|
||||
Model(&room).
|
||||
Exec(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *BunDatabase) DeleteUserStatus(
|
||||
ctx context.Context,
|
||||
username string,
|
||||
@@ -101,14 +81,3 @@ func (self *BunDatabase) DeleteUserStatus(
|
||||
Exec(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *BunDatabase) DeleteRoom(
|
||||
ctx context.Context,
|
||||
roomId int,
|
||||
) error {
|
||||
_, err := self.db.NewDelete().
|
||||
Model(&models.Room{Id: roomId}).
|
||||
WherePK().
|
||||
Exec(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -16,10 +16,6 @@ type Database interface {
|
||||
ctx context.Context,
|
||||
) ([]models.UserStatus, error)
|
||||
|
||||
GetRooms(
|
||||
ctx context.Context,
|
||||
) ([]models.Room, error)
|
||||
|
||||
InsertUser(
|
||||
ctx context.Context,
|
||||
user models.User,
|
||||
@@ -30,18 +26,8 @@ type Database interface {
|
||||
userStatus models.UserStatus,
|
||||
) error
|
||||
|
||||
InsertRoom(
|
||||
ctx context.Context,
|
||||
room models.Room,
|
||||
) error
|
||||
|
||||
DeleteUserStatus(
|
||||
ctx context.Context,
|
||||
username string,
|
||||
) error
|
||||
|
||||
DeleteRoom(
|
||||
ctx context.Context,
|
||||
roomId int,
|
||||
) error
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/uptrace/bun"
|
||||
)
|
||||
|
||||
type RoomType int
|
||||
|
||||
const (
|
||||
RoomTypeWordle RoomType = iota
|
||||
)
|
||||
|
||||
var (
|
||||
RoomTypeStr = []string{"Wordle"}
|
||||
)
|
||||
|
||||
type RoomStatus int
|
||||
|
||||
const (
|
||||
RoomStatusWaiting RoomStatus = iota
|
||||
RoomStatusPlaying
|
||||
RoomStatusEnded
|
||||
)
|
||||
|
||||
var (
|
||||
RoomStatusStr = []string{"Waiting", "Playing", "Ended"}
|
||||
)
|
||||
|
||||
type Room struct {
|
||||
bun.BaseModel `bun:"table:room"`
|
||||
|
||||
Id int `bun:"id,pk,autoincrement"`
|
||||
Creater string `bun:"creater"`
|
||||
Type RoomType `bun:"type"`
|
||||
Status RoomStatus `bun:"status"`
|
||||
}
|
||||
|
||||
func (self Room) View() string {
|
||||
return fmt.Sprintf("%2d. %10s %10s [%s]",
|
||||
self.Id,
|
||||
self.Creater,
|
||||
RoomTypeStr[self.Type],
|
||||
RoomStatusStr[self.Status],
|
||||
)
|
||||
}
|
||||
@@ -20,12 +20,14 @@ func Tick(d time.Duration) tea.Cmd {
|
||||
}
|
||||
|
||||
type Base struct {
|
||||
client *resty.Client
|
||||
client *resty.Client
|
||||
username string
|
||||
}
|
||||
|
||||
func NewBase(client *resty.Client) *Base {
|
||||
return &Base{
|
||||
client: client,
|
||||
client: client,
|
||||
username: "",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
121
plays/game.go
Normal file
121
plays/game.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package plays
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"sync"
|
||||
|
||||
"gitea.konchin.com/ytshih/inp2025/game/server/wordle"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/types"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
)
|
||||
|
||||
type Game struct {
|
||||
*Base
|
||||
server url.URL
|
||||
|
||||
mutex sync.RWMutex
|
||||
state types.WordleState
|
||||
|
||||
input string
|
||||
}
|
||||
|
||||
func (m *Game) GetState() {
|
||||
c, _, err := websocket.DefaultDialer.Dial(m.server.String(), nil)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to dial, %w", err))
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
for {
|
||||
_, b, err := c.ReadMessage()
|
||||
switch err.(type) {
|
||||
case nil:
|
||||
var state types.WordleState
|
||||
if err := msgpack.Unmarshal(b, &state); err != nil {
|
||||
panic(fmt.Errorf("failed to unmarshal state, %w", err))
|
||||
}
|
||||
|
||||
m.mutex.Lock()
|
||||
m.state = state
|
||||
m.mutex.Unlock()
|
||||
case *websocket.CloseError:
|
||||
return
|
||||
default:
|
||||
panic(fmt.Errorf("failed to read message, %w", err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func NewGame(base *Base, server url.URL) *Game {
|
||||
m := &Game{
|
||||
Base: base,
|
||||
server: server,
|
||||
state: types.NewWordleState(),
|
||||
input: "",
|
||||
}
|
||||
|
||||
go m.GetState()
|
||||
return m
|
||||
}
|
||||
|
||||
func (m *Game) Init() tea.Cmd {
|
||||
return tea.Batch(tea.ClearScreen)
|
||||
}
|
||||
|
||||
func (m *Game) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
if _, cmd := m.Base.Update(msg); cmd != nil {
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case tea.KeyMsg:
|
||||
switch msg.Type {
|
||||
case tea.KeyBackspace:
|
||||
if len(m.input) > 0 {
|
||||
m.input = m.input[:len(m.input)-1]
|
||||
}
|
||||
case tea.KeyEnter:
|
||||
if len(m.input) == types.MaxLength {
|
||||
return m, tea.Quit
|
||||
}
|
||||
case tea.KeyRunes:
|
||||
if len(m.input) < types.MaxLength {
|
||||
m.input = m.input + string(msg.Runes)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m *Game) View() string {
|
||||
m.mutex.RLock()
|
||||
ret := m.state.View()
|
||||
m.mutex.RUnlock()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (m *Game) Next(queue *[]*tea.Program) error {
|
||||
if len(m.input) == types.MaxLength {
|
||||
b, err := msgpack.Marshal(wordle.Operation{
|
||||
Type: wordle.OperationTypeGuess,
|
||||
Username: m.username,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = m.Base.client.R().
|
||||
SetBody(b).
|
||||
Post("/api/guess")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*queue = append(*queue,
|
||||
tea.NewProgram(NewGame(m.Base, m.server)))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
lobbyChoices = []string{"No-op", "Logout"}
|
||||
lobbyChoices = []string{"No-op", "Create Room", "Logout"}
|
||||
)
|
||||
|
||||
type Lobby struct {
|
||||
@@ -25,18 +25,18 @@ type Lobby struct {
|
||||
|
||||
updateCh chan struct{}
|
||||
users []models.UserStatus
|
||||
rooms []models.Room
|
||||
rooms []types.Room
|
||||
}
|
||||
|
||||
func NewLobby(base *Base) *Lobby {
|
||||
m := Lobby{
|
||||
m := &Lobby{
|
||||
Base: base,
|
||||
choice: "",
|
||||
cursor: 0,
|
||||
updateCh: make(chan struct{}, 1),
|
||||
}
|
||||
|
||||
return &m
|
||||
return m
|
||||
}
|
||||
|
||||
func updateLobbyInfo(m *Lobby) error {
|
||||
@@ -58,7 +58,8 @@ func updateLobbyInfo(m *Lobby) error {
|
||||
}
|
||||
m.users = users
|
||||
|
||||
var rooms []models.Room
|
||||
var rooms []types.Room
|
||||
// TODO: scan rooms
|
||||
_, err = m.Base.client.R().
|
||||
SetResult(&rooms).
|
||||
ForceContentType("application/json").
|
||||
@@ -147,6 +148,9 @@ func (m *Lobby) Next(queue *[]*tea.Program) error {
|
||||
case "No-op":
|
||||
*queue = append(*queue,
|
||||
tea.NewProgram(NewLobby(m.Base)))
|
||||
case "Create Room":
|
||||
*queue = append(*queue,
|
||||
tea.NewProgram(NewRoomWaiting(m.Base)))
|
||||
case "Logout":
|
||||
*queue = append(*queue,
|
||||
tea.NewProgram(NewLogout(m.Base)))
|
||||
|
||||
@@ -125,6 +125,7 @@ func (m *Login) Next(queue *[]*tea.Program) error {
|
||||
if resp.StatusCode() == http.StatusOK {
|
||||
m.Base.client.
|
||||
SetBasicAuth(username, password)
|
||||
m.Base.username = username
|
||||
*queue = append(*queue,
|
||||
tea.NewProgram(NewLobby(m.Base)))
|
||||
} else {
|
||||
|
||||
@@ -123,17 +123,19 @@ func (m *Register) Next(queue *[]*tea.Program) error {
|
||||
}).
|
||||
Post("/auth/register")
|
||||
|
||||
switch resp.StatusCode() {
|
||||
case http.StatusOK:
|
||||
if err == nil && resp.StatusCode() == http.StatusOK {
|
||||
*queue = append(*queue,
|
||||
tea.NewProgram(NewLogin(m.Base)))
|
||||
case http.StatusBadRequest:
|
||||
*queue = append(*queue,
|
||||
tea.NewProgram(NewRedirect("Username already exist")))
|
||||
*queue = append(*queue,
|
||||
tea.NewProgram(NewRegister(m.Base)))
|
||||
case http.StatusInternalServerError:
|
||||
return err
|
||||
} else {
|
||||
switch resp.StatusCode() {
|
||||
case http.StatusBadRequest:
|
||||
*queue = append(*queue,
|
||||
tea.NewProgram(NewRedirect("Username already exist")))
|
||||
*queue = append(*queue,
|
||||
tea.NewProgram(NewRegister(m.Base)))
|
||||
default:
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
65
plays/roomWaiting.go
Normal file
65
plays/roomWaiting.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package plays
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"gitea.konchin.com/ytshih/inp2025/game/types"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
)
|
||||
|
||||
type RoomWaiting struct {
|
||||
*Base
|
||||
|
||||
doneCh chan struct{}
|
||||
}
|
||||
|
||||
func NewRoomWaiting(base *Base) *RoomWaiting {
|
||||
m := &RoomWaiting{
|
||||
base: base,
|
||||
|
||||
doneCh: make(chan struct{}),
|
||||
}
|
||||
return &m
|
||||
}
|
||||
|
||||
func updateRoomWaitingInfo(m *RoomWaiting) error {
|
||||
for {
|
||||
select {
|
||||
case <-m.doneCh:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m *RoomWaiting) Init() tea.Cmd {
|
||||
go updateRoomWaitingInfo(m)
|
||||
return tea.Sequence(tea.ClearScreen, Tick(refreshTick))
|
||||
}
|
||||
|
||||
func (m *RoomWaiting) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
if _, cmd := m.Base.Update(msg); cmd != nil {
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
switch msg := msg.(type) {
|
||||
case types.TickMsg:
|
||||
return m, Tick(refreshTick)
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (m *RoomWaiting) View() string {
|
||||
var b strings.Builder
|
||||
|
||||
b.WriteString("waiting for user to join ...")
|
||||
return b.String()
|
||||
}
|
||||
|
||||
func (m *RoomWaiting) Next(queue *[]*tea.Program) error {
|
||||
m.doneCh <- struct{}{}
|
||||
switch m.choice {
|
||||
case "":
|
||||
*queue = append(*queue,
|
||||
tea.NewProgram)
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package api
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"gitea.konchin.com/ytshih/inp2025/game/backend/middlewares"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/server/middlewares"
|
||||
"github.com/uptrace/bunrouter"
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"database/sql"
|
||||
"net/http"
|
||||
|
||||
"gitea.konchin.com/ytshih/inp2025/game/backend/middlewares"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/server/middlewares"
|
||||
"github.com/uptrace/bunrouter"
|
||||
)
|
||||
|
||||
@@ -3,8 +3,8 @@ package auth
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"gitea.konchin.com/ytshih/inp2025/game/backend/middlewares"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/models"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/server/middlewares"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/types"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/utils"
|
||||
"github.com/uptrace/bunrouter"
|
||||
@@ -3,8 +3,8 @@ package auth
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"gitea.konchin.com/ytshih/inp2025/game/backend/middlewares"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/models"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/server/middlewares"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/types"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/utils"
|
||||
"github.com/uptrace/bunrouter"
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"gitea.konchin.com/ytshih/inp2025/game/backend/middlewares"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/models"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/server/middlewares"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/types"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/utils"
|
||||
"github.com/uptrace/bunrouter"
|
||||
@@ -18,11 +18,6 @@ const docTemplate = `{
|
||||
"host": "{{.Host}}",
|
||||
"basePath": "{{.BasePath}}",
|
||||
"paths": {
|
||||
"/api/lobby/rooms": {
|
||||
"get": {
|
||||
"responses": {}
|
||||
}
|
||||
},
|
||||
"/api/lobby/users": {
|
||||
"get": {
|
||||
"responses": {}
|
||||
@@ -10,11 +10,6 @@
|
||||
},
|
||||
"basePath": "/",
|
||||
"paths": {
|
||||
"/api/lobby/rooms": {
|
||||
"get": {
|
||||
"responses": {}
|
||||
}
|
||||
},
|
||||
"/api/lobby/users": {
|
||||
"get": {
|
||||
"responses": {}
|
||||
@@ -14,9 +14,6 @@ info:
|
||||
title: Intro. to Network Programming Game
|
||||
version: 0.0.1-alpha
|
||||
paths:
|
||||
/api/lobby/rooms:
|
||||
get:
|
||||
responses: {}
|
||||
/api/lobby/users:
|
||||
get:
|
||||
responses: {}
|
||||
@@ -11,7 +11,7 @@ func (self *Handlers) AccessLog(
|
||||
next bunrouter.HandlerFunc,
|
||||
) bunrouter.HandlerFunc {
|
||||
return func(w http.ResponseWriter, req bunrouter.Request) error {
|
||||
tracing.Logger.Ctx(req.Context()).
|
||||
tracing.Logger.
|
||||
Info(req.Method + " " + req.Params().Route())
|
||||
return next(w, req)
|
||||
}
|
||||
@@ -35,7 +35,7 @@ func (self *Handlers) Auth(
|
||||
}
|
||||
|
||||
if dbUser.Password != password {
|
||||
tracing.Logger.Ctx(ctx).
|
||||
tracing.Logger.
|
||||
Debug("password input",
|
||||
zap.String("input.password", password),
|
||||
zap.String("dbuser.password", dbUser.Password))
|
||||
@@ -45,7 +45,7 @@ func (self *Handlers) ErrorHandler(
|
||||
httpErr = err
|
||||
|
||||
default:
|
||||
tracing.Logger.Ctx(ctx).
|
||||
tracing.Logger.
|
||||
Error("unhandled error",
|
||||
zap.Error(err))
|
||||
httpErr = NewHTTPError(err)
|
||||
@@ -60,20 +60,20 @@ func (self *Handlers) ErrorHandler(
|
||||
if 500 <= httpErr.StatusCode && httpErr.StatusCode <= 599 {
|
||||
span.SetStatus(codes.Error, err.Error())
|
||||
if httpErr.OriginError == nil {
|
||||
tracing.Logger.Ctx(ctx).
|
||||
tracing.Logger.
|
||||
Error(httpErr.Message)
|
||||
} else {
|
||||
tracing.Logger.Ctx(ctx).
|
||||
tracing.Logger.
|
||||
Error(httpErr.Message,
|
||||
zap.Error(httpErr.OriginError))
|
||||
}
|
||||
} else {
|
||||
span.SetStatus(codes.Ok, "")
|
||||
if httpErr.OriginError == nil {
|
||||
tracing.Logger.Ctx(ctx).
|
||||
tracing.Logger.
|
||||
Warn(httpErr.Message)
|
||||
} else {
|
||||
tracing.Logger.Ctx(ctx).
|
||||
tracing.Logger.
|
||||
Warn(httpErr.Message,
|
||||
zap.Error(httpErr.OriginError))
|
||||
}
|
||||
60
server/wordle/handlers.go
Normal file
60
server/wordle/handlers.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package wordle
|
||||
|
||||
import (
|
||||
"gitea.konchin.com/ytshih/inp2025/game/types"
|
||||
"github.com/gorilla/websocket"
|
||||
)
|
||||
|
||||
type OperationType int
|
||||
|
||||
const (
|
||||
OperationTypeGuess OperationType = iota
|
||||
)
|
||||
|
||||
type Operation struct {
|
||||
Type OperationType
|
||||
Username string
|
||||
Guess string
|
||||
}
|
||||
|
||||
type Handlers struct {
|
||||
state types.WordleState
|
||||
ans string
|
||||
upgrader websocket.Upgrader
|
||||
|
||||
opCh chan Operation
|
||||
subs []*chan types.WordleState
|
||||
}
|
||||
|
||||
func NewHandlers() *Handlers {
|
||||
ret := &Handlers{
|
||||
upgrader: websocket.Upgrader{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
},
|
||||
|
||||
subs: nil,
|
||||
}
|
||||
go ret.GameFlow()
|
||||
return ret
|
||||
}
|
||||
|
||||
func (self *Handlers) GameFlow() {
|
||||
for op := range self.opCh {
|
||||
switch op.Type {
|
||||
case OperationTypeGuess:
|
||||
self.state.CurrentGuess++
|
||||
if self.state.CurrentGuess >= len(self.state.Users) {
|
||||
for username, user := range self.state.Users {
|
||||
user.History = append(user.History,
|
||||
types.NewWord(op.Guess, self.ans))
|
||||
self.state.Users[username] = user
|
||||
}
|
||||
|
||||
for _, sub := range self.subs {
|
||||
*sub <- self.state
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
server/wordle/wsGetState.go
Normal file
44
server/wordle/wsGetState.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package wordle
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"gitea.konchin.com/ytshih/inp2025/game/server/middlewares"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/types"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/utils"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/uptrace/bunrouter"
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
)
|
||||
|
||||
func (self *Handlers) WSGetState(
|
||||
w http.ResponseWriter,
|
||||
req bunrouter.Request,
|
||||
) error {
|
||||
c, err := self.upgrader.Upgrade(w, req.Request, nil)
|
||||
if err != nil {
|
||||
return middlewares.HTTPError{
|
||||
StatusCode: http.StatusInternalServerError,
|
||||
Message: "failed to upgrade websocket",
|
||||
OriginError: err,
|
||||
}
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
dataCh := make(chan types.WordleState)
|
||||
self.subs = append(self.subs, &dataCh)
|
||||
|
||||
for data := range dataCh {
|
||||
b, err := msgpack.Marshal(data)
|
||||
if err != nil {
|
||||
return middlewares.HTTPError{
|
||||
StatusCode: http.StatusInternalServerError,
|
||||
Message: "failed to marshal data into msgpack",
|
||||
OriginError: err,
|
||||
}
|
||||
}
|
||||
c.WriteMessage(websocket.BinaryMessage, b)
|
||||
}
|
||||
|
||||
return utils.Success(w)
|
||||
}
|
||||
@@ -1,33 +1,42 @@
|
||||
package tracing
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"github.com/uptrace/opentelemetry-go-extra/otelzap"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/contrib/bridges/otelzap"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc"
|
||||
"go.opentelemetry.io/otel/sdk/log"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var (
|
||||
Tracer trace.Tracer
|
||||
Logger *otelzap.Logger
|
||||
Provider *log.LoggerProvider
|
||||
Tracer trace.Tracer
|
||||
Logger *zap.Logger
|
||||
|
||||
version string = "0.0.1-alpha"
|
||||
)
|
||||
|
||||
func InitTracer(appname string) {
|
||||
Tracer = otel.Tracer(appname)
|
||||
|
||||
var l *zap.Logger
|
||||
var err error
|
||||
if viper.GetBool("zap-production") {
|
||||
l, err = zap.NewProduction()
|
||||
} else {
|
||||
l, err = zap.NewDevelopment()
|
||||
}
|
||||
ctx := context.Background()
|
||||
exp, err := otlploggrpc.New(ctx,
|
||||
otlploggrpc.WithInsecure(),
|
||||
otlploggrpc.WithEndpoint(viper.GetString("otel-endpoint")))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
Logger = otelzap.New(l)
|
||||
Provider = log.NewLoggerProvider(
|
||||
log.WithProcessor(log.NewBatchProcessor(exp)))
|
||||
otelCore := otelzap.NewCore(appname,
|
||||
otelzap.WithLoggerProvider(Provider))
|
||||
|
||||
Logger = zap.New(otelCore, zap.AddCaller())
|
||||
}
|
||||
|
||||
func DeferTracer() {
|
||||
Logger.Sync()
|
||||
Provider.Shutdown(context.Background())
|
||||
}
|
||||
|
||||
27
types/game.go
Normal file
27
types/game.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package types
|
||||
|
||||
import "fmt"
|
||||
|
||||
type RoomStatus int
|
||||
|
||||
const (
|
||||
RoomStatusWaiting RoomStatus = iota
|
||||
RoomStatusPlaying
|
||||
RoomStatusEnded
|
||||
)
|
||||
|
||||
var (
|
||||
RoomStatusStr = []string{"Waiting", "Playing", "Ended"}
|
||||
)
|
||||
|
||||
type Room struct {
|
||||
Creater string
|
||||
Status RoomStatus
|
||||
}
|
||||
|
||||
func (self Room) View() string {
|
||||
return fmt.Sprintf("%10s [%s]",
|
||||
self.Creater,
|
||||
RoomStatusStr[self.Status],
|
||||
)
|
||||
}
|
||||
89
types/wordle.go
Normal file
89
types/wordle.go
Normal file
@@ -0,0 +1,89 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
)
|
||||
|
||||
type CharStatus int
|
||||
|
||||
const (
|
||||
CharStatusA CharStatus = iota
|
||||
CharStatusB
|
||||
CharStatusC
|
||||
)
|
||||
|
||||
type Char struct {
|
||||
Char rune `msgpack:"char"`
|
||||
Status CharStatus `msgpack:"status"`
|
||||
}
|
||||
|
||||
func NewChar() Char {
|
||||
return Char{
|
||||
Char: 0x0,
|
||||
Status: CharStatusC,
|
||||
}
|
||||
}
|
||||
|
||||
func (self Char) View() string {
|
||||
style := lipgloss.NewStyle()
|
||||
|
||||
switch self.Status {
|
||||
case CharStatusA:
|
||||
style = style.Background(lipgloss.Color("#00ff00"))
|
||||
case CharStatusB:
|
||||
style = style.Background(lipgloss.Color("#ffff00"))
|
||||
case CharStatusC:
|
||||
style = style.Background(lipgloss.Color("#808080"))
|
||||
}
|
||||
|
||||
return style.Render(string(self.Char))
|
||||
}
|
||||
|
||||
type Word struct {
|
||||
Chars []Char `msgpack:"chars"`
|
||||
}
|
||||
|
||||
func NewWord(word, ans string) Word {
|
||||
return Word{
|
||||
Chars: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (self Word) View() string {
|
||||
var b strings.Builder
|
||||
|
||||
for _, char := range self.Chars {
|
||||
b.WriteString(char.View())
|
||||
b.WriteRune('\n')
|
||||
}
|
||||
|
||||
return b.String()
|
||||
}
|
||||
|
||||
const (
|
||||
MaxLength = 5
|
||||
)
|
||||
|
||||
type UserState struct {
|
||||
History []Word `msgpack:"history"`
|
||||
Input string
|
||||
}
|
||||
|
||||
type WordleState struct {
|
||||
Users map[string]UserState `msgpack:"users"`
|
||||
CurrentGuess int
|
||||
}
|
||||
|
||||
func NewWordleState() WordleState {
|
||||
return WordleState{
|
||||
Users: nil,
|
||||
}
|
||||
}
|
||||
|
||||
func (self WordleState) View() string {
|
||||
var b strings.Builder
|
||||
|
||||
return b.String()
|
||||
}
|
||||
@@ -11,6 +11,5 @@ func InitDB(ctx context.Context, db *bun.DB) error {
|
||||
return db.ResetModel(ctx,
|
||||
(*models.User)(nil),
|
||||
(*models.UserStatus)(nil),
|
||||
(*models.Room)(nil),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ func ReadConfig(ctx context.Context) {
|
||||
viper.AddConfigPath(".")
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
|
||||
tracing.Logger.Ctx(ctx).
|
||||
tracing.Logger.
|
||||
Panic("failed to read config file",
|
||||
zap.Error(err))
|
||||
panic(err)
|
||||
|
||||
50
utils/udp.go
Normal file
50
utils/udp.go
Normal file
@@ -0,0 +1,50 @@
|
||||
package workflows
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
)
|
||||
|
||||
type UDPPayload struct {
|
||||
MagicNumber int `msgpack:"magicNumber"`
|
||||
Data string `msgpack:"data"`
|
||||
}
|
||||
|
||||
const (
|
||||
BUFFER_SIZE int = 1024
|
||||
MAGIC_NUMBER int = 114514
|
||||
)
|
||||
|
||||
func ListenUDP(port string) (string, error) {
|
||||
addr, err := net.ResolveUDPAddr("udp", ":"+port)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to resolve address, %w", err)
|
||||
}
|
||||
|
||||
conn, err := net.ListenUDP("udp", addr)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to listen on addr '%v', %w", addr, err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
for {
|
||||
buffer := make([]byte, BUFFER_SIZE)
|
||||
|
||||
n, clientAddr, err := conn.ReadFromUDP(buffer)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var payload UDPPayload
|
||||
err = msgpack.Unmarshal(buffer[:n], &payload)
|
||||
if err == nil && payload.MagicNumber == MAGIC_NUMBER {
|
||||
return payload.Data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func SendPayload(endpoint, data string) error {
|
||||
|
||||
}
|
||||
48
workflows/wordleServer.go
Normal file
48
workflows/wordleServer.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package workflows
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
|
||||
"gitea.konchin.com/ytshih/inp2025/game/implements"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/server/middlewares"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/server/wordle"
|
||||
"gitea.konchin.com/ytshih/inp2025/game/tracing"
|
||||
"github.com/uptrace/bunrouter"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type ShutdownFunc = func()
|
||||
|
||||
func WordleServer(addr string) ShutdownFunc {
|
||||
handlers := wordle.NewHandlers()
|
||||
middlewareHandlers := middlewares.NewHandlers(
|
||||
implements.NewBunDatabase(nil))
|
||||
|
||||
router := bunrouter.New()
|
||||
|
||||
apiGroup := router.NewGroup("/api").
|
||||
Use(middlewareHandlers.ErrorHandler)
|
||||
apiGroup.GET("/state",
|
||||
handlers.WSGetState)
|
||||
apiGroup.POST("/guess",
|
||||
handlers.WSPostGuess)
|
||||
|
||||
httpServer = &http.Server{
|
||||
Addr: addr,
|
||||
Handler: http.Handler(router),
|
||||
}
|
||||
if err := httpServer.ListenAndServe(); err != http.ErrServerClosed {
|
||||
tracing.Logger.Panic("failed to start http server",
|
||||
zap.Error(err))
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return func() {
|
||||
if err := httpServer.Shutdown(context.Background()); err != nil {
|
||||
tracing.Logger.Panic("failed to shutdown server",
|
||||
zap.Error(err))
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user