Обновил версию go. Добавил логику в сервис
This commit is contained in:
parent
ecc3dfa980
commit
9108da715d
29 changed files with 2023 additions and 536 deletions
|
@ -3,12 +3,13 @@ package main
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"git.urec56.ru/urec/chat_back_go/config"
|
||||
"git.urec56.ru/urec/chat_back_go/internal/database"
|
||||
"git.urec56.ru/urec/chat_back_go/internal/domain"
|
||||
|
@ -26,7 +27,7 @@ func main() {
|
|||
|
||||
db, rdb, mc, closeDBs, err := database.New(cfg, log)
|
||||
if err != nil {
|
||||
log.Fatalf("error occurred while database initialization: %s", err.Error())
|
||||
log.Fatalf("error occurred while database initialization: %s", err)
|
||||
}
|
||||
defer closeDBs()
|
||||
|
||||
|
@ -39,11 +40,11 @@ func main() {
|
|||
|
||||
go func() {
|
||||
if err = srv.Run(cfg.Srv.Port); !errors.Is(err, http.ErrServerClosed) {
|
||||
log.Fatalf("error occurred while running rest server: %s", err.Error())
|
||||
log.Fatalf("error occurred while running rest server: %s", err)
|
||||
}
|
||||
}()
|
||||
|
||||
log.Infof("starting server on port %s\n", cfg.Srv.Port)
|
||||
log.Infof("starting server on port %d\n", cfg.Srv.Port)
|
||||
|
||||
quit := make(chan os.Signal, 1)
|
||||
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
|
||||
|
@ -53,6 +54,6 @@ func main() {
|
|||
log.Info("shutting down the server")
|
||||
|
||||
if err = srv.Shutdown(context.Background()); err != nil {
|
||||
log.Fatalf("error occurred while shutting down rest server: %s", err.Error())
|
||||
log.Fatalf("error occurred while shutting down rest server: %s", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,9 +42,10 @@ type JWT struct {
|
|||
}
|
||||
|
||||
type Server struct {
|
||||
Port string `yaml:"port"`
|
||||
Port int `yaml:"port"`
|
||||
RequestIDHeader string `yaml:"request_id_header"`
|
||||
}
|
||||
|
||||
type Migrations struct {
|
||||
Folder string `yaml:"folder"`
|
||||
}
|
||||
|
|
58
go.mod
58
go.mod
|
@ -1,11 +1,11 @@
|
|||
module git.urec56.ru/urec/chat_back_go
|
||||
|
||||
go 1.22.6
|
||||
go 1.24.2
|
||||
|
||||
require (
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2
|
||||
github.com/go-playground/validator/v10 v10.24.0
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||
github.com/golang-migrate/migrate/v4 v4.18.2
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/ilyakaznacheev/cleanenv v1.5.0
|
||||
|
@ -22,35 +22,87 @@ require (
|
|||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.2.1 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/go-openapi/analysis v0.23.0 // indirect
|
||||
github.com/go-openapi/errors v0.22.0 // indirect
|
||||
github.com/go-openapi/inflect v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/loads v0.22.0 // indirect
|
||||
github.com/go-openapi/runtime v0.28.0 // indirect
|
||||
github.com/go-openapi/spec v0.21.0 // indirect
|
||||
github.com/go-openapi/strfmt v0.23.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/go-openapi/validate v0.24.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-swagger/go-swagger v0.31.0 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/gorilla/handlers v1.5.2 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/huandu/xstrings v1.4.0 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/jessevdk/go-flags v1.5.0 // indirect
|
||||
github.com/joho/godotenv v1.5.1 // indirect
|
||||
github.com/klauspost/compress v1.16.7 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/klauspost/compress v1.17.0 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/oklog/ulid v1.3.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/viper v1.18.2 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/toqueteos/webbrowser v1.2.0 // indirect
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||
github.com/xdg-go/scram v1.1.2 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||
go.mongodb.org/mongo-driver v1.14.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.32.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.32.0 // indirect
|
||||
go.uber.org/atomic v1.9.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
|
||||
golang.org/x/mod v0.21.0 // indirect
|
||||
golang.org/x/net v0.34.0 // indirect
|
||||
golang.org/x/sync v0.11.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect
|
||||
)
|
||||
|
||||
tool github.com/go-swagger/go-swagger/cmd/swagger
|
||||
|
|
127
go.sum
127
go.sum
|
@ -6,8 +6,17 @@ github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak
|
|||
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
|
||||
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
|
||||
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
|
||||
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
|
||||
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
|
||||
|
@ -33,12 +42,38 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
|
|||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/analysis v0.23.0 h1:aGday7OWupfMs+LbmLZG4k0MYXIANxcuBTYUC03zFCU=
|
||||
github.com/go-openapi/analysis v0.23.0/go.mod h1:9mz9ZWaSlV8TvjQHLl2mUW2PbZtemkE8yA5v22ohupo=
|
||||
github.com/go-openapi/errors v0.22.0 h1:c4xY/OLxUBSTiepAg3j/MHuAv5mJhnf53LLMWFB+u/w=
|
||||
github.com/go-openapi/errors v0.22.0/go.mod h1:J3DmZScxCDufmIMsdOuDHxJbdOGC0xtUynjIx092vXE=
|
||||
github.com/go-openapi/inflect v0.21.0 h1:FoBjBTQEcbg2cJUWX6uwL9OyIW8eqc9k4KhN4lfbeYk=
|
||||
github.com/go-openapi/inflect v0.21.0/go.mod h1:INezMuUu7SJQc2AyR3WO0DqqYUJSj8Kb4hBd7WtjlAw=
|
||||
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
||||
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
|
||||
github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ=
|
||||
github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4=
|
||||
github.com/go-openapi/loads v0.22.0 h1:ECPGd4jX1U6NApCGG1We+uEozOAvXvJSF4nnwHZ8Aco=
|
||||
github.com/go-openapi/loads v0.22.0/go.mod h1:yLsaTCS92mnSAZX5WWoxszLj0u+Ojl+Zs5Stn1oF+rs=
|
||||
github.com/go-openapi/runtime v0.28.0 h1:gpPPmWSNGo214l6n8hzdXYhPuJcGtziTOgUpvsFWGIQ=
|
||||
github.com/go-openapi/runtime v0.28.0/go.mod h1:QN7OzcS+XuYmkQLw05akXk0jRH/eZ3kb18+1KwW9gyc=
|
||||
github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY=
|
||||
github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk=
|
||||
github.com/go-openapi/strfmt v0.23.0 h1:nlUS6BCqcnAk0pyhi9Y+kdDVZdZMHfEKQiS4HaMgO/c=
|
||||
github.com/go-openapi/strfmt v0.23.0/go.mod h1:NrtIpfKtWIygRkKVsxh7XQMDQW5HKQl6S5ik2elW+K4=
|
||||
github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE=
|
||||
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
|
||||
github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
|
||||
github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
|
||||
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=
|
||||
|
@ -49,25 +84,38 @@ github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE
|
|||
github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/go-swagger/go-swagger v0.31.0 h1:H8eOYQnY2u7vNKWDNykv2xJP3pBhRG/R+SOCAmKrLlc=
|
||||
github.com/go-swagger/go-swagger v0.31.0/go.mod h1:WSigRRWEig8zV6t6Sm8Y+EmUjlzA/HoaZJ5edupq7po=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-migrate/migrate/v4 v4.18.2 h1:2VSCMz7x7mjyTXx3m2zPokOY82LTRgxK1yQYKo6wWQ8=
|
||||
github.com/golang-migrate/migrate/v4 v4.18.2/go.mod h1:2CM6tJvn2kqPXwnXO/d3rAQYiyoIm180VsO8PRX6Rpk=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
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/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
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/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
|
||||
github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
|
||||
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/ilyakaznacheev/cleanenv v1.5.0 h1:0VNZXggJE2OYdXE87bfSSwGxeiGt9moSR2lOrsHHvr4=
|
||||
github.com/ilyakaznacheev/cleanenv v1.5.0/go.mod h1:a5aDzaJrLCQZsazHol1w8InnDcOX0OColm64SlIi6gk=
|
||||
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
|
||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
||||
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-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
|
@ -76,13 +124,17 @@ github.com/jackc/pgx/v5 v5.7.2 h1:mLoDLV6sonKlvjIEsV56SkWNCnuNv531l94GaIzO+XI=
|
|||
github.com/jackc/pgx/v5 v5.7.2/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LFvc=
|
||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
|
||||
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/kisielk/sqlstruct v0.0.0-20201105191214-5f3e10d3ab46/go.mod h1:yyMNCyc/Ib3bDTKd379tNMpB/7/H5TjM2Y9QJ5THLbE=
|
||||
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
|
||||
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
|
||||
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
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=
|
||||
|
@ -91,18 +143,34 @@ 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/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
||||
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
|
||||
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
|
@ -114,13 +182,42 @@ github.com/redis/go-redis/v9 v9.7.1/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93Ge
|
|||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
|
||||
github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
|
||||
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
|
||||
github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
|
||||
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/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
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.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ=
|
||||
github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM=
|
||||
github.com/urec56/pathparams v0.0.6 h1:OuCbamKVdfVtprL+arL5QUuy84R909haBHLburAAp1c=
|
||||
github.com/urec56/pathparams v0.0.6/go.mod h1:EymabShlKrvvNckqTZ6zVki6wEYTQmcg41nxFtd7G8Y=
|
||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
|
||||
|
@ -132,6 +229,8 @@ github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gi
|
|||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80=
|
||||
go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c=
|
||||
go.mongodb.org/mongo-driver/v2 v2.1.0 h1:/ELnVNjmfUKDsoBisXxuJL0noR9CfeUIrP7Yt3R+egg=
|
||||
go.mongodb.org/mongo-driver/v2 v2.1.0/go.mod h1:AWiLRShSrk5RHQS3AEn3RL19rqOzVq49MCpWQ3x/huI=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk=
|
||||
|
@ -146,14 +245,22 @@ go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
|||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
|
||||
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
|
||||
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -162,27 +269,39 @@ golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
|||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
|
||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
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/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
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=
|
||||
|
|
51
internal/domain/date.go
Normal file
51
internal/domain/date.go
Normal file
|
@ -0,0 +1,51 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CustomDate struct {
|
||||
time.Time
|
||||
}
|
||||
|
||||
func (ct *CustomDate) UnmarshalJSON(data []byte) error {
|
||||
str := string(data[1 : len(data)-1])
|
||||
|
||||
t, err := time.Parse(time.DateOnly, str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ct.Time = t
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ct CustomDate) MarshalJSON() ([]byte, error) {
|
||||
return []byte(fmt.Sprintf("\"%s\"", ct.Format(time.DateOnly))), nil
|
||||
}
|
||||
|
||||
func (ct CustomDate) String() string {
|
||||
return ct.Format(time.DateOnly)
|
||||
}
|
||||
|
||||
func (ct *CustomDate) Scan(value any) error {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
t, err := time.Parse(time.DateOnly, v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*ct = CustomDate{Time: t}
|
||||
case time.Time:
|
||||
*ct = CustomDate{Time: v}
|
||||
default:
|
||||
panic("incorrect time type received")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ct CustomDate) Value() (driver.Value, error) {
|
||||
return ct.Time.Format(time.DateOnly), nil
|
||||
}
|
190
internal/domain/date_test.go
Normal file
190
internal/domain/date_test.go
Normal file
|
@ -0,0 +1,190 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestCustomDate_UnmarshalJSON(t *testing.T) {
|
||||
testTable := []struct {
|
||||
name string
|
||||
input string
|
||||
expectErr bool
|
||||
expected time.Time
|
||||
}{
|
||||
{
|
||||
name: "ok",
|
||||
input: `"2024-02-25"`,
|
||||
expected: time.Date(2024, 2, 25, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
{
|
||||
name: "invalid_format",
|
||||
input: `"25-02-2024"`,
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid_characters",
|
||||
input: `"invalid-date"`,
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "empty_string",
|
||||
input: `""`,
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "whitespace",
|
||||
input: `" "`,
|
||||
expectErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testTable {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var cd CustomDate
|
||||
err := json.Unmarshal([]byte(tc.input), &cd)
|
||||
|
||||
assert.Equal(t, tc.expectErr, err != nil)
|
||||
assert.True(t, cd.Time.Equal(tc.expected) || tc.expectErr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomDate_MarshalJSON(t *testing.T) {
|
||||
testTable := []struct {
|
||||
name string
|
||||
date CustomDate
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "ok_1",
|
||||
date: CustomDate{Time: time.Date(2024, 2, 25, 0, 0, 0, 0, time.UTC)},
|
||||
expected: `"2024-02-25"`,
|
||||
},
|
||||
{
|
||||
name: "ok_2",
|
||||
date: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
|
||||
expected: `"2023-08-10"`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testTable {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result, err := json.Marshal(tc.date)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.expected, string(result))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomDate_String(t *testing.T) {
|
||||
testTable := []struct {
|
||||
name string
|
||||
date CustomDate
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "ok_1",
|
||||
date: CustomDate{Time: time.Date(2024, 2, 25, 0, 0, 0, 0, time.UTC)},
|
||||
expected: "2024-02-25",
|
||||
},
|
||||
{
|
||||
name: "ok_2",
|
||||
date: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
|
||||
expected: "2023-08-10",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testTable {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := tc.date.String()
|
||||
|
||||
assert.Equal(t, tc.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomDate_Scan(t *testing.T) {
|
||||
testTable := []struct {
|
||||
name string
|
||||
dbValue any
|
||||
expected CustomDate
|
||||
expectedErr error
|
||||
panics bool
|
||||
}{
|
||||
{
|
||||
name: "ok_1",
|
||||
dbValue: "2023-08-10",
|
||||
expected: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
|
||||
},
|
||||
{
|
||||
name: "ok_2",
|
||||
dbValue: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC),
|
||||
expected: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
|
||||
},
|
||||
{
|
||||
name: "invalid_date",
|
||||
dbValue: "",
|
||||
expectedErr: &time.ParseError{},
|
||||
},
|
||||
{
|
||||
name: "invalid_type",
|
||||
panics: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testTable {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if tc.panics {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
assert.Equal(t, "incorrect time type received", r)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
date := &CustomDate{}
|
||||
|
||||
err := date.Scan(tc.dbValue)
|
||||
|
||||
if tc.expectedErr != nil {
|
||||
assert.ErrorAs(t, err, &tc.expectedErr)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
assert.Equal(t, tc.expected, *date)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomDate_Value(t *testing.T) {
|
||||
testTable := []struct {
|
||||
name string
|
||||
date CustomDate
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "ok_1",
|
||||
date: CustomDate{Time: time.Date(2024, 2, 25, 0, 0, 0, 0, time.UTC)},
|
||||
expected: "2024-02-25",
|
||||
},
|
||||
{
|
||||
name: "ok_2",
|
||||
date: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
|
||||
expected: "2023-08-10",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testTable {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result, err := tc.date.Value()
|
||||
assert.NoError(t, err)
|
||||
|
||||
date, ok := result.(string)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, tc.expected, date)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -4,7 +4,7 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
type MessageRaw struct {
|
||||
type RawMessage struct {
|
||||
ID UUID `bson:"id"`
|
||||
Message string `bson:"message,omitempty"`
|
||||
ImageUrl string `bson:"image_url,omitempty"`
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -29,7 +26,7 @@ func (u *User) UnmarshalBinary(b []byte) error {
|
|||
return json.Unmarshal(b, u)
|
||||
}
|
||||
|
||||
func (u User) MarshalBinary() ([]byte, error) {
|
||||
func (u *User) MarshalBinary() ([]byte, error) {
|
||||
return json.Marshal(u)
|
||||
}
|
||||
|
||||
|
@ -49,47 +46,3 @@ type UserRegister struct {
|
|||
Password2 string `json:"password2" validate:"eqfield=Password"`
|
||||
DateOfBirth CustomDate `json:"date_of_birth" validate:"date_of_birth"`
|
||||
}
|
||||
|
||||
type CustomDate struct {
|
||||
time.Time
|
||||
}
|
||||
|
||||
func (ct *CustomDate) UnmarshalJSON(data []byte) error {
|
||||
str := string(data[1 : len(data)-1])
|
||||
|
||||
t, err := time.Parse(time.DateOnly, str)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ct.Time = t
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ct CustomDate) MarshalJSON() ([]byte, error) {
|
||||
return []byte(fmt.Sprintf("\"%s\"", ct.Format(time.DateOnly))), nil
|
||||
}
|
||||
|
||||
func (ct CustomDate) String() string {
|
||||
return ct.Format(time.DateOnly)
|
||||
}
|
||||
|
||||
func (ct *CustomDate) Scan(value any) error {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
t, err := time.Parse(time.DateOnly, v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*ct = CustomDate{Time: t}
|
||||
case time.Time:
|
||||
*ct = CustomDate{Time: v}
|
||||
default:
|
||||
panic("incorrect time type received")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ct CustomDate) Value() (driver.Value, error) {
|
||||
return ct.Time.Format(time.DateOnly), nil
|
||||
}
|
||||
|
|
|
@ -173,185 +173,3 @@ func TestUser_UnmarshalBinary(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomDate_UnmarshalJSON(t *testing.T) {
|
||||
testTable := []struct {
|
||||
name string
|
||||
input string
|
||||
expectErr bool
|
||||
expected time.Time
|
||||
}{
|
||||
{
|
||||
name: "ok",
|
||||
input: `"2024-02-25"`,
|
||||
expected: time.Date(2024, 2, 25, 0, 0, 0, 0, time.UTC),
|
||||
},
|
||||
{
|
||||
name: "invalid_format",
|
||||
input: `"25-02-2024"`,
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid_characters",
|
||||
input: `"invalid-date"`,
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "empty_string",
|
||||
input: `""`,
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "whitespace",
|
||||
input: `" "`,
|
||||
expectErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testTable {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var cd CustomDate
|
||||
err := json.Unmarshal([]byte(tc.input), &cd)
|
||||
|
||||
assert.Equal(t, tc.expectErr, err != nil)
|
||||
assert.True(t, cd.Time.Equal(tc.expected) || tc.expectErr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomDate_MarshalJSON(t *testing.T) {
|
||||
testTable := []struct {
|
||||
name string
|
||||
date CustomDate
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "ok_1",
|
||||
date: CustomDate{Time: time.Date(2024, 2, 25, 0, 0, 0, 0, time.UTC)},
|
||||
expected: `"2024-02-25"`,
|
||||
},
|
||||
{
|
||||
name: "ok_2",
|
||||
date: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
|
||||
expected: `"2023-08-10"`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testTable {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result, err := json.Marshal(tc.date)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, tc.expected, string(result))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomDate_String(t *testing.T) {
|
||||
testTable := []struct {
|
||||
name string
|
||||
date CustomDate
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "ok_1",
|
||||
date: CustomDate{Time: time.Date(2024, 2, 25, 0, 0, 0, 0, time.UTC)},
|
||||
expected: "2024-02-25",
|
||||
},
|
||||
{
|
||||
name: "ok_2",
|
||||
date: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
|
||||
expected: "2023-08-10",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testTable {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := tc.date.String()
|
||||
|
||||
assert.Equal(t, tc.expected, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomDate_Scan(t *testing.T) {
|
||||
testTable := []struct {
|
||||
name string
|
||||
dbValue any
|
||||
expected CustomDate
|
||||
expectedErr error
|
||||
panics bool
|
||||
}{
|
||||
{
|
||||
name: "ok_1",
|
||||
dbValue: "2023-08-10",
|
||||
expected: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
|
||||
},
|
||||
{
|
||||
name: "ok_2",
|
||||
dbValue: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC),
|
||||
expected: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
|
||||
},
|
||||
{
|
||||
name: "invalid_date",
|
||||
dbValue: "",
|
||||
expectedErr: &time.ParseError{},
|
||||
},
|
||||
{
|
||||
name: "invalid_type",
|
||||
panics: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testTable {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
if tc.panics {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
assert.Equal(t, "incorrect time type received", r)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
date := &CustomDate{}
|
||||
|
||||
err := date.Scan(tc.dbValue)
|
||||
|
||||
if tc.expectedErr != nil {
|
||||
assert.ErrorAs(t, err, &tc.expectedErr)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
assert.Equal(t, tc.expected, *date)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCustomDate_Value(t *testing.T) {
|
||||
testTable := []struct {
|
||||
name string
|
||||
date CustomDate
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "ok_1",
|
||||
date: CustomDate{Time: time.Date(2024, 2, 25, 0, 0, 0, 0, time.UTC)},
|
||||
expected: "2024-02-25",
|
||||
},
|
||||
{
|
||||
name: "ok_2",
|
||||
date: CustomDate{Time: time.Date(2023, 8, 10, 0, 0, 0, 0, time.UTC)},
|
||||
expected: "2023-08-10",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testTable {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result, err := tc.date.Value()
|
||||
assert.NoError(t, err)
|
||||
|
||||
date, ok := result.(string)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, tc.expected, date)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,15 +5,13 @@ import (
|
|||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
)
|
||||
|
||||
type UUID struct {
|
||||
uuid.NullUUID
|
||||
}
|
||||
type UUID uuid.NullUUID
|
||||
|
||||
func (u UUID) IsZero() bool {
|
||||
func (u *UUID) IsZero() bool {
|
||||
return !u.Valid
|
||||
}
|
||||
|
||||
func (u UUID) MarshalBSONValue() (byte, []byte, error) {
|
||||
func (u *UUID) MarshalBSONValue() (byte, []byte, error) {
|
||||
if !u.Valid {
|
||||
return byte(bson.TypeString), nil, nil
|
||||
}
|
||||
|
@ -46,7 +44,7 @@ func (u *UUID) UnmarshalBSONValue(_ byte, data []byte) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (u UUID) String() string {
|
||||
func (u *UUID) String() string {
|
||||
if !u.Valid {
|
||||
return "<nil>"
|
||||
}
|
||||
|
@ -54,8 +52,19 @@ func (u UUID) String() string {
|
|||
}
|
||||
|
||||
func GenerateUUID() UUID {
|
||||
return UUID{NullUUID: uuid.NullUUID{
|
||||
return UUID(
|
||||
uuid.NullUUID{
|
||||
UUID: uuid.New(),
|
||||
Valid: true,
|
||||
}}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func GenerateTestUUID() UUID {
|
||||
return UUID(
|
||||
uuid.NullUUID{
|
||||
UUID: uuid.MustParse("5c94e2c5-7615-4fdc-a2e2-00f71ae1e380"),
|
||||
Valid: true,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.mongodb.org/mongo-driver/v2/bson"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestUUID_IsZero(t *testing.T) {
|
||||
|
@ -19,7 +20,7 @@ func TestUUID_IsZero(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "non_zero",
|
||||
uuid: UUID{NullUUID: uuid.NullUUID{Valid: true}},
|
||||
uuid: UUID(uuid.NullUUID{Valid: true}),
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
|
@ -44,10 +45,12 @@ func TestUUID_MarshalBSONValue(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "non_zero",
|
||||
uuid: UUID{NullUUID: uuid.NullUUID{
|
||||
uuid: UUID(
|
||||
uuid.NullUUID{
|
||||
UUID: [16]byte{183, 27, 35, 52, 27, 195, 79, 180, 160, 72, 9, 103, 64, 182, 247, 131},
|
||||
Valid: true,
|
||||
}},
|
||||
},
|
||||
),
|
||||
expectedUuid: []byte{37, 0, 0, 0, 98, 55, 49, 98, 50, 51, 51, 52, 45, 49, 98, 99, 51, 45, 52, 102, 98, 52, 45, 97, 48, 52, 56, 45, 48, 57, 54, 55, 52, 48, 98, 54, 102, 55, 56, 51, 0},
|
||||
},
|
||||
}
|
||||
|
@ -76,10 +79,12 @@ func TestUUID_UnmarshalBSONValue(t *testing.T) {
|
|||
{
|
||||
name: "valid_not_zero",
|
||||
data: []byte{37, 0, 0, 0, 98, 55, 49, 98, 50, 51, 51, 52, 45, 49, 98, 99, 51, 45, 52, 102, 98, 52, 45, 97, 48, 52, 56, 45, 48, 57, 54, 55, 52, 48, 98, 54, 102, 55, 56, 51, 0},
|
||||
expectedUuid: UUID{NullUUID: uuid.NullUUID{
|
||||
expectedUuid: UUID(
|
||||
uuid.NullUUID{
|
||||
UUID: [16]byte{183, 27, 35, 52, 27, 195, 79, 180, 160, 72, 9, 103, 64, 182, 247, 131},
|
||||
Valid: true,
|
||||
}},
|
||||
},
|
||||
),
|
||||
},
|
||||
{
|
||||
name: "parsing_error",
|
||||
|
@ -111,10 +116,12 @@ func TestUUID_String(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "non_zero",
|
||||
uuid: UUID{NullUUID: uuid.NullUUID{
|
||||
uuid: UUID(
|
||||
uuid.NullUUID{
|
||||
UUID: [16]byte{183, 27, 35, 52, 27, 195, 79, 180, 160, 72, 9, 103, 64, 182, 247, 131},
|
||||
Valid: true,
|
||||
}},
|
||||
},
|
||||
),
|
||||
expectedUuid: "b71b2334-1bc3-4fb4-a048-096740b6f783",
|
||||
},
|
||||
}
|
||||
|
@ -131,3 +138,12 @@ func TestUUID_String(t *testing.T) {
|
|||
func Test_GenerateUUID(t *testing.T) {
|
||||
_ = GenerateUUID()
|
||||
}
|
||||
|
||||
func Test_GenerateTestUUID(t *testing.T) {
|
||||
uid1 := GenerateTestUUID()
|
||||
uid2 := GenerateTestUUID()
|
||||
uid3 := GenerateTestUUID()
|
||||
|
||||
assert.Equal(t, uid1, uid2)
|
||||
assert.Equal(t, uid1, uid3)
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ func NewLogger(cfg config.Config) *Logger {
|
|||
logger.SetOutput(io.Discard)
|
||||
logger.SetLevel(log.PanicLevel)
|
||||
default:
|
||||
logger.Fatal("incorrect MODE was specified")
|
||||
logger.Fatalf("incorrect MODE was specified: %s", cfg.Mode)
|
||||
}
|
||||
|
||||
logger.Infof("logger initialized")
|
||||
|
|
|
@ -48,82 +48,91 @@ type UnpinMessage struct {
|
|||
}
|
||||
|
||||
type GetSome struct {
|
||||
ChatID, MessageNumberFrom, MessagesToGet int
|
||||
ChatID, Offset, Limit int
|
||||
}
|
||||
|
||||
func newMessageRepo(db *sqlx.DB, mdb *mongo.Database, l *logger.Logger) *messageRepository {
|
||||
return &messageRepository{db: db, mc: mdb.Collection("message"), l: l}
|
||||
}
|
||||
|
||||
func (r *messageRepository) Get(ID domain.UUID) (domain.MessageRaw, error) {
|
||||
var msg domain.MessageRaw
|
||||
func (r *messageRepository) Get(ID domain.UUID) (domain.RawMessage, error) {
|
||||
var msg domain.RawMessage
|
||||
res := r.mc.FindOne(nil, bson.M{"id": ID})
|
||||
|
||||
if err := res.Decode(&msg); err != nil {
|
||||
r.l.Errorf("getting message: %s", err.Error())
|
||||
return domain.MessageRaw{}, domain.InternalServerError
|
||||
r.l.Errorf("getting message: %s", err)
|
||||
return domain.RawMessage{}, domain.InternalServerError
|
||||
}
|
||||
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
func (r *messageRepository) GetByIDs(IDs []domain.UUID) ([]domain.MessageRaw, error) {
|
||||
var messages []domain.MessageRaw
|
||||
func (r *messageRepository) GetByIDs(IDs []domain.UUID) ([]domain.RawMessage, error) {
|
||||
var messages []domain.RawMessage
|
||||
res, err := r.mc.Find(nil, bson.M{"visibility": true, "id": bson.M{"$in": IDs}})
|
||||
if err != nil {
|
||||
r.l.Errorf("getting messages by ids: %s", err.Error())
|
||||
r.l.Errorf("getting messages by ids: %s", err)
|
||||
return nil, domain.InternalServerError
|
||||
}
|
||||
|
||||
if err = res.All(nil, &messages); err != nil {
|
||||
r.l.Errorf("decoding messages by ids: %s", err.Error())
|
||||
r.l.Errorf("decoding messages by ids: %s", err)
|
||||
return nil, domain.InternalServerError
|
||||
}
|
||||
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
func (r *messageRepository) GetSome(messagesInfo GetSome) ([]domain.MessageRaw, error) {
|
||||
var messages []domain.MessageRaw
|
||||
findOptions := options.Find().SetSort(bson.M{"created_at": -1}).SetLimit(int64(messagesInfo.MessagesToGet)).SetSkip(int64(messagesInfo.MessageNumberFrom))
|
||||
func (r *messageRepository) GetSome(messagesInfo GetSome) ([]domain.RawMessage, error) {
|
||||
var messages []domain.RawMessage
|
||||
findOptions := options.Find().SetSort(bson.M{"created_at": -1}).SetLimit(int64(messagesInfo.Limit)).SetSkip(int64(messagesInfo.Offset))
|
||||
res, err := r.mc.Find(nil, bson.M{"visibility": true, "chat_id": messagesInfo.ChatID}, findOptions)
|
||||
if err != nil {
|
||||
r.l.Errorf("getting some messages: %s", err.Error())
|
||||
r.l.Errorf("getting some messages: %s", err)
|
||||
return nil, domain.InternalServerError
|
||||
}
|
||||
|
||||
if err = res.All(nil, &messages); err != nil {
|
||||
r.l.Errorf("decoding some messages: %s", err.Error())
|
||||
r.l.Errorf("decoding some messages: %s", err)
|
||||
return nil, domain.InternalServerError
|
||||
}
|
||||
|
||||
return messages, nil
|
||||
}
|
||||
|
||||
func (r *messageRepository) Send(message SendMessage) (domain.UUID, error) {
|
||||
func (r *messageRepository) Send(message SendMessage) (domain.RawMessage, error) {
|
||||
message.ID = domain.GenerateUUID()
|
||||
message.CreatedAt = time.Now()
|
||||
message.Visibility = true
|
||||
|
||||
_, err := r.mc.InsertOne(nil, message)
|
||||
if err != nil {
|
||||
r.l.Errorf("inserting message: %s", err.Error())
|
||||
return domain.UUID{}, domain.InternalServerError
|
||||
r.l.Errorf("inserting message: %s", err)
|
||||
return domain.RawMessage{}, domain.InternalServerError
|
||||
}
|
||||
|
||||
return message.ID, nil
|
||||
return domain.RawMessage{
|
||||
ID: message.ID,
|
||||
Message: message.Message,
|
||||
ImageUrl: message.ImageUrl,
|
||||
ChatID: message.ChatID,
|
||||
UserID: message.UserID,
|
||||
CreatedAt: message.CreatedAt,
|
||||
AnswerID: message.AnswerID,
|
||||
AnswerMessage: message.AnswerMessage,
|
||||
AnswerImageUrl: message.AnswerImageUrl,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (r *messageRepository) Delete(ID domain.UUID) error {
|
||||
|
||||
if _, err := r.mc.UpdateOne(nil, bson.M{"id": ID}, bson.M{"$set": bson.M{"visibility": false}}); err != nil {
|
||||
r.l.Errorf("deleting message: %s", err.Error())
|
||||
r.l.Errorf("deleting message: %s", err)
|
||||
return domain.InternalServerError
|
||||
}
|
||||
|
||||
_, err := r.mc.UpdateMany(nil, bson.M{"answer_id": ID}, bson.M{"$set": bson.M{"answer_message": nil, "answer_image_url": nil}})
|
||||
if err != nil {
|
||||
r.l.Errorf("deleting message: %s", err.Error())
|
||||
r.l.Errorf("deleting message: %s", err)
|
||||
return domain.InternalServerError
|
||||
}
|
||||
|
||||
|
@ -132,13 +141,13 @@ func (r *messageRepository) Delete(ID domain.UUID) error {
|
|||
func (r *messageRepository) Edit(newMessage EditMessage) error {
|
||||
_, err := r.mc.UpdateOne(nil, bson.M{"id": newMessage.ID}, bson.M{"$set": bson.M{"message": newMessage.Message, "image_url": newMessage.ImageUrl}})
|
||||
if err != nil {
|
||||
r.l.Errorf("edditing message: %s", err.Error())
|
||||
r.l.Errorf("edditing message: %s", err)
|
||||
return domain.InternalServerError
|
||||
}
|
||||
|
||||
_, err = r.mc.UpdateMany(nil, bson.M{"answer_id": newMessage.ID}, bson.M{"$set": bson.M{"answer_message": newMessage.Message, "answer_image_url": newMessage.ImageUrl}})
|
||||
if err != nil {
|
||||
r.l.Errorf("edditing message: %s", err.Error())
|
||||
r.l.Errorf("edditing message: %s", err)
|
||||
return domain.InternalServerError
|
||||
}
|
||||
|
||||
|
@ -152,7 +161,7 @@ func (r *messageRepository) Pin(msg PinMessage) error {
|
|||
return domain.MessageAlreadyPinnedError
|
||||
}
|
||||
|
||||
r.l.Errorf("pining message: %s", err.Error())
|
||||
r.l.Errorf("pining message: %s", err)
|
||||
return domain.InternalServerError
|
||||
}
|
||||
|
||||
|
@ -162,7 +171,7 @@ func (r *messageRepository) Pin(msg PinMessage) error {
|
|||
func (r *messageRepository) Unpin(msg UnpinMessage) error {
|
||||
query := `DELETE FROM pinned_message WHERE chat_id = $1 AND message_id = $2`
|
||||
if _, err := r.db.Exec(query, msg.ChatID, msg.MessageID); err != nil {
|
||||
r.l.Errorf("unpining message: %s", err.Error())
|
||||
r.l.Errorf("unpining message: %s", err)
|
||||
return domain.InternalServerError
|
||||
}
|
||||
|
||||
|
@ -173,7 +182,7 @@ func (r *messageRepository) GetPinnedIDs(chatID int) ([]domain.UUID, error) {
|
|||
var IDs []domain.UUID
|
||||
query := `SELECT message_id FROM pinned_message WHERE chat_id = $1`
|
||||
if err := r.db.Select(&IDs, query, chatID); err != nil {
|
||||
r.l.Errorf("getting pinned ids: %s", err.Error())
|
||||
r.l.Errorf("getting pinned ids: %s", err)
|
||||
return []domain.UUID{}, domain.InternalServerError
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ import (
|
|||
type MockUser struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockUserMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockUserMockRecorder is the mock recorder for MockUser.
|
||||
|
@ -106,7 +105,6 @@ func (mr *MockUserMockRecorder) Register(email, hashedPassword, username, dateOf
|
|||
type MockChat struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockChatMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockChatMockRecorder is the mock recorder for MockChat.
|
||||
|
@ -130,7 +128,6 @@ func (m *MockChat) EXPECT() *MockChatMockRecorder {
|
|||
type MockMessage struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockMessageMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockMessageMockRecorder is the mock recorder for MockMessage.
|
||||
|
@ -179,10 +176,10 @@ func (mr *MockMessageMockRecorder) Edit(newMessage any) *gomock.Call {
|
|||
}
|
||||
|
||||
// Get mocks base method.
|
||||
func (m *MockMessage) Get(ID domain.UUID) (domain.MessageRaw, error) {
|
||||
func (m *MockMessage) Get(ID domain.UUID) (domain.RawMessage, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Get", ID)
|
||||
ret0, _ := ret[0].(domain.MessageRaw)
|
||||
ret0, _ := ret[0].(domain.RawMessage)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
@ -194,10 +191,10 @@ func (mr *MockMessageMockRecorder) Get(ID any) *gomock.Call {
|
|||
}
|
||||
|
||||
// GetByIDs mocks base method.
|
||||
func (m *MockMessage) GetByIDs(IDs []domain.UUID) ([]domain.MessageRaw, error) {
|
||||
func (m *MockMessage) GetByIDs(IDs []domain.UUID) ([]domain.RawMessage, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetByIDs", IDs)
|
||||
ret0, _ := ret[0].([]domain.MessageRaw)
|
||||
ret0, _ := ret[0].([]domain.RawMessage)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
@ -224,10 +221,10 @@ func (mr *MockMessageMockRecorder) GetPinnedIDs(chatID any) *gomock.Call {
|
|||
}
|
||||
|
||||
// GetSome mocks base method.
|
||||
func (m *MockMessage) GetSome(messagesInfo repository.GetSome) ([]domain.MessageRaw, error) {
|
||||
func (m *MockMessage) GetSome(messagesInfo repository.GetSome) ([]domain.RawMessage, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetSome", messagesInfo)
|
||||
ret0, _ := ret[0].([]domain.MessageRaw)
|
||||
ret0, _ := ret[0].([]domain.RawMessage)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
@ -253,10 +250,10 @@ func (mr *MockMessageMockRecorder) Pin(msg any) *gomock.Call {
|
|||
}
|
||||
|
||||
// Send mocks base method.
|
||||
func (m *MockMessage) Send(message repository.SendMessage) (domain.UUID, error) {
|
||||
func (m *MockMessage) Send(message repository.SendMessage) (domain.RawMessage, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Send", message)
|
||||
ret0, _ := ret[0].(domain.UUID)
|
||||
ret0, _ := ret[0].(domain.RawMessage)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
@ -285,7 +282,6 @@ func (mr *MockMessageMockRecorder) Unpin(msg any) *gomock.Call {
|
|||
type MockRepo struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockRepoMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockRepoMockRecorder is the mock recorder for MockRepo.
|
||||
|
@ -349,10 +345,10 @@ func (mr *MockRepoMockRecorder) FindOne(username, email any) *gomock.Call {
|
|||
}
|
||||
|
||||
// Get mocks base method.
|
||||
func (m *MockRepo) Get(ID domain.UUID) (domain.MessageRaw, error) {
|
||||
func (m *MockRepo) Get(ID domain.UUID) (domain.RawMessage, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Get", ID)
|
||||
ret0, _ := ret[0].(domain.MessageRaw)
|
||||
ret0, _ := ret[0].(domain.RawMessage)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
@ -394,10 +390,10 @@ func (mr *MockRepoMockRecorder) GetByID(userID any) *gomock.Call {
|
|||
}
|
||||
|
||||
// GetByIDs mocks base method.
|
||||
func (m *MockRepo) GetByIDs(IDs []domain.UUID) ([]domain.MessageRaw, error) {
|
||||
func (m *MockRepo) GetByIDs(IDs []domain.UUID) ([]domain.RawMessage, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetByIDs", IDs)
|
||||
ret0, _ := ret[0].([]domain.MessageRaw)
|
||||
ret0, _ := ret[0].([]domain.RawMessage)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
@ -424,10 +420,10 @@ func (mr *MockRepoMockRecorder) GetPinnedIDs(chatID any) *gomock.Call {
|
|||
}
|
||||
|
||||
// GetSome mocks base method.
|
||||
func (m *MockRepo) GetSome(messagesInfo repository.GetSome) ([]domain.MessageRaw, error) {
|
||||
func (m *MockRepo) GetSome(messagesInfo repository.GetSome) ([]domain.RawMessage, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetSome", messagesInfo)
|
||||
ret0, _ := ret[0].([]domain.MessageRaw)
|
||||
ret0, _ := ret[0].([]domain.RawMessage)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
@ -468,10 +464,10 @@ func (mr *MockRepoMockRecorder) Register(email, hashedPassword, username, dateOf
|
|||
}
|
||||
|
||||
// Send mocks base method.
|
||||
func (m *MockRepo) Send(message repository.SendMessage) (domain.UUID, error) {
|
||||
func (m *MockRepo) Send(message repository.SendMessage) (domain.RawMessage, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Send", message)
|
||||
ret0, _ := ret[0].(domain.UUID)
|
||||
ret0, _ := ret[0].(domain.RawMessage)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
|
|
@ -21,10 +21,10 @@ type User interface {
|
|||
type Chat interface{}
|
||||
|
||||
type Message interface {
|
||||
Get(ID domain.UUID) (domain.MessageRaw, error)
|
||||
GetByIDs(IDs []domain.UUID) ([]domain.MessageRaw, error)
|
||||
GetSome(messagesInfo GetSome) ([]domain.MessageRaw, error)
|
||||
Send(message SendMessage) (domain.UUID, error)
|
||||
Get(ID domain.UUID) (domain.RawMessage, error)
|
||||
GetByIDs(IDs []domain.UUID) ([]domain.RawMessage, error)
|
||||
GetSome(messagesInfo GetSome) ([]domain.RawMessage, error)
|
||||
Send(message SendMessage) (domain.RawMessage, error)
|
||||
Delete(ID domain.UUID) error
|
||||
Edit(newMessage EditMessage) error
|
||||
Pin(msg PinMessage) error
|
||||
|
|
|
@ -42,7 +42,7 @@ func (r *userRepository) GetAll(username string) ([]domain.User, error) {
|
|||
query := fmt.Sprintf(`SELECT * FROM users WHERE username ILIKE $1 AND role != %d`, domain.AdminUser)
|
||||
err := r.db.Select(&users, query, username)
|
||||
if err != nil {
|
||||
r.l.Errorf("getting users: %s", err.Error())
|
||||
r.l.Errorf("getting users: %s", err)
|
||||
return nil, domain.InternalServerError
|
||||
}
|
||||
return users, nil
|
||||
|
@ -84,18 +84,18 @@ func (r *userRepository) Register(email, hashedPassword, username string, dateOf
|
|||
|
||||
tx, err := r.db.Beginx()
|
||||
if err != nil {
|
||||
r.l.Errorf("user registration: tx begin: %s", err.Error())
|
||||
r.l.Errorf("user registration: tx begin: %s", err)
|
||||
return domain.User{}, domain.InternalServerError
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
var pgError *pgconn.PgError
|
||||
if !errors.As(err, &pgError) {
|
||||
r.l.Errorf("user registration: %s", err.Error())
|
||||
r.l.Errorf("user registration: %s", err)
|
||||
}
|
||||
|
||||
if err = tx.Rollback(); err != nil && !errors.Is(err, sql.ErrTxDone) {
|
||||
r.l.Errorf("user registration: tx rollback: %s", err.Error())
|
||||
r.l.Errorf("user registration: tx rollback: %s", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
|
|
@ -81,7 +81,7 @@ func (s *authService) EncodeAuthToken(userID int) (string, error) {
|
|||
func (s *authService) HashPassword(p string) (string, error) {
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(p)[:maxBcryptPasswordLen], bcrypt.DefaultCost)
|
||||
if err != nil {
|
||||
s.l.Errorf("error during password hashing: %s", err.Error())
|
||||
s.l.Errorf("error during password hashing: %s", err)
|
||||
return "", domain.HashingError
|
||||
}
|
||||
return string(hash), nil
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"encoding"
|
||||
"errors"
|
||||
"github.com/redis/go-redis/v9"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.urec56.ru/urec/chat_back_go/internal/domain"
|
||||
|
@ -14,23 +15,39 @@ import (
|
|||
type cacheService struct {
|
||||
l *logger.Logger
|
||||
r redis.UniversalClient
|
||||
storage *sync.Map
|
||||
}
|
||||
|
||||
type userCache struct {
|
||||
u []byte // domain.User
|
||||
expiresAt time.Time
|
||||
}
|
||||
|
||||
func newCacheService(r redis.UniversalClient, l *logger.Logger) *cacheService {
|
||||
return &cacheService{r: r, l: l}
|
||||
return &cacheService{r: r, l: l, storage: &sync.Map{}}
|
||||
}
|
||||
|
||||
func (c *cacheService) Get(key string, v encoding.BinaryUnmarshaler) error {
|
||||
return c.GetCtx(context.Background(), key, v)
|
||||
func (c *cacheService) Get(key string, v encoding.BinaryUnmarshaler, isFast bool) error {
|
||||
return c.GetCtx(context.Background(), key, v, isFast)
|
||||
}
|
||||
|
||||
func (c *cacheService) GetCtx(ctx context.Context, key string, v encoding.BinaryUnmarshaler) error {
|
||||
func (c *cacheService) GetCtx(ctx context.Context, key string, v encoding.BinaryUnmarshaler, isFast bool) error {
|
||||
if isFast {
|
||||
item, ok := c.storage.Load(key)
|
||||
if ok {
|
||||
if userData, ok := item.(userCache); ok && userData.expiresAt.After(time.Now()) {
|
||||
err := v.UnmarshalBinary(userData.u)
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err := c.r.Get(ctx, key).Scan(v)
|
||||
if err != nil {
|
||||
if errors.Is(err, redis.Nil) {
|
||||
return domain.NoKeyFoundError
|
||||
}
|
||||
c.l.Errorf("getting key %s: %s", key, err.Error())
|
||||
c.l.Errorf("getting key %s: %s", key, err)
|
||||
return domain.InternalServerError
|
||||
}
|
||||
return nil
|
||||
|
@ -44,5 +61,12 @@ func (c *cacheService) SetCtx(ctx context.Context, key string, v encoding.Binary
|
|||
if err := c.r.SetEx(ctx, key, v, ex).Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data, err := v.MarshalBinary()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.storage.Store(key, userCache{u: data, expiresAt: time.Now().Add(time.Minute)})
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -18,9 +18,10 @@ func newMessageService(repo repository.Message, u User, l *logger.Logger) *messa
|
|||
return &messageService{repo: repo, u: u, l: l}
|
||||
}
|
||||
|
||||
func (s *messageService) AddAvatarImageAndUsernameToMessage(msgRaw domain.MessageRaw) (domain.Message, error) {
|
||||
u, err := s.u.GetCachedUser(msgRaw.UserID)
|
||||
func (s *messageService) AddAvatarImageAndUsernameToMessage(msgRaw domain.RawMessage) (domain.Message, error) {
|
||||
u, err := s.u.Get(msgRaw.UserID, true)
|
||||
if err != nil {
|
||||
s.l.Infof("error adding image and username to message: %s", err)
|
||||
return domain.Message{}, domain.InternalServerError
|
||||
}
|
||||
|
||||
|
@ -39,7 +40,7 @@ func (s *messageService) AddAvatarImageAndUsernameToMessage(msgRaw domain.Messag
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (s *messageService) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.MessageRaw) []domain.Message {
|
||||
func (s *messageService) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.RawMessage) []domain.Message {
|
||||
msgs := make([]domain.Message, 0, len(msgsRaw))
|
||||
for _, v := range msgsRaw {
|
||||
msg, err := s.AddAvatarImageAndUsernameToMessage(v)
|
||||
|
@ -51,10 +52,19 @@ func (s *messageService) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.Me
|
|||
return msgs
|
||||
}
|
||||
|
||||
func (s *messageService) GetRaw(ID domain.UUID) (domain.RawMessage, error) {
|
||||
rawMessage, err := s.repo.Get(ID)
|
||||
if err != nil {
|
||||
s.l.Infof("error getting message: %s", err)
|
||||
return domain.RawMessage{}, domain.InternalServerError
|
||||
}
|
||||
|
||||
return rawMessage, nil
|
||||
}
|
||||
|
||||
func (s *messageService) GetMessage(ID domain.UUID) (domain.Message, error) {
|
||||
rawMessage, err := s.GetRaw(ID)
|
||||
if err != nil {
|
||||
s.l.Infof("error getting message: %s", err.Error())
|
||||
return domain.Message{}, domain.InternalServerError
|
||||
}
|
||||
|
||||
|
@ -66,26 +76,16 @@ func (s *messageService) GetMessage(ID domain.UUID) (domain.Message, error) {
|
|||
return newMessage, nil
|
||||
}
|
||||
|
||||
func (s *messageService) GetRaw(ID domain.UUID) (domain.MessageRaw, error) {
|
||||
rawMessage, err := s.repo.Get(ID)
|
||||
if err != nil {
|
||||
s.l.Infof("error getting message: %s", err.Error())
|
||||
return domain.MessageRaw{}, domain.InternalServerError
|
||||
}
|
||||
|
||||
return rawMessage, nil
|
||||
}
|
||||
|
||||
func (s *messageService) GetPinned(chatID int) ([]domain.Message, error) {
|
||||
IDs, err := s.repo.GetPinnedIDs(chatID)
|
||||
if err != nil {
|
||||
s.l.Infof("error getting pinned ids: %s", err.Error())
|
||||
s.l.Infof("error getting pinned ids: %s", err)
|
||||
return nil, domain.InternalServerError
|
||||
}
|
||||
|
||||
rawMessages, err := s.repo.GetByIDs(IDs)
|
||||
if err != nil {
|
||||
s.l.Infof("error messages by ids: %s", err.Error())
|
||||
s.l.Infof("error messages by ids: %s", err)
|
||||
return nil, domain.InternalServerError
|
||||
}
|
||||
|
||||
|
@ -94,11 +94,11 @@ func (s *messageService) GetPinned(chatID int) ([]domain.Message, error) {
|
|||
return messages, nil
|
||||
}
|
||||
|
||||
func (s *messageService) GetSome(chatID, messageNumberFrom, messagesToGet int) ([]domain.Message, error) {
|
||||
messagesRaw, err := s.repo.GetSome(repository.GetSome{ChatID: chatID, MessageNumberFrom: messageNumberFrom, MessagesToGet: messagesToGet})
|
||||
func (s *messageService) GetSome(chatID, offset, limit int) ([]domain.Message, error) {
|
||||
messagesRaw, err := s.repo.GetSome(repository.GetSome{ChatID: chatID, Offset: offset, Limit: limit})
|
||||
if err != nil {
|
||||
s.l.Infof("error getting some messages: %s", err.Error())
|
||||
return nil, err
|
||||
s.l.Infof("error getting some messages: %s", err)
|
||||
return nil, domain.InternalServerError
|
||||
}
|
||||
|
||||
messages := s.AddAvatarImageAndUsernameToMessages(messagesRaw)
|
||||
|
@ -107,28 +107,28 @@ func (s *messageService) GetSome(chatID, messageNumberFrom, messagesToGet int) (
|
|||
}
|
||||
|
||||
func (s *messageService) SendMessage(userID, chatID int, message domain.SendMessage) (domain.Message, error) {
|
||||
var messageID domain.UUID
|
||||
var rawMessage domain.RawMessage
|
||||
var err error
|
||||
if message.Answer.IsZero() {
|
||||
messageID, err = s.repo.Send(repository.SendMessage{
|
||||
rawMessage, err = s.repo.Send(repository.SendMessage{
|
||||
Message: message.Message,
|
||||
ImageUrl: message.ImageUrl,
|
||||
ChatID: chatID,
|
||||
UserID: userID,
|
||||
})
|
||||
if err != nil {
|
||||
s.l.Infof("error sending message: %s", err.Error())
|
||||
s.l.Infof("error sending message: %s", err)
|
||||
return domain.Message{}, domain.InternalServerError
|
||||
}
|
||||
|
||||
} else {
|
||||
answerMessage, err := s.GetRaw(message.Answer)
|
||||
if err != nil {
|
||||
s.l.Infof("error getting message: %s", err.Error())
|
||||
s.l.Infof("error getting message: %s", err)
|
||||
return domain.Message{}, domain.InternalServerError
|
||||
}
|
||||
|
||||
messageID, err = s.repo.Send(repository.SendMessage{
|
||||
rawMessage, err = s.repo.Send(repository.SendMessage{
|
||||
Message: message.Message,
|
||||
ImageUrl: message.ImageUrl,
|
||||
ChatID: chatID,
|
||||
|
@ -138,14 +138,14 @@ func (s *messageService) SendMessage(userID, chatID int, message domain.SendMess
|
|||
AnswerImageUrl: answerMessage.ImageUrl,
|
||||
})
|
||||
if err != nil {
|
||||
s.l.Infof("error sending message: %s", err.Error())
|
||||
s.l.Infof("error sending message: %s", err)
|
||||
return domain.Message{}, domain.InternalServerError
|
||||
}
|
||||
}
|
||||
|
||||
newMessage, err := s.GetMessage(messageID)
|
||||
newMessage, err := s.AddAvatarImageAndUsernameToMessage(rawMessage)
|
||||
if err != nil {
|
||||
s.l.Infof("error getting message: %s", err.Error())
|
||||
s.l.Infof("error getting message: %s", err)
|
||||
return domain.Message{}, domain.InternalServerError
|
||||
}
|
||||
|
||||
|
@ -154,7 +154,7 @@ func (s *messageService) SendMessage(userID, chatID int, message domain.SendMess
|
|||
|
||||
func (s *messageService) Delete(ID domain.UUID) error {
|
||||
if err := s.repo.Delete(ID); err != nil {
|
||||
s.l.Infof("error deleting message: %s", err.Error())
|
||||
s.l.Infof("error deleting message: %s", err)
|
||||
return domain.InternalServerError
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ func (s *messageService) Delete(ID domain.UUID) error {
|
|||
|
||||
func (s *messageService) Edit(ID domain.UUID, newMessage, newImageUrl string) error {
|
||||
if err := s.repo.Edit(repository.EditMessage{ID: ID, Message: newMessage, ImageUrl: newImageUrl}); err != nil {
|
||||
s.l.Infof("error editing message: %s", err.Error())
|
||||
s.l.Infof("error editing message: %s", err)
|
||||
return domain.InternalServerError
|
||||
}
|
||||
|
||||
|
@ -177,13 +177,13 @@ func (s *messageService) Pin(chatID, userID int, messageID domain.UUID) (domain.
|
|||
return domain.Message{}, err
|
||||
}
|
||||
|
||||
s.l.Infof("error pinning message: %s", err.Error())
|
||||
s.l.Infof("error pinning message: %s", err)
|
||||
return domain.Message{}, domain.InternalServerError
|
||||
}
|
||||
|
||||
message, err := s.GetMessage(messageID)
|
||||
if err != nil {
|
||||
s.l.Infof("error getting message: %s", err.Error())
|
||||
s.l.Infof("error getting message: %s", err)
|
||||
return domain.Message{}, domain.InternalServerError
|
||||
}
|
||||
|
||||
|
@ -193,7 +193,7 @@ func (s *messageService) Pin(chatID, userID int, messageID domain.UUID) (domain.
|
|||
func (s *messageService) Unpin(chatID int, messageID domain.UUID) error {
|
||||
err := s.repo.Unpin(repository.UnpinMessage{ChatID: chatID, MessageID: messageID})
|
||||
if err != nil {
|
||||
s.l.Infof("error unpinning message: %s", err.Error())
|
||||
s.l.Infof("error unpinning message: %s", err)
|
||||
return domain.InternalServerError
|
||||
}
|
||||
|
||||
|
|
1338
internal/service/messages_test.go
Normal file
1338
internal/service/messages_test.go
Normal file
File diff suppressed because it is too large
Load diff
|
@ -25,7 +25,6 @@ import (
|
|||
type MockUser struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockUserMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockUserMockRecorder is the mock recorder for MockUser.
|
||||
|
@ -61,18 +60,18 @@ func (mr *MockUserMockRecorder) FindOne(username, email any) *gomock.Call {
|
|||
}
|
||||
|
||||
// Get mocks base method.
|
||||
func (m *MockUser) Get(userID int) (domain.User, error) {
|
||||
func (m *MockUser) Get(userID int, isFast bool) (domain.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Get", userID)
|
||||
ret := m.ctrl.Call(m, "Get", userID, isFast)
|
||||
ret0, _ := ret[0].(domain.User)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Get indicates an expected call of Get.
|
||||
func (mr *MockUserMockRecorder) Get(userID any) *gomock.Call {
|
||||
func (mr *MockUserMockRecorder) Get(userID, isFast any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockUser)(nil).Get), userID)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockUser)(nil).Get), userID, isFast)
|
||||
}
|
||||
|
||||
// GetAll mocks base method.
|
||||
|
@ -90,21 +89,6 @@ func (mr *MockUserMockRecorder) GetAll(username any) *gomock.Call {
|
|||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAll", reflect.TypeOf((*MockUser)(nil).GetAll), username)
|
||||
}
|
||||
|
||||
// GetCachedUser mocks base method.
|
||||
func (m *MockUser) GetCachedUser(userID int) (domain.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetCachedUser", userID)
|
||||
ret0, _ := ret[0].(domain.User)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetCachedUser indicates an expected call of GetCachedUser.
|
||||
func (mr *MockUserMockRecorder) GetCachedUser(userID any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCachedUser", reflect.TypeOf((*MockUser)(nil).GetCachedUser), userID)
|
||||
}
|
||||
|
||||
// GetVerificated mocks base method.
|
||||
func (m *MockUser) GetVerificated(userID int) (domain.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -135,23 +119,10 @@ func (mr *MockUserMockRecorder) Register(userData any) *gomock.Call {
|
|||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Register", reflect.TypeOf((*MockUser)(nil).Register), userData)
|
||||
}
|
||||
|
||||
// SetCachedUser mocks base method.
|
||||
func (m *MockUser) SetCachedUser(u domain.User) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetCachedUser", u)
|
||||
}
|
||||
|
||||
// SetCachedUser indicates an expected call of SetCachedUser.
|
||||
func (mr *MockUserMockRecorder) SetCachedUser(u any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetCachedUser", reflect.TypeOf((*MockUser)(nil).SetCachedUser), u)
|
||||
}
|
||||
|
||||
// MockAuth is a mock of Auth interface.
|
||||
type MockAuth struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockAuthMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockAuthMockRecorder is the mock recorder for MockAuth.
|
||||
|
@ -249,7 +220,6 @@ func (mr *MockAuthMockRecorder) VerifyHashedPassword(p, hp any) *gomock.Call {
|
|||
type MockChat struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockChatMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockChatMockRecorder is the mock recorder for MockChat.
|
||||
|
@ -273,7 +243,6 @@ func (m *MockChat) EXPECT() *MockChatMockRecorder {
|
|||
type MockMessages struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockMessagesMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockMessagesMockRecorder is the mock recorder for MockMessages.
|
||||
|
@ -294,7 +263,7 @@ func (m *MockMessages) EXPECT() *MockMessagesMockRecorder {
|
|||
}
|
||||
|
||||
// AddAvatarImageAndUsernameToMessage mocks base method.
|
||||
func (m *MockMessages) AddAvatarImageAndUsernameToMessage(msgRaw domain.MessageRaw) (domain.Message, error) {
|
||||
func (m *MockMessages) AddAvatarImageAndUsernameToMessage(msgRaw domain.RawMessage) (domain.Message, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AddAvatarImageAndUsernameToMessage", msgRaw)
|
||||
ret0, _ := ret[0].(domain.Message)
|
||||
|
@ -309,7 +278,7 @@ func (mr *MockMessagesMockRecorder) AddAvatarImageAndUsernameToMessage(msgRaw an
|
|||
}
|
||||
|
||||
// AddAvatarImageAndUsernameToMessages mocks base method.
|
||||
func (m *MockMessages) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.MessageRaw) []domain.Message {
|
||||
func (m *MockMessages) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.RawMessage) []domain.Message {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AddAvatarImageAndUsernameToMessages", msgsRaw)
|
||||
ret0, _ := ret[0].([]domain.Message)
|
||||
|
@ -381,10 +350,10 @@ func (mr *MockMessagesMockRecorder) GetPinned(chatID any) *gomock.Call {
|
|||
}
|
||||
|
||||
// GetRaw mocks base method.
|
||||
func (m *MockMessages) GetRaw(ID domain.UUID) (domain.MessageRaw, error) {
|
||||
func (m *MockMessages) GetRaw(ID domain.UUID) (domain.RawMessage, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetRaw", ID)
|
||||
ret0, _ := ret[0].(domain.MessageRaw)
|
||||
ret0, _ := ret[0].(domain.RawMessage)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
@ -396,18 +365,18 @@ func (mr *MockMessagesMockRecorder) GetRaw(ID any) *gomock.Call {
|
|||
}
|
||||
|
||||
// GetSome mocks base method.
|
||||
func (m *MockMessages) GetSome(chatID, messageNumberFrom, messagesToGet int) ([]domain.Message, error) {
|
||||
func (m *MockMessages) GetSome(chatID, offset, limit int) ([]domain.Message, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetSome", chatID, messageNumberFrom, messagesToGet)
|
||||
ret := m.ctrl.Call(m, "GetSome", chatID, offset, limit)
|
||||
ret0, _ := ret[0].([]domain.Message)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetSome indicates an expected call of GetSome.
|
||||
func (mr *MockMessagesMockRecorder) GetSome(chatID, messageNumberFrom, messagesToGet any) *gomock.Call {
|
||||
func (mr *MockMessagesMockRecorder) GetSome(chatID, offset, limit any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSome", reflect.TypeOf((*MockMessages)(nil).GetSome), chatID, messageNumberFrom, messagesToGet)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSome", reflect.TypeOf((*MockMessages)(nil).GetSome), chatID, offset, limit)
|
||||
}
|
||||
|
||||
// Pin mocks base method.
|
||||
|
@ -458,7 +427,6 @@ func (mr *MockMessagesMockRecorder) Unpin(chatID, messageID any) *gomock.Call {
|
|||
type MockCache struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockCacheMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockCacheMockRecorder is the mock recorder for MockCache.
|
||||
|
@ -479,31 +447,31 @@ func (m *MockCache) EXPECT() *MockCacheMockRecorder {
|
|||
}
|
||||
|
||||
// Get mocks base method.
|
||||
func (m *MockCache) Get(key string, v encoding.BinaryUnmarshaler) error {
|
||||
func (m *MockCache) Get(key string, v encoding.BinaryUnmarshaler, isFast bool) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Get", key, v)
|
||||
ret := m.ctrl.Call(m, "Get", key, v, isFast)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// Get indicates an expected call of Get.
|
||||
func (mr *MockCacheMockRecorder) Get(key, v any) *gomock.Call {
|
||||
func (mr *MockCacheMockRecorder) Get(key, v, isFast any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockCache)(nil).Get), key, v)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockCache)(nil).Get), key, v, isFast)
|
||||
}
|
||||
|
||||
// GetCtx mocks base method.
|
||||
func (m *MockCache) GetCtx(ctx context.Context, key string, v encoding.BinaryUnmarshaler) error {
|
||||
func (m *MockCache) GetCtx(ctx context.Context, key string, v encoding.BinaryUnmarshaler, isFast bool) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetCtx", ctx, key, v)
|
||||
ret := m.ctrl.Call(m, "GetCtx", ctx, key, v, isFast)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// GetCtx indicates an expected call of GetCtx.
|
||||
func (mr *MockCacheMockRecorder) GetCtx(ctx, key, v any) *gomock.Call {
|
||||
func (mr *MockCacheMockRecorder) GetCtx(ctx, key, v, isFast any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCtx", reflect.TypeOf((*MockCache)(nil).GetCtx), ctx, key, v)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCtx", reflect.TypeOf((*MockCache)(nil).GetCtx), ctx, key, v, isFast)
|
||||
}
|
||||
|
||||
// Set mocks base method.
|
||||
|
@ -538,7 +506,6 @@ func (mr *MockCacheMockRecorder) SetCtx(ctx, key, v, ex any) *gomock.Call {
|
|||
type MockParser struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockParserMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockParserMockRecorder is the mock recorder for MockParser.
|
||||
|
@ -623,7 +590,6 @@ func (mr *MockParserMockRecorder) ParseWithClaims(tokenString, claims, keyFunc a
|
|||
type MockClaims struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockClaimsMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockClaimsMockRecorder is the mock recorder for MockClaims.
|
||||
|
@ -737,7 +703,6 @@ func (mr *MockClaimsMockRecorder) GetSubject() *gomock.Call {
|
|||
type MockServ struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockServMockRecorder
|
||||
isgomock struct{}
|
||||
}
|
||||
|
||||
// MockServMockRecorder is the mock recorder for MockServ.
|
||||
|
@ -758,7 +723,7 @@ func (m *MockServ) EXPECT() *MockServMockRecorder {
|
|||
}
|
||||
|
||||
// AddAvatarImageAndUsernameToMessage mocks base method.
|
||||
func (m *MockServ) AddAvatarImageAndUsernameToMessage(msgRaw domain.MessageRaw) (domain.Message, error) {
|
||||
func (m *MockServ) AddAvatarImageAndUsernameToMessage(msgRaw domain.RawMessage) (domain.Message, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AddAvatarImageAndUsernameToMessage", msgRaw)
|
||||
ret0, _ := ret[0].(domain.Message)
|
||||
|
@ -773,7 +738,7 @@ func (mr *MockServMockRecorder) AddAvatarImageAndUsernameToMessage(msgRaw any) *
|
|||
}
|
||||
|
||||
// AddAvatarImageAndUsernameToMessages mocks base method.
|
||||
func (m *MockServ) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.MessageRaw) []domain.Message {
|
||||
func (m *MockServ) AddAvatarImageAndUsernameToMessages(msgsRaw []domain.RawMessage) []domain.Message {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AddAvatarImageAndUsernameToMessages", msgsRaw)
|
||||
ret0, _ := ret[0].([]domain.Message)
|
||||
|
@ -875,18 +840,18 @@ func (mr *MockServMockRecorder) FindOne(username, email any) *gomock.Call {
|
|||
}
|
||||
|
||||
// Get mocks base method.
|
||||
func (m *MockServ) Get(userID int) (domain.User, error) {
|
||||
func (m *MockServ) Get(userID int, isFast bool) (domain.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Get", userID)
|
||||
ret := m.ctrl.Call(m, "Get", userID, isFast)
|
||||
ret0, _ := ret[0].(domain.User)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// Get indicates an expected call of Get.
|
||||
func (mr *MockServMockRecorder) Get(userID any) *gomock.Call {
|
||||
func (mr *MockServMockRecorder) Get(userID, isFast any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockServ)(nil).Get), userID)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockServ)(nil).Get), userID, isFast)
|
||||
}
|
||||
|
||||
// GetAll mocks base method.
|
||||
|
@ -904,21 +869,6 @@ func (mr *MockServMockRecorder) GetAll(username any) *gomock.Call {
|
|||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAll", reflect.TypeOf((*MockServ)(nil).GetAll), username)
|
||||
}
|
||||
|
||||
// GetCachedUser mocks base method.
|
||||
func (m *MockServ) GetCachedUser(userID int) (domain.User, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetCachedUser", userID)
|
||||
ret0, _ := ret[0].(domain.User)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetCachedUser indicates an expected call of GetCachedUser.
|
||||
func (mr *MockServMockRecorder) GetCachedUser(userID any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCachedUser", reflect.TypeOf((*MockServ)(nil).GetCachedUser), userID)
|
||||
}
|
||||
|
||||
// GetMessage mocks base method.
|
||||
func (m *MockServ) GetMessage(ID domain.UUID) (domain.Message, error) {
|
||||
m.ctrl.T.Helper()
|
||||
|
@ -950,10 +900,10 @@ func (mr *MockServMockRecorder) GetPinned(chatID any) *gomock.Call {
|
|||
}
|
||||
|
||||
// GetRaw mocks base method.
|
||||
func (m *MockServ) GetRaw(ID domain.UUID) (domain.MessageRaw, error) {
|
||||
func (m *MockServ) GetRaw(ID domain.UUID) (domain.RawMessage, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetRaw", ID)
|
||||
ret0, _ := ret[0].(domain.MessageRaw)
|
||||
ret0, _ := ret[0].(domain.RawMessage)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
@ -965,18 +915,18 @@ func (mr *MockServMockRecorder) GetRaw(ID any) *gomock.Call {
|
|||
}
|
||||
|
||||
// GetSome mocks base method.
|
||||
func (m *MockServ) GetSome(chatID, messageNumberFrom, messagesToGet int) ([]domain.Message, error) {
|
||||
func (m *MockServ) GetSome(chatID, offset, limit int) ([]domain.Message, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "GetSome", chatID, messageNumberFrom, messagesToGet)
|
||||
ret := m.ctrl.Call(m, "GetSome", chatID, offset, limit)
|
||||
ret0, _ := ret[0].([]domain.Message)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// GetSome indicates an expected call of GetSome.
|
||||
func (mr *MockServMockRecorder) GetSome(chatID, messageNumberFrom, messagesToGet any) *gomock.Call {
|
||||
func (mr *MockServMockRecorder) GetSome(chatID, offset, limit any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSome", reflect.TypeOf((*MockServ)(nil).GetSome), chatID, messageNumberFrom, messagesToGet)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSome", reflect.TypeOf((*MockServ)(nil).GetSome), chatID, offset, limit)
|
||||
}
|
||||
|
||||
// GetVerificated mocks base method.
|
||||
|
@ -1054,18 +1004,6 @@ func (mr *MockServMockRecorder) SendMessage(userID, chatID, message any) *gomock
|
|||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SendMessage", reflect.TypeOf((*MockServ)(nil).SendMessage), userID, chatID, message)
|
||||
}
|
||||
|
||||
// SetCachedUser mocks base method.
|
||||
func (m *MockServ) SetCachedUser(u domain.User) {
|
||||
m.ctrl.T.Helper()
|
||||
m.ctrl.Call(m, "SetCachedUser", u)
|
||||
}
|
||||
|
||||
// SetCachedUser indicates an expected call of SetCachedUser.
|
||||
func (mr *MockServMockRecorder) SetCachedUser(u any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetCachedUser", reflect.TypeOf((*MockServ)(nil).SetCachedUser), u)
|
||||
}
|
||||
|
||||
// Unpin mocks base method.
|
||||
func (m *MockServ) Unpin(chatID int, messageID domain.UUID) error {
|
||||
m.ctrl.T.Helper()
|
||||
|
|
|
@ -17,9 +17,7 @@ import (
|
|||
//go:generate mockgen -source=service.go -destination=mocks/mock.go
|
||||
|
||||
type User interface {
|
||||
GetCachedUser(userID int) (domain.User, error)
|
||||
SetCachedUser(u domain.User)
|
||||
Get(userID int) (domain.User, error)
|
||||
Get(userID int, isFast bool) (domain.User, error)
|
||||
GetVerificated(userID int) (domain.User, error)
|
||||
GetAll(username string) ([]domain.User, error)
|
||||
FindOne(username, email string) (domain.User, error)
|
||||
|
@ -37,12 +35,12 @@ type Auth interface {
|
|||
type Chat interface{}
|
||||
|
||||
type Messages interface {
|
||||
AddAvatarImageAndUsernameToMessage(msgRaw domain.MessageRaw) (domain.Message, error)
|
||||
AddAvatarImageAndUsernameToMessages(msgsRaw []domain.MessageRaw) []domain.Message
|
||||
AddAvatarImageAndUsernameToMessage(msgRaw domain.RawMessage) (domain.Message, error)
|
||||
AddAvatarImageAndUsernameToMessages(msgsRaw []domain.RawMessage) []domain.Message
|
||||
GetRaw(ID domain.UUID) (domain.RawMessage, error)
|
||||
GetMessage(ID domain.UUID) (domain.Message, error)
|
||||
GetRaw(ID domain.UUID) (domain.MessageRaw, error)
|
||||
GetPinned(chatID int) ([]domain.Message, error)
|
||||
GetSome(chatID, messageNumberFrom, messagesToGet int) ([]domain.Message, error)
|
||||
GetSome(chatID, offset, limit int) ([]domain.Message, error)
|
||||
SendMessage(userID, chatID int, message domain.SendMessage) (domain.Message, error)
|
||||
Delete(ID domain.UUID) error
|
||||
Edit(ID domain.UUID, newMessage, newImageUrl string) error
|
||||
|
@ -51,8 +49,8 @@ type Messages interface {
|
|||
}
|
||||
|
||||
type Cache interface {
|
||||
Get(key string, v encoding.BinaryUnmarshaler) error
|
||||
GetCtx(ctx context.Context, key string, v encoding.BinaryUnmarshaler) error
|
||||
Get(key string, v encoding.BinaryUnmarshaler, isFast bool) error
|
||||
GetCtx(ctx context.Context, key string, v encoding.BinaryUnmarshaler, isFast bool) error
|
||||
Set(key string, v encoding.BinaryMarshaler, ex time.Duration) error
|
||||
SetCtx(ctx context.Context, key string, v encoding.BinaryMarshaler, ex time.Duration) error
|
||||
}
|
||||
|
|
|
@ -23,9 +23,9 @@ func Test_NewService(t *testing.T) {
|
|||
rdb := &redis.Client{}
|
||||
|
||||
serv := NewService(repo, cfg, log, rdb)
|
||||
cache := &cacheService{l: log, r: rdb}
|
||||
cache := &cacheService{l: log, r: rdb, storage: &sync.Map{}}
|
||||
auth := &authService{cfg: cfg.JWT, parser: jwt.NewParser(), l: log}
|
||||
user := &userService{ur: repo, auth: auth, l: log, cache: cache, m: &sync.Map{}}
|
||||
user := &userService{ur: repo, auth: auth, l: log, cache: cache}
|
||||
expectedServ := &Service{
|
||||
User: user,
|
||||
Auth: auth,
|
||||
|
|
|
@ -3,7 +3,6 @@ package service
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"git.urec56.ru/urec/chat_back_go/internal/domain"
|
||||
|
@ -13,58 +12,30 @@ import (
|
|||
|
||||
type userService struct {
|
||||
cache Cache
|
||||
m *sync.Map
|
||||
ur repository.User
|
||||
auth Auth
|
||||
l *logger.Logger
|
||||
}
|
||||
|
||||
type userCache struct {
|
||||
u domain.User
|
||||
expiresAt time.Time
|
||||
}
|
||||
|
||||
func newUserService(user repository.User, auth Auth, l *logger.Logger, cache Cache) *userService {
|
||||
return &userService{ur: user, auth: auth, l: l, cache: cache, m: &sync.Map{}}
|
||||
return &userService{ur: user, auth: auth, l: l, cache: cache}
|
||||
}
|
||||
|
||||
func (s *userService) GetCachedUser(userID int) (domain.User, error) {
|
||||
item, ok := s.m.Load(userID)
|
||||
if ok {
|
||||
if userData, ok := item.(userCache); ok && userData.expiresAt.After(time.Now()) {
|
||||
return userData.u, nil
|
||||
}
|
||||
}
|
||||
|
||||
u, err := s.Get(userID)
|
||||
if err != nil {
|
||||
s.l.Infof("error getting user by id: %s", err.Error())
|
||||
return domain.User{}, domain.UserNotFoundError
|
||||
}
|
||||
|
||||
s.SetCachedUser(u)
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (s *userService) SetCachedUser(u domain.User) {
|
||||
s.m.Store(u.ID, userCache{u: u, expiresAt: time.Now().Add(time.Minute)})
|
||||
}
|
||||
|
||||
func (s *userService) Get(userID int) (domain.User, error) {
|
||||
func (s *userService) Get(userID int, isFast bool) (domain.User, error) {
|
||||
u := domain.User{}
|
||||
err := s.cache.Get(fmt.Sprintf("user: {'id': %d}", userID), &u)
|
||||
err := s.cache.Get(fmt.Sprintf("user: {'id': %d}", userID), &u, isFast)
|
||||
if err == nil {
|
||||
return u, nil
|
||||
}
|
||||
|
||||
s.l.Infof("error getting user from cache: %s", err.Error())
|
||||
s.l.Infof("error getting user from cache: %s", err)
|
||||
u, err = s.ur.GetByID(userID)
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
|
||||
if err = s.cache.Set(fmt.Sprintf("user: {'id': %d}", userID), u, time.Second*20); err != nil {
|
||||
s.l.Infof("error setting user to cache: %s", err.Error())
|
||||
if err = s.cache.Set(fmt.Sprintf("user: {'id': %d}", userID), &u, time.Second*20); err != nil {
|
||||
s.l.Infof("error setting user to cache: %s", err)
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import (
|
|||
"errors"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"go.uber.org/mock/gomock"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -27,7 +26,7 @@ func Test_newUserService(t *testing.T) {
|
|||
|
||||
serv := newUserService(repo, auth, log, cache)
|
||||
|
||||
assert.EqualValues(t, &userService{ur: repo, auth: auth, l: log, cache: cache, m: &sync.Map{}}, serv)
|
||||
assert.EqualValues(t, &userService{ur: repo, auth: auth, l: log, cache: cache}, serv)
|
||||
}
|
||||
|
||||
func TestUserService_Get(t *testing.T) {
|
||||
|
@ -64,8 +63,10 @@ func TestUserService_Get(t *testing.T) {
|
|||
name: "user_in_cache",
|
||||
repoBehavior: func(r *mock_repository.MockUser, userID int, user domain.User, err error) {},
|
||||
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
|
||||
c.EXPECT().Get(key, gomock.Any()).DoAndReturn(
|
||||
func(key string, v encoding.BinaryUnmarshaler) error { return v.UnmarshalBinary([]byte(`{"id": 1}`)) },
|
||||
c.EXPECT().Get(key, gomock.Any(), false).DoAndReturn(
|
||||
func(key string, v encoding.BinaryUnmarshaler, isFast bool) error {
|
||||
return v.UnmarshalBinary([]byte(`{"id": 1}`))
|
||||
},
|
||||
)
|
||||
},
|
||||
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {},
|
||||
|
@ -80,7 +81,7 @@ func TestUserService_Get(t *testing.T) {
|
|||
r.EXPECT().GetByID(userID).Return(user, err)
|
||||
},
|
||||
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
|
||||
c.EXPECT().Get(key, gomock.Any()).Return(err)
|
||||
c.EXPECT().Get(key, gomock.Any(), false).Return(err)
|
||||
},
|
||||
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {
|
||||
c.EXPECT().Set(key, v, ex).Return(err)
|
||||
|
@ -99,7 +100,7 @@ func TestUserService_Get(t *testing.T) {
|
|||
r.EXPECT().GetByID(userID).Return(user, err)
|
||||
},
|
||||
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
|
||||
c.EXPECT().Get(key, gomock.Any()).Return(err)
|
||||
c.EXPECT().Get(key, gomock.Any(), false).Return(err)
|
||||
},
|
||||
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {},
|
||||
cacheKey: "user: {'id': 1}",
|
||||
|
@ -115,7 +116,7 @@ func TestUserService_Get(t *testing.T) {
|
|||
r.EXPECT().GetByID(userID).Return(user, err)
|
||||
},
|
||||
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
|
||||
c.EXPECT().Get(key, gomock.Any()).Return(err)
|
||||
c.EXPECT().Get(key, gomock.Any(), false).Return(err)
|
||||
},
|
||||
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {
|
||||
c.EXPECT().Set(key, v, ex).Return(err)
|
||||
|
@ -134,7 +135,7 @@ func TestUserService_Get(t *testing.T) {
|
|||
r.EXPECT().GetByID(userID).Return(user, err)
|
||||
},
|
||||
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
|
||||
c.EXPECT().Get(key, gomock.Any()).Return(err)
|
||||
c.EXPECT().Get(key, gomock.Any(), false).Return(err)
|
||||
},
|
||||
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {
|
||||
c.EXPECT().Set(key, v, ex).Return(err)
|
||||
|
@ -154,7 +155,7 @@ func TestUserService_Get(t *testing.T) {
|
|||
r.EXPECT().GetByID(userID).Return(user, err)
|
||||
},
|
||||
cacheGetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryUnmarshaler, err error) {
|
||||
c.EXPECT().Get(key, gomock.Any()).Return(err)
|
||||
c.EXPECT().Get(key, gomock.Any(), false).Return(err)
|
||||
},
|
||||
cacheSetBehavior: func(c *mock_service.MockCache, key string, v encoding.BinaryMarshaler, ex time.Duration, err error) {},
|
||||
cacheKey: "user: {'id': 1}",
|
||||
|
@ -178,9 +179,9 @@ func TestUserService_Get(t *testing.T) {
|
|||
|
||||
tc.repoBehavior(repo, tc.userID, tc.repoUser, tc.repoErr)
|
||||
tc.cacheGetBehavior(cache, tc.cacheKey, tc.cacheGetData.container, tc.cacheGetData.err)
|
||||
tc.cacheSetBehavior(cache, tc.cacheKey, tc.cacheSetData.value, tc.cacheSetData.duration, tc.cacheSetData.err)
|
||||
tc.cacheSetBehavior(cache, tc.cacheKey, &tc.cacheSetData.value, tc.cacheSetData.duration, tc.cacheSetData.err)
|
||||
|
||||
u, err := serv.Get(tc.userID)
|
||||
u, err := serv.Get(tc.userID, false)
|
||||
|
||||
assert.Equal(t, tc.expectedUser, u)
|
||||
assert.ErrorIs(t, err, tc.expectedErr)
|
||||
|
|
|
@ -17,7 +17,7 @@ func (h *Handler) GetUsers(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
users, err := h.serv.GetAll(username)
|
||||
if err != nil {
|
||||
h.l.Infof("[%s] getting users: %s", r.URL.Path, err.Error())
|
||||
h.l.Infof("[%s] getting users: %s", r.URL.Path, err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ func (h *Handler) GetUsers(w http.ResponseWriter, r *http.Request) {
|
|||
j, _ := json.Marshal(map[string][]domain.User{"users": users}) // no error because []domain.User can`t cause any error here
|
||||
|
||||
if _, err = w.Write(j); err != nil {
|
||||
h.l.Errorf("[%s] writing response: %s", r.URL.Path, err.Error())
|
||||
h.l.Errorf("[%s] writing response: %s", r.URL.Path, err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
@ -42,14 +42,14 @@ func (h *Handler) CheckExisting(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
if err := domain.V.Struct(userFilter); err != nil {
|
||||
h.l.Infof("[%s] validation: %s", r.URL.Path, err.Error())
|
||||
h.l.Infof("[%s] validation: %s", r.URL.Path, err)
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
return
|
||||
}
|
||||
|
||||
u, err := h.serv.FindOne(userFilter.Username, userFilter.Email)
|
||||
if err != nil {
|
||||
h.l.Infof("[%s] serv.FindOne error: %s", r.URL.Path, err.Error())
|
||||
h.l.Infof("[%s] serv.FindOne error: %s", r.URL.Path, err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ func (h *Handler) Register(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
if err := domain.V.Struct(userData); err != nil {
|
||||
h.l.Infof("[%s] validation: %s", r.URL.Path, err.Error())
|
||||
h.l.Infof("[%s] validation: %s", r.URL.Path, err)
|
||||
w.WriteHeader(http.StatusUnprocessableEntity)
|
||||
return
|
||||
}
|
||||
|
@ -87,7 +87,7 @@ func (h *Handler) Register(w http.ResponseWriter, r *http.Request) {
|
|||
if errors.Is(err, domain.UserAlreadyExistsError) {
|
||||
w.WriteHeader(http.StatusConflict)
|
||||
} else {
|
||||
h.l.Infof("[%s] serv.Register: %s", r.URL.Path, err.Error())
|
||||
h.l.Infof("[%s] serv.Register: %s", r.URL.Path, err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}
|
||||
return
|
||||
|
@ -97,7 +97,7 @@ func (h *Handler) Register(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
if _, err = w.Write(resp); err != nil {
|
||||
h.l.Errorf("[%s] writing response: %s", r.URL.Path, err.Error())
|
||||
h.l.Errorf("[%s] writing response: %s", r.URL.Path, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ func (h *Handler) Get(w http.ResponseWriter, r *http.Request) {
|
|||
j, _ := json.Marshal(user) // no error because domain.User can`t cause any error here
|
||||
|
||||
if _, err := w.Write(j); err != nil {
|
||||
h.l.Errorf("[%s] writing response: %s", r.URL.Path, err.Error())
|
||||
h.l.Errorf("[%s] writing response: %s", r.URL.Path, err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -13,25 +13,25 @@ func (m *Middleware) Auth(next http.HandlerFunc) http.HandlerFunc {
|
|||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := m.serv.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
m.l.Infof("[%s] error extracting token: %s", r.URL.Path, err.Error())
|
||||
m.l.Infof("[%s] error extracting token: %s", r.URL.Path, err)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
userID, err := m.serv.DecodeAuthToken(t)
|
||||
if err != nil {
|
||||
m.l.Infof("[%s] error decoding token: %s", r.URL.Path, err.Error())
|
||||
m.l.Infof("[%s] error decoding token: %s", r.URL.Path, err)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
user, err := m.serv.Get(userID)
|
||||
user, err := m.serv.Get(userID, false)
|
||||
if err != nil {
|
||||
if errors.Is(err, domain.UserNotFoundError) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
m.l.Infof("[%s] error resolving user: %s", r.URL.Path, err.Error())
|
||||
m.l.Infof("[%s] error resolving user: %s", r.URL.Path, err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
@ -48,14 +48,14 @@ func (m *Middleware) VerificatedAuth(next http.HandlerFunc) http.HandlerFunc {
|
|||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
t, err := m.serv.ExtractAuthToken(r)
|
||||
if err != nil {
|
||||
m.l.Infof("[%s] error extracting token: %s", r.URL.Path, err.Error())
|
||||
m.l.Infof("[%s] error extracting token: %s", r.URL.Path, err)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
||||
userID, err := m.serv.DecodeAuthToken(t)
|
||||
if err != nil {
|
||||
m.l.Infof("[%s] error decoding token: %s", r.URL.Path, err.Error())
|
||||
m.l.Infof("[%s] error decoding token: %s", r.URL.Path, err)
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ func (m *Middleware) VerificatedAuth(next http.HandlerFunc) http.HandlerFunc {
|
|||
w.WriteHeader(http.StatusConflict)
|
||||
return
|
||||
}
|
||||
m.l.Infof("[%s] error resolving user: %s", r.URL.Path, err.Error())
|
||||
m.l.Infof("[%s] error resolving user: %s", r.URL.Path, err)
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ func TestMiddleware_Auth(t *testing.T) {
|
|||
s.EXPECT().DecodeAuthToken(token).Return(userID, err)
|
||||
},
|
||||
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {
|
||||
s.EXPECT().Get(userID).Return(user, err)
|
||||
s.EXPECT().Get(userID, false).Return(user, err)
|
||||
},
|
||||
reqToken: "Bearer token",
|
||||
extractToken: "token",
|
||||
|
@ -82,7 +82,7 @@ func TestMiddleware_Auth(t *testing.T) {
|
|||
s.EXPECT().DecodeAuthToken(token).Return(userID, err)
|
||||
},
|
||||
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {
|
||||
s.EXPECT().Get(userID).Return(user, err)
|
||||
s.EXPECT().Get(userID, false).Return(user, err)
|
||||
},
|
||||
reqToken: "Bearer token",
|
||||
extractToken: "token",
|
||||
|
@ -122,7 +122,7 @@ func TestMiddleware_Auth(t *testing.T) {
|
|||
s.EXPECT().DecodeAuthToken(token).Return(userID, err)
|
||||
},
|
||||
getBehavior: func(s *mock_service.MockServ, userID int, user domain.User, err error) {
|
||||
s.EXPECT().Get(userID).Return(user, err)
|
||||
s.EXPECT().Get(userID, false).Return(user, err)
|
||||
},
|
||||
getErr: domain.AnyError,
|
||||
logErr: domain.AnyError,
|
||||
|
|
|
@ -3,9 +3,11 @@ package rest
|
|||
import (
|
||||
"context"
|
||||
"expvar"
|
||||
"github.com/urec56/pathparams"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/urec56/pathparams"
|
||||
|
||||
"git.urec56.ru/urec/chat_back_go/config"
|
||||
"git.urec56.ru/urec/chat_back_go/internal/logger"
|
||||
"git.urec56.ru/urec/chat_back_go/internal/service"
|
||||
|
@ -23,11 +25,11 @@ func NewServer(serv service.Serv, l *logger.Logger, cfg config.Config) *Server {
|
|||
return &Server{m: middleware.NewMiddleware(serv, l, cfg.Srv), h: handler.NewHandler(serv, l)}
|
||||
}
|
||||
|
||||
func (s *Server) Run(port string) error {
|
||||
func (s *Server) Run(port int) error {
|
||||
r := s.getRouter()
|
||||
|
||||
s.httpServer = &http.Server{
|
||||
Addr: ":" + port,
|
||||
Addr: fmt.Sprintf(":%d", port),
|
||||
Handler: r,
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue