test
This commit is contained in:
parent
a0f879a3d4
commit
3c6748d5b3
@ -3,6 +3,6 @@ FROM golang:1.23-alpine
|
|||||||
WORKDIR /root
|
WORKDIR /root
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN go install github.com/swaggo/swag/cmd/swag@latest
|
RUN go install github.com/swaggo/swag/cmd/swag@latest
|
||||||
RUN go mod tidy && swag init -g cmd/main.go -o cmd/docs
|
RUN go mod tidy && swag init -g cmd/main.go -o api/http
|
||||||
|
|
||||||
CMD go run cmd/main.go
|
CMD go run cmd/main.go
|
@ -1,5 +1,5 @@
|
|||||||
// Package docs Code generated by swaggo/swag. DO NOT EDIT
|
// Package docs Code generated by swaggo/swag. DO NOT EDIT
|
||||||
package docs
|
package http
|
||||||
|
|
||||||
import "github.com/swaggo/swag"
|
import "github.com/swaggo/swag"
|
||||||
|
|
30
cmd/main.go
30
cmd/main.go
@ -1,17 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import "donat-widget/internal/app/http"
|
||||||
"github.com/labstack/echo/v4"
|
|
||||||
"log/slog"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
import (
|
|
||||||
_ "donat-widget/cmd/docs"
|
|
||||||
"donat-widget/cmd/handlers"
|
|
||||||
"donat-widget/config"
|
|
||||||
"donat-widget/lib/validator"
|
|
||||||
)
|
|
||||||
|
|
||||||
// @title Widget service
|
// @title Widget service
|
||||||
// @version 1.0
|
// @version 1.0
|
||||||
@ -20,20 +9,7 @@ import (
|
|||||||
// @host localhost:8002
|
// @host localhost:8002
|
||||||
// @BasePath /api/widget
|
// @BasePath /api/widget
|
||||||
|
|
||||||
func init() {
|
|
||||||
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
|
|
||||||
slog.SetDefault(logger)
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := initApp()
|
httpServer := http.NewApp()
|
||||||
port := config.Config.Server.Port
|
http.Run(httpServer)
|
||||||
app.Logger.Fatal(app.Start(":" + port))
|
|
||||||
}
|
|
||||||
|
|
||||||
func initApp() *echo.Echo {
|
|
||||||
app := echo.New()
|
|
||||||
app.Validator = validator.NewValidator()
|
|
||||||
handlers.IncludeRouters(app)
|
|
||||||
return app
|
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,13 @@ package pg
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"donat-widget/config"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/jackc/pgx/v5/pgxpool"
|
"github.com/jackc/pgx/v5/pgxpool"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Postgres struct {
|
type Postgres struct {
|
||||||
Db *pgxpool.Pool
|
db *pgxpool.Pool
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -20,7 +19,7 @@ var (
|
|||||||
func NewPgPool(
|
func NewPgPool(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
username, password, host, port, dbname string,
|
username, password, host, port, dbname string,
|
||||||
) (*Postgres, error) {
|
) *Postgres {
|
||||||
connString := "postgres://" + username + ":" + password + "@" + host + ":" + port + "/" + dbname + "?pool_max_conns=100"
|
connString := "postgres://" + username + ":" + password + "@" + host + ":" + port + "/" + dbname + "?pool_max_conns=100"
|
||||||
pgOnce.Do(func() {
|
pgOnce.Do(func() {
|
||||||
db, err := pgxpool.New(ctx, connString)
|
db, err := pgxpool.New(ctx, connString)
|
||||||
@ -30,20 +29,11 @@ func NewPgPool(
|
|||||||
pgInstance = &Postgres{db}
|
pgInstance = &Postgres{db}
|
||||||
})
|
})
|
||||||
|
|
||||||
return pgInstance, nil
|
return pgInstance
|
||||||
}
|
|
||||||
|
|
||||||
func (pg *Postgres) Ping(ctx context.Context) error {
|
|
||||||
err := pg.Db.Ping(ctx)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (pg *Postgres) Close() {
|
|
||||||
pg.Db.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pg *Postgres) CreateTable(ctx context.Context) error {
|
func (pg *Postgres) CreateTable(ctx context.Context) error {
|
||||||
result, err := pg.Db.Exec(ctx, createTableQuery)
|
result, err := pg.db.Exec(ctx, createTableQuery)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -51,11 +41,32 @@ func (pg *Postgres) CreateTable(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var Pool, _ = NewPgPool(
|
func (pg *Postgres) DropTable(ctx context.Context) error {
|
||||||
context.Background(),
|
result, err := pg.db.Exec(ctx, dropTableQuery)
|
||||||
config.Config.Database.Username,
|
if err != nil {
|
||||||
config.Config.Database.Password,
|
return err
|
||||||
config.Config.Database.Host,
|
}
|
||||||
config.Config.Database.Port,
|
fmt.Println(result)
|
||||||
config.Config.Database.DBName,
|
return nil
|
||||||
)
|
}
|
||||||
|
|
||||||
|
func (pg *Postgres) Exec(ctx context.Context, query string, args ...interface{}) (interface{}, error) {
|
||||||
|
result, err := pg.db.Exec(ctx, query, args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pg *Postgres) Query(ctx context.Context, query string, args ...interface{}) (interface{}, error) {
|
||||||
|
result, err := pg.db.Query(ctx, query, args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pg *Postgres) QueryRow(ctx context.Context, query string, args ...interface{}) interface{} {
|
||||||
|
result := pg.db.QueryRow(ctx, query, args...)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
@ -9,7 +9,7 @@ var createTableQuery = `
|
|||||||
video TEXT DEFAULT '',
|
video TEXT DEFAULT '',
|
||||||
image TEXT DEFAULT '',
|
image TEXT DEFAULT '',
|
||||||
audio TEXT DEFAULT '',
|
audio TEXT DEFAULT '',
|
||||||
duration TEXT DEFAULT '',
|
duration INTEGER DEFAULT 30,
|
||||||
display BOOLEAN DEFAULT TRUE,
|
display BOOLEAN DEFAULT TRUE,
|
||||||
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
@ -32,5 +32,5 @@ CREATE OR REPLACE FUNCTION update_updated_at()
|
|||||||
`
|
`
|
||||||
|
|
||||||
var dropTableQuery = `
|
var dropTableQuery = `
|
||||||
DROP TABLE IF EXISTS test_users;
|
DROP TABLE IF EXISTS widgets;
|
||||||
`
|
`
|
||||||
|
@ -1 +1,52 @@
|
|||||||
package widget
|
package widget
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/labstack/echo/v4"
|
||||||
|
"log/slog"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
type requestModel struct {
|
||||||
|
UserId int `json:"userId" validate:"required"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type responseModel struct {
|
||||||
|
WidgetId int `json:"widgetId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Creator interface {
|
||||||
|
Create(ctx context.Context, userId int) (int, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create @Description Create widget
|
||||||
|
//
|
||||||
|
// @Tags Widget
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Param RegisterData body requestModel true "Create widget"
|
||||||
|
// @Success 200 {object} responseModel
|
||||||
|
// @Router /api/widget/create [post]
|
||||||
|
func Create(service Creator, log *slog.Logger) echo.HandlerFunc {
|
||||||
|
return func(request echo.Context) error {
|
||||||
|
ctx := context.Background()
|
||||||
|
var widgetData requestModel
|
||||||
|
if err := request.Bind(&widgetData); err != nil {
|
||||||
|
slog.Error(err.Error())
|
||||||
|
return echo.NewHTTPError(400, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
err := request.Validate(&widgetData)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error(err.Error())
|
||||||
|
return echo.NewHTTPError(400, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
id, err := service.Create(ctx, widgetData.UserId)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error(err.Error())
|
||||||
|
return request.JSON(422, err)
|
||||||
|
}
|
||||||
|
return request.String(200, strconv.FormatUint(uint64(id), 10))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
73
internal/app/http/app.go
Normal file
73
internal/app/http/app.go
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
_ "donat-widget/api/http"
|
||||||
|
"donat-widget/infrastructure/pg"
|
||||||
|
widgetHandler "donat-widget/internal/api/http/handlers/widget"
|
||||||
|
"donat-widget/internal/config"
|
||||||
|
"donat-widget/pkg/validator"
|
||||||
|
"github.com/labstack/echo/v4"
|
||||||
|
"github.com/swaggo/echo-swagger"
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
import (
|
||||||
|
widgetService "donat-widget/internal/service/widget"
|
||||||
|
)
|
||||||
|
|
||||||
|
type App struct {
|
||||||
|
Config *config.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewApp() *echo.Echo {
|
||||||
|
app := &App{}
|
||||||
|
cfg := app.InitConfig()
|
||||||
|
pool := app.initDB(cfg)
|
||||||
|
log := app.InitLogger()
|
||||||
|
|
||||||
|
server := InitHTTPServer()
|
||||||
|
InitHandlers(server, pool, log)
|
||||||
|
|
||||||
|
return server
|
||||||
|
}
|
||||||
|
|
||||||
|
func Run(server *echo.Echo) {
|
||||||
|
server.Logger.Fatal(server.Start(":8002"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitHTTPServer() *echo.Echo {
|
||||||
|
server := echo.New()
|
||||||
|
server.Validator = validator.NewValidator()
|
||||||
|
return server
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) InitConfig() *config.Config {
|
||||||
|
cfg := config.Init()
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) initDB(cfg *config.Config) *pg.Postgres {
|
||||||
|
pool := pg.NewPgPool(
|
||||||
|
context.Background(),
|
||||||
|
cfg.Database.Username,
|
||||||
|
cfg.Database.Password,
|
||||||
|
cfg.Database.Host,
|
||||||
|
cfg.Database.Port,
|
||||||
|
cfg.Database.DBName,
|
||||||
|
)
|
||||||
|
return pool
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitHandlers(server *echo.Echo, pool *pg.Postgres, log *slog.Logger) {
|
||||||
|
PREFIX := "/api/widget"
|
||||||
|
server.GET("/api/docs/*", echoSwagger.WrapHandler)
|
||||||
|
widgetSvc := widgetService.New(pool)
|
||||||
|
server.GET(PREFIX+"/create", widgetHandler.Create(widgetSvc, log))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *App) InitLogger() *slog.Logger {
|
||||||
|
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
|
||||||
|
return logger
|
||||||
|
}
|
@ -1 +1,33 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Database DatabaseConfig `yaml:"db"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DatabaseConfig struct {
|
||||||
|
Username string `yaml:"username"`
|
||||||
|
Password string `yaml:"password"`
|
||||||
|
Host string `yaml:"host"`
|
||||||
|
Port string `yaml:"port"`
|
||||||
|
DBName string `yaml:"dbname"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Init() *Config {
|
||||||
|
data, err := os.ReadFile("internal/config/config.yaml")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfg Config
|
||||||
|
|
||||||
|
err = yaml.Unmarshal(data, &cfg)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return &cfg
|
||||||
|
}
|
||||||
|
@ -1 +1,32 @@
|
|||||||
package widget
|
package widget
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
type User struct {
|
||||||
|
Id int `json:"id"`
|
||||||
|
Login string `json:"login"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *Repository) Create(
|
||||||
|
ctx context.Context,
|
||||||
|
userId int,
|
||||||
|
) (int, error) {
|
||||||
|
query := `
|
||||||
|
INSERT INTO widgets (userId)
|
||||||
|
VALUES (@userId);
|
||||||
|
`
|
||||||
|
args := pgx.NamedArgs{
|
||||||
|
"userId": userId,
|
||||||
|
}
|
||||||
|
result, err := r.Exec(ctx, query, args)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
widgetId := 9
|
||||||
|
fmt.Println(result)
|
||||||
|
return widgetId, nil
|
||||||
|
}
|
||||||
|
19
internal/repository/widget/init.go
Normal file
19
internal/repository/widget/init.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package widget
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Pool interface {
|
||||||
|
Exec(ctx context.Context, query string, args ...interface{}) (interface{}, error)
|
||||||
|
Query(ctx context.Context, query string, args ...interface{}) (interface{}, error)
|
||||||
|
QueryRow(ctx context.Context, query string, args ...interface{}) interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Repository struct {
|
||||||
|
Pool
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(pool Pool) *Repository {
|
||||||
|
return &Repository{pool}
|
||||||
|
}
|
@ -1 +1,17 @@
|
|||||||
package widget
|
package widget
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CreatorRepository interface {
|
||||||
|
Create(ctx context.Context, userId int) (int, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (service *Service) Create(ctx context.Context, userId int) (int, error) {
|
||||||
|
widgetId, err := service.repository.Create(ctx, userId)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return widgetId, nil
|
||||||
|
}
|
||||||
|
@ -1 +1,16 @@
|
|||||||
package widget
|
package widget
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"donat-widget/infrastructure/pg"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Deleter interface {
|
||||||
|
Delete(ctx context.Context) (int, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteWidget(pool *pg.Postgres) func(ctx context.Context, repository Deleter) int {
|
||||||
|
return func(ctx context.Context, repository Deleter) int {
|
||||||
|
return 8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
19
internal/service/widget/init.go
Normal file
19
internal/service/widget/init.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package widget
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
widgetRepository "donat-widget/internal/repository/widget"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Repository interface {
|
||||||
|
Create(ctx context.Context, userId int) (int, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Service struct {
|
||||||
|
repository Repository
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(pool widgetRepository.Pool) *Service {
|
||||||
|
repository := widgetRepository.New(pool)
|
||||||
|
return &Service{repository: repository}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user