diff --git a/.gitignore b/.gitignore index 34899be..639dd42 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,12 @@ -# игнорируем содержимое ent, кроме ent/schema -ent/* -!ent/schema -!ent/schema/** - -# игнорируем маковский индекс -.DS_Store - -# игнорируем локальную конфигурацию +# локальная конфигурация .env .vscode/ +.DS_Store -# игнорируем собранное приложение -backend.run +# собранные бинарники +*.exe +service +proxy -# игнорируем отладочную информацию +# отладочная информация src/__debug_* diff --git a/Makefile b/Makefile index 6ca5d3c..cd4eea0 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -NAMESPACE ?= -PACKAGE := backend +NAMESPACE ?= proxy +PACKAGE := ollama-proxy SHELL := /bin/bash REGISTRY := registry.halfakop.ru REPOSITORY := $(NAMESPACE)/$(PACKAGE) @@ -21,6 +21,7 @@ help: @printf " make test - Run unit tests\n" @printf " make test-integration - Run tests with integration tag\n" @printf " make run - Build then run locally\n" + @printf " make dev - Run without building (go run, with env vars)\n" @printf " make clean - Clean build artifacts\n" @printf " make release - Clean, build image, login, push\n" @printf "\nVariables:\n" @@ -53,6 +54,10 @@ run: app @echo "Run application" @./${EXEC} +dev: + @echo "Run in development mode" + @OLLAMA_BACKEND=http://localhost:11434 LISTEN_ADDR=:8080 go run ./src + clean: @echo "Clean build environment" @rm -rf ./${EXEC} diff --git a/README.md b/README.md index bdcd471..d28c11c 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,64 @@ -# НАЗВАНИЕ ПРОЕКТА — Бэкэнд — Go 1.24 +# Ollama Proxy -Этот репозиторий реализует сервис, который обеспечивает: -* получение и сохранение метрик, полученных от внешней организации; -* управление параметрами экспортёров метрик и планами экспорта. +Прокси для подключения к серверу Ollama без SSH-туннелей. -## TL;DR +--- -Создание пользователя и базы для него: +## Первый раз (один раз на ноутбуке) - createuser USERNAME -P - createdb --owner USERNAME DBNAME +### 1. Клонировать репозиторий -Проверка доступа: - - psql -U USERNAME DBNAME - -Для работы миграций надо сделать так: - - psql -d DBNAME -c 'alter schema public owner to USERNAME;' - -Затем: - -```bash -# 0) Подготовьте Postgres + переменные окружения -export DATABASE_URL='postgres://USERNAME:top_secret@localhost:5432/DBNAME?sslmode=disable' - -export PATH="$PATH:$(go env GOPATH)/bin" - -# 1) Сгенерируйте код Ent по схемам (требуется один раз, при изменении схем) - Подключите ваш ORM как сабмодуль Git. - -go install entgo.io/ent/cmd/ent@latest -ent generate ./orm/ent/schema - -# 2) Примените миграции Atlas (готовые SQL в atlas/migrations) -go install ariga.io/atlas/cmd/atlas@v0.38.0 -atlas migrate apply --dir file://orm/atlas/migrations --url "$DATABASE_URL" - -# 3) Запустите сервис -go run ./cmd/server +```cmd +git clone <репозиторий> C:\ollama-proxy (диск C: как пример) +cd C:\ollama-proxy ``` + +### 2. Собрать + +```cmd +go build -o proxy.exe ./src +``` + +### 3. Создать файл `.env` рядом с `proxy.exe` + +``` +LISTEN_ADDR=localhost:11434 +OLLAMA_BACKEND=http://10.111.111.40:8080 +``` + +--- + +## Перед работой + +**Терминал 1** — запустить прокси: + +```cmd +cd C:\ollama-proxy +proxy.exe +``` + +Дождись строки: + +``` +Прокси запущен addr=localhost:11434 backend=http://10.111.111.40:8080 +``` + +**Терминал 2** — запустить Codex: + +```cmd +ollama launch codex +``` + +Работаешь. Закончил — закрыл оба терминала. + +--- + +## Проверка (если что-то не работает) + +Убедись что прокси запущен и сервер доступен: + +```cmd +curl http://localhost:11434/api/tags +``` + +Если вернулся список моделей — всё работает. diff --git a/go.mod b/go.mod index 2f11cff..bef309f 100644 --- a/go.mod +++ b/go.mod @@ -2,10 +2,4 @@ module backend go 1.24.13 -require ( - github.com/google/uuid v1.6.0 - github.com/gorilla/websocket v1.5.0 - github.com/joho/godotenv v1.5.1 - github.com/lib/pq v1.10.9 - github.com/rs/cors v1.11.1 -) +require github.com/joho/godotenv v1.5.1 diff --git a/go.sum b/go.sum index c718206..d61b19e 100644 --- a/go.sum +++ b/go.sum @@ -1,10 +1,2 @@ -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= -github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA= -github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU= diff --git a/proxy.exe b/proxy.exe new file mode 100644 index 0000000..cc11a00 Binary files /dev/null and b/proxy.exe differ diff --git a/src.exe b/src.exe new file mode 100644 index 0000000..dc7a500 Binary files /dev/null and b/src.exe differ diff --git a/src/internal/config/base.go b/src/internal/config/base.go index 200d584..199e620 100644 --- a/src/internal/config/base.go +++ b/src/internal/config/base.go @@ -13,48 +13,40 @@ import ( // LoadConfig загружает конфиг из .env (если есть) и окружения. func LoadConfig(logger *slog.Logger) (*Config, error) { - _ = godotenv.Load() // необязательно фейлиться, если файла нет + _ = godotenv.Load() cfg := &Config{} - cfg.Timezone = GetEnvAs("TIMEZONE", "UTC", ParseString) - cfg.ServiceURL = GetEnvAs("SERVICE_URL", "http://localhost:8080", ParseString) + cfg.ListenAddr = GetEnvAs("LISTEN_ADDR", ":8080", ParseString) + cfg.BackendURL = GetEnvAs("OLLAMA_BACKEND", "http://localhost:11434", ParseString) cfg.LoggingConfig.Instance = logger cfg.LoggingConfig.Level = GetEnvAs("LOG_LEVEL", "info", ParseString) cfg.LoggingConfig.ShowCfgDump = GetEnvAs("LOG_SHOW_DUMP", false, ParseBool) - cfg.DatabaseConfig = FillDatabaseConfig() - if cfg.LoggingConfig.ShowCfgDump { cfg.Print() } return cfg, nil } -// PrintConfig выводит конфигурацию (или любой другой struct) в виде таблички "KEY - VALUE". -// Функция использует рефлексию для перебора полей структуры. +// Print выводит конфигурацию в виде таблички "KEY - VALUE". func (c *Config) Print() { - w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) fmt.Fprintln(w, "Loaded configuration:") fmt.Fprintln(w, "KEY\tVALUE") fmt.Fprintln(w, "----\t-----") - // Получаем reflect.Value объекта. v := reflect.ValueOf(c) - // Если передан указатель, получаем значение, на которое он указывает. if v.Kind() == reflect.Ptr { v = v.Elem() } t := v.Type() - // Перебираем все поля структуры. for i := 0; i < v.NumField(); i++ { fieldName := t.Field(i).Name fieldValue := v.Field(i).Interface() - // Если поле имеет тип time.Duration, выводим его в виде строки. if d, ok := fieldValue.(time.Duration); ok { fieldValue = d.String() } diff --git a/src/internal/config/database.go b/src/internal/config/database.go deleted file mode 100644 index f86dddc..0000000 --- a/src/internal/config/database.go +++ /dev/null @@ -1,113 +0,0 @@ -package config - -import ( - "fmt" - "net/url" - "time" -) - -type DatabaseConfig struct { - URL string - Kind string - Host string - Port string - User string - Password string - Name string - UseTLS bool - Timeout time.Duration -} - -func FillDatabaseConfig() DatabaseConfig { - databaseURL := GetEnvAs("DATABASE_URL", "", ParseString) - - if databaseURL == "" { - return DatabaseConfig{} - } - - u, err := url.Parse(databaseURL) - if err != nil { - return DatabaseConfig{} - } - - kind := "postgres" - if u.Scheme == "postgresql" { - kind = "postgres" - } else if u.Scheme != "" { - kind = u.Scheme - } - - dbName := "" - if len(u.Path) > 1 { - dbName = u.Path[1:] - } - - return DatabaseConfig{ - URL: databaseURL, - Kind: kind, - Host: u.Hostname(), - Port: u.Port(), - User: u.User.Username(), - Password: func() string { - password, _ := u.User.Password() - return password - }(), - Name: dbName, - UseTLS: GetEnvAs("DATABASE_USETLS", false, ParseBool), - Timeout: GetEnvAs("DATABASE_TIMEOUT", 30*time.Second, ParseDuration), - } -} - -// GetDatabaseURLForLogging возвращает URL базы данных для логирования, скрывая пароль. -func GetDatabaseURLForLogging(cfg *DatabaseConfig) (string, error) { - if cfg.URL == "" { - return "", fmt.Errorf("parameter DATABASE_URL is empty") - } - - u, err := url.Parse(cfg.URL) - if err == nil { - if u.User != nil { - username := u.User.Username() - s := u.Scheme + "://" + username + ":***@" + u.Host - if u.Path != "" { - s += u.Path - } - if u.RawQuery != "" { - s += "?" + u.RawQuery - } - return s, err - } - } - return u.String(), err -} - -func GetDatabaseDSN(cfg *DatabaseConfig) (string, error) { - if cfg.URL == "" { - return "", fmt.Errorf("parameter DATABASE_URL is empty") - } - - u, err := url.Parse(cfg.URL) - if err == nil { - query := u.Query() - if !cfg.UseTLS { - query.Set("sslmode", "disable") - } else if query.Get("sslmode") == "" { - query.Set("sslmode", "require") - } - u.RawQuery = query.Encode() - return u.String(), err - } - - dsn := fmt.Sprintf( - "host=%s port=%s user=%s password=%s dbname=%s", - cfg.Host, cfg.Port, cfg.User, cfg.Password, cfg.Name, - ) - - if !cfg.UseTLS { - dsn += " sslmode=disable" - } else { - dsn += " sslmode=require" - } - - return dsn, nil -} diff --git a/src/internal/config/interface.go b/src/internal/config/interface.go index 64ca0a0..c186885 100644 --- a/src/internal/config/interface.go +++ b/src/internal/config/interface.go @@ -9,9 +9,8 @@ type LoggingConfig struct { } type Config struct { - Timezone string - ServiceURL string + ListenAddr string // env: LISTEN_ADDR, по умолчанию ":8080" + BackendURL string // env: OLLAMA_BACKEND, по умолчанию "http://localhost:11434" LoggingConfig - DatabaseConfig } diff --git a/src/internal/gateway/handler.go b/src/internal/gateway/handler.go deleted file mode 100644 index 6e55af7..0000000 --- a/src/internal/gateway/handler.go +++ /dev/null @@ -1,134 +0,0 @@ -package gateway - -import ( - "backend/src/internal/config" - "backend/src/logic" - "backend/src/models" - "context" - "encoding/json" - "log" - "net/http" - "sync" - - "github.com/google/uuid" - "github.com/gorilla/websocket" -) - -// глобальный хаб соединений WebSocket -var hub sync.Map - -// Настройки для обновления соединения до WebSocket -var upgrader = websocket.Upgrader{ - // разрешаем соединения с любых источников - // (для продакшена стоит ограничить) - CheckOrigin: func(r *http.Request) bool { - return true - }, -} - -// WebSocketHubResponse отправляет ответ отдельному приложению -func WebSocketHubResponse(packet models.ClientPacket) { - cid := packet.ClientID - msg := packet.Payload - value, ok := hub.Load(cid) - if ok { - conn := value.(*websocket.Conn) - log.Printf("[WS] Sending message: %s", msg) - if err := conn.WriteMessage(websocket.TextMessage, msg); err != nil { - log.Printf("[WS] Send error: %v", err) - } - } else { - log.Printf("[WS] Client <%s> unknown, skipping sending...", cid) - } -} - -// Worker обрабатывает канал подписки и отправляет результат в WebSocket -func Worker(ch models.ChannelOut) { - log.Printf("[WS] Response worker is ready") - for packet := range ch { - WebSocketHubResponse(packet) - } -} - -// Обработчик для WebSocket соединения -func WebSocketHandler(ctx context.Context, cfg *config.Config, - w http.ResponseWriter, r *http.Request, bl *logic.Business) { - logger := cfg.LoggingConfig.Instance - - conn, err := upgrader.Upgrade(w, r, nil) - if err != nil { - logger.Error("[WS] Unable to restart connection", "error", err) - return - } - defer conn.Close() - - // рассчитываем, что клиент присылает свой идентификатор, иначе создаём - cid := r.URL.Query().Get("cid") - if cid == "" { - cid = uuid.New().String() // FIXME: или сбрасывать соединение - } - - // сохраняем соединение с клиентом в хабе - hub.Store(cid, conn) - logger.Info("[WS] Remote <%s> connected: %s", cid, conn.RemoteAddr()) - - // создаём канал для ответов в вебсокет - wsResponseChannel := make(chan models.ClientPacket, 10000) - - // Запускаем горутину, которая будет получать сообщения из канала и отправлять их клиенту. - go Worker(wsResponseChannel) - - // начинаем обработку сообщений от веб приложения - for { - messageType, message, err := conn.ReadMessage() - if err != nil { - logger.Info("[WS] Remote <%s> disconnected: %v:", cid, err) - hub.Delete(cid) - break - } - - // получаем общие поля - var commonFields models.BaseFieldT - if err := json.Unmarshal(message, &commonFields); err != nil { - log.Println("[WS] Unable unmarshal common fields:", err) - continue - } - // определяем тип сообщения - switch commonFields.Action { - case "COMMAND1": - logger.Info("[WS] COMMAND1 requested!") - /* - var request models.CoordinatorConfigurationRequestT - if err := json.Unmarshal(message, &request); err != nil { - logger.Error("[WS] Unable unmarshal CoordinatorConfigurationRequestT") - continue - } - - payload, err := bl.GetCoordinatorConfiguration(request.OrganizationID) - - var packet models.CoordinatorConfigurationResponseT - if err != nil { - packet = models.CoordinatorConfigurationResponseT{ - BaseFieldT: commonFields, - Status: 200, - Payload: *payload, - } - } else { - packet = models.CoordinatorConfigurationResponseT{ - BaseFieldT: commonFields, - Status: 400, - Payload: models.CoordinatorConfigurationT{}, - } - } - data, _ := json.Marshal(packet) - wsResponseChannel <- models.ClientPacket{ClientID: cid, Payload: data} - */ - default: - if messageType == websocket.TextMessage { - log.Printf("[WS] Got text message: %s", string(message)) - } else { - log.Printf("[WS] Got unknown message: %d", messageType) - } - } - } -} diff --git a/src/internal/gateway/ws_queue.go b/src/internal/gateway/ws_queue.go deleted file mode 100644 index 91c63f1..0000000 --- a/src/internal/gateway/ws_queue.go +++ /dev/null @@ -1,65 +0,0 @@ -package gateway - -import ( - "context" - "log" - - "github.com/gorilla/websocket" -) - -// ClientPacket используется для передачи пакетов через Go каналы -type ClientPacket struct { - ClientID string - Payload []byte -} - -type ChannelIn chan<- ClientPacket -type ChannelOut <-chan ClientPacket - -type WebSocketQueue struct { - ctx context.Context - ch chan ClientPacket -} - -func NewWebSocketQueue(ctx context.Context) *WebSocketQueue { - q := WebSocketQueue{ - ctx: ctx, - ch: make(chan ClientPacket, 10000), - } - - // Запускаем горутину, которая будет получать сообщения из канала - // и отправлять их клиенту. - go q.runWorker() - return &q -} - -// runWorker обрабатывает канал подписк и отправляет результат в WebSocket -func (q *WebSocketQueue) runWorker() { - // создаём канал для ответов в вебсокет - log.Printf("[WS] Response worker is ready") - for packet := range q.ch { - q.realSend(packet) - } -} - -// Send на самом деле помещает пакет в очередь отправки, которая затем -// разгребается с помощью WorkerOfQueuedResponsesToWS. -func (q *WebSocketQueue) Send(packet ClientPacket) { - q.ch <- packet -} - -// WebSocketHubResponse отправляет ответ отдельному приложению -func (q *WebSocketQueue) realSend(packet ClientPacket) { - cid := packet.ClientID - msg := packet.Payload - value, ok := hub.Load(cid) - if ok { - conn := value.(*websocket.Conn) - log.Printf("[WS] Sending message: %s", msg) - if err := conn.WriteMessage(websocket.TextMessage, msg); err != nil { - log.Printf("[WS] Send error: %v", err) - } - } else { - log.Printf("[WS] Client <%s> unknown, skipping sending...", cid) - } -} diff --git a/src/internal/logging/logging.go b/src/internal/logging/logging.go index a29bd39..a531cc9 100644 --- a/src/internal/logging/logging.go +++ b/src/internal/logging/logging.go @@ -6,12 +6,11 @@ import ( "strings" ) -// New creates a slog logger with the provided level string (e.g., "debug", "info"). func New(level string) *slog.Logger { return slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: ParseLevel(level)})) } -// ParseLevel converts a string level to slog.Level, defaults to info on unknown. + func ParseLevel(lvl string) slog.Level { switch strings.ToLower(lvl) { case "debug": diff --git a/src/logic/business.go b/src/logic/business.go deleted file mode 100644 index 695f647..0000000 --- a/src/logic/business.go +++ /dev/null @@ -1,18 +0,0 @@ -package logic - -import ( - "backend/ent" - "context" -) - -type Business struct { - ctx context.Context - db *ent.Client -} - -func NewBusinessLogic(ctx context.Context, client *ent.Client) *Business { - return &Business{ - ctx: ctx, - db: client, - } -} diff --git a/src/main.go b/src/main.go index 57beb2d..c3e0040 100644 --- a/src/main.go +++ b/src/main.go @@ -1,110 +1,86 @@ package main import ( - "context" "fmt" "log/slog" "net/http" + "net/http/httputil" "net/url" - "strings" + "time" - "backend/ent" "backend/src/internal/config" - "backend/src/internal/gateway" "backend/src/internal/logging" - "backend/src/logic" - - _ "github.com/lib/pq" // побочный импорт драйвера PostgreSQL - "github.com/rs/cors" ) const ( - AppName = "Backend" + AppName = "Ollama Proxy" AppVersion = "1.0.0" ) func main() { - var err error logger := logging.New("info") slog.SetDefault(logger) - - logger.Info(fmt.Sprintf("Starting %s version %s\n", AppName, AppVersion)) + logger.Info(fmt.Sprintf("Starting %s version %s", AppName, AppVersion)) cfg, err := config.LoadConfig(logger) if err != nil { - logger.Error("Configuration loading error", "error", err) + logger.Error("Ошибка конфигурации", "error", err) return } - // adjust logger according to LOG_LEVEL level := logging.ParseLevel(cfg.LoggingConfig.Level) if level != slog.LevelInfo { - logger.Info("Adjusting log level from env", "level", level.String()) + logger.Info("Уровень логирования из env", "level", level.String()) } logger = logging.New(cfg.LoggingConfig.Level) slog.SetDefault(logger) cfg.LoggingConfig.Instance = logger - // создаем контекст с отменой для управления жизненным циклом сервиса. - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - // подключаемся к базе данных - dbURL, err := config.GetDatabaseURLForLogging(&cfg.DatabaseConfig) + target, err := url.Parse(cfg.BackendURL) if err != nil { - logger.Error("Failed getting database URL for logging", "error", err) - return - } - logger.Info("Connecting to database...", "url", dbURL) - - dsn, err := config.GetDatabaseDSN(&cfg.DatabaseConfig) - if err != nil { - logger.Error("Failed getting database DSN", "error", err) - return - } - db, err := ent.Open(cfg.DatabaseConfig.Kind, dsn) - if err != nil { - logger.Error("Failed opening connection to postgres", "error", err) - return - } - defer db.Close() - - // Применяем миграции - if err := db.Schema.Create(ctx); err != nil { - logger.Error("Failed creating schema resources", "error", err) + logger.Error("Неверный URL бэкенда", "error", err) return } - // инициализируем бизнес логику - business := logic.NewBusinessLogic(ctx, db) - - // регистрируем обработчик WebSocket по адресу /ws - http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) { - gateway.WebSocketHandler(ctx, cfg, w, r, business) - }) - - // создаём CORS middleware - corsMiddleware := cors.New(cors.Options{ - AllowedOrigins: []string{"http://localhost:4200"}, - AllowedMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"}, - AllowedHeaders: []string{"Content-Type", "Authorization"}, - AllowCredentials: true, - }) - - // оборачиваем стандартный mux (DefaultServeMux) - handler := corsMiddleware.Handler(http.DefaultServeMux) - - // адрес сервера должен быть без схемы - clearURL := cfg.ServiceURL - if strings.Contains(clearURL, "://") { - if u, err := url.Parse(clearURL); err == nil && u.Host != "" { - clearURL = u.Host - } + proxy := &httputil.ReverseProxy{ + Rewrite: func(r *httputil.ProxyRequest) { + r.SetURL(target) + r.Out.Host = target.Host + }, + ErrorHandler: func(w http.ResponseWriter, r *http.Request, err error) { + logger.Error("Ошибка прокси", "method", r.Method, "path", r.URL.Path, "error", err) + http.Error(w, "Bad Gateway", http.StatusBadGateway) + }, } - logger.Info("WebSocket server is on", cfg.ServiceURL) - if err := http.ListenAndServe(clearURL, handler); err != nil { - logger.Error("WebSocket server is unable to start", "error", err) - return + handler := loggingMiddleware(logger, proxy) + + logger.Info("Прокси запущен", "addr", cfg.ListenAddr, "backend", cfg.BackendURL) + if err := http.ListenAndServe(cfg.ListenAddr, handler); err != nil { + logger.Error("Ошибка сервера", "error", err) } } + +func loggingMiddleware(logger *slog.Logger, next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + start := time.Now() + rw := &responseWriter{ResponseWriter: w, status: http.StatusOK} + next.ServeHTTP(rw, r) + logger.Info("запрос", + "method", r.Method, + "path", r.URL.Path, + "status", rw.status, + "duration", time.Since(start).String(), + ) + }) +} + +type responseWriter struct { + http.ResponseWriter + status int +} + +func (rw *responseWriter) WriteHeader(code int) { + rw.status = code + rw.ResponseWriter.WriteHeader(code) +} diff --git a/src/models/base.go b/src/models/base.go deleted file mode 100644 index 2c2ea32..0000000 --- a/src/models/base.go +++ /dev/null @@ -1,7 +0,0 @@ -package models - -type BaseFieldT struct { - TaskID int `json:"taskId" binding:"required"` - Kind string `json:"kind" binding:"required"` - Action string `json:"action" binding:"required"` -} diff --git a/src/models/packets.go b/src/models/packets.go deleted file mode 100644 index a46bbb2..0000000 --- a/src/models/packets.go +++ /dev/null @@ -1,27 +0,0 @@ -package models - -import "github.com/google/uuid" - -// ClientPacket используется для передачи пакетов через Go каналы -type ClientPacket struct { - ClientID string - Payload []byte -} - -// ClientRequest используется для передачи запросов от клиента -type ClientRequest struct { - TaskID uuid.UUID `json:"taskId" binding:"required"` - Kind string `json:"kind" binding:"required"` - Action string `json:"action" binding:"required"` -} - -// ClientResponse используется для передачи ответов клиенту -type ClientResponse struct { - ClientRequest - Status int `json:"status" binding:"required"` - Message string `json:"message,omitempty"` - Payload any `json:"payload,omitempty"` -} - -type ChannelIn chan<- ClientPacket -type ChannelOut <-chan ClientPacket