From f6521b9332c0c423a08fb8e9da37abe2a84392fb Mon Sep 17 00:00:00 2001 From: Michael Makarochkin Date: Fri, 28 Feb 2025 02:47:17 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B0=20=D1=81=D1=80=D0=B5=D0=B4=D0=B0=20=D1=80=D0=B0?= =?UTF-8?q?=D0=B7=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B8=20=D0=B8=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=20=D0=BD=D0=BE?= =?UTF-8?q?=D0=B2=D1=8B=D0=B9=20=D1=84=D1=83=D0=BD=D0=BA=D1=86=D0=B8=D0=BE?= =?UTF-8?q?=D0=BD=D0=B0=D0=BB=20=D0=B2=20=D1=81=D0=B5=D1=80=D0=B2=D0=B5?= =?UTF-8?q?=D1=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Улучшена среда разработки, поправлены косяки старта дебагера - Добавлен логер в приложение - Добавлен cli framework --- application/.gitignore | 1 - application/go.mod | 3 -- application/main.go | 23 --------- docker-compose.yml | 4 +- pink_fox_app/.gitignore | 2 + pink_fox_app/go.mod | 11 +++++ pink_fox_app/go.sum | 13 +++++ pink_fox_app/internal/app/cmd/cmd.go | 47 ++++++++++++++++++ pink_fox_app/internal/app/cmd/server.go | 57 ++++++++++++++++++++++ pink_fox_app/internal/app/config/config.go | 41 ++++++++++++++++ pink_fox_app/internal/app/db/db.go | 30 ++++++++++++ pink_fox_app/internal/app/log/log.go | 30 ++++++++++++ pink_fox_app/internal/app/timer/timer.go | 3 ++ pink_fox_app/main.go | 15 ++++++ services/site/build.sh | 31 ++++++------ services/site/rerun.py | 32 +++++++----- 16 files changed, 289 insertions(+), 54 deletions(-) delete mode 100644 application/.gitignore delete mode 100644 application/go.mod delete mode 100644 application/main.go create mode 100644 pink_fox_app/.gitignore create mode 100644 pink_fox_app/go.mod create mode 100644 pink_fox_app/go.sum create mode 100644 pink_fox_app/internal/app/cmd/cmd.go create mode 100644 pink_fox_app/internal/app/cmd/server.go create mode 100644 pink_fox_app/internal/app/config/config.go create mode 100644 pink_fox_app/internal/app/db/db.go create mode 100644 pink_fox_app/internal/app/log/log.go create mode 100644 pink_fox_app/internal/app/timer/timer.go create mode 100644 pink_fox_app/main.go diff --git a/application/.gitignore b/application/.gitignore deleted file mode 100644 index a52d155..0000000 --- a/application/.gitignore +++ /dev/null @@ -1 +0,0 @@ -out.log \ No newline at end of file diff --git a/application/go.mod b/application/go.mod deleted file mode 100644 index 7e570ea..0000000 --- a/application/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module pink_fox - -go 1.24.0 diff --git a/application/main.go b/application/main.go deleted file mode 100644 index 5e2ce32..0000000 --- a/application/main.go +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "fmt" - "net/http" - "os" -) - -func main() { - http.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) { - _, _ = fmt.Fprintf(w, "ok") - }) - - http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - _, _ = fmt.Fprintf(w, "Hello world!") - }) - - fmt.Println("Starting server at port 12001...") - if err := http.ListenAndServe(":12001", nil); err != nil { - fmt.Println(err) - os.Exit(1) - } -} diff --git a/docker-compose.yml b/docker-compose.yml index f780eac..bdc9080 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,8 +9,8 @@ services: - "12001:12001" - "12002:2345" volumes: - - ./application:/app - - ./dist:/app/dist + - ./pink_fox_app:/app + - ./dist:/dist - ./environment:/var/environment/pink_fox - ./log:/var/log/pink_fox - ./.storage/go:/go diff --git a/pink_fox_app/.gitignore b/pink_fox_app/.gitignore new file mode 100644 index 0000000..d14b42a --- /dev/null +++ b/pink_fox_app/.gitignore @@ -0,0 +1,2 @@ +out.log +err.log \ No newline at end of file diff --git a/pink_fox_app/go.mod b/pink_fox_app/go.mod new file mode 100644 index 0000000..25c8d67 --- /dev/null +++ b/pink_fox_app/go.mod @@ -0,0 +1,11 @@ +module pink_fox + +go 1.24.0 + +require ( + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/lib/pq v1.10.9 // indirect + github.com/spf13/cobra v1.9.1 // indirect + github.com/spf13/pflag v1.0.6 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/pink_fox_app/go.sum b/pink_fox_app/go.sum new file mode 100644 index 0000000..b4c5b03 --- /dev/null +++ b/pink_fox_app/go.sum @@ -0,0 +1,13 @@ +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= +github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= +github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= +github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pink_fox_app/internal/app/cmd/cmd.go b/pink_fox_app/internal/app/cmd/cmd.go new file mode 100644 index 0000000..beb8a23 --- /dev/null +++ b/pink_fox_app/internal/app/cmd/cmd.go @@ -0,0 +1,47 @@ +package cmd + +import ( + "fmt" + "github.com/spf13/cobra" + "os" +) + +var ( + port = 12001 + config = "/var/environment/pink_fox/config.yml" + + rootCmd = &cobra.Command{ + Use: "pink_fox", + Short: "Розовый лис\nСквозь ссылок паутину —\nСвет в ночи горит.", + } + + serverCmd = &cobra.Command{ + Use: "server", + Short: "Запуск сервера", + Run: func(cmd *cobra.Command, args []string) { + err := NewServer().Execute(config, port) + if err != nil { + exit(err) + } + }, + } +) + +func init() { + serverCmd.Flags().IntVarP(&port, "port", "p", port, "Порт доступ к приложению") + serverCmd.Flags().StringVarP(&config, "config", "c", config, "Путь к файлу конфигурации") + + rootCmd.AddCommand(serverCmd) +} + +func Execute() error { + if err := rootCmd.Execute(); err != nil { + return fmt.Errorf("cmd: %s", err) + } + return nil +} + +func exit(err error) { + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) +} diff --git a/pink_fox_app/internal/app/cmd/server.go b/pink_fox_app/internal/app/cmd/server.go new file mode 100644 index 0000000..dc907d6 --- /dev/null +++ b/pink_fox_app/internal/app/cmd/server.go @@ -0,0 +1,57 @@ +package cmd + +import ( + "database/sql" + "fmt" + "net/http" + conf2 "pink_fox/internal/app/config" + "pink_fox/internal/app/db" + "pink_fox/internal/app/log" +) + +type Server struct { +} + +func NewServer() *Server { + return &Server{} +} + +func (it *Server) Execute(defaultConfig string, defaultPort int) error { + conf, err := conf2.LoadConfig(defaultConfig, defaultPort) + if err != nil { + exit(err) + } + + conn, err := db.CreateConnection(&conf.Db) + if err != nil { + exit(err) + } + defer func(conn *sql.DB) { + _ = conn.Close() + }(conn) + + logger, err := log.NewLogger(conf.LogFile) + if err != nil { + exit(err) + } + defer func(logger *log.Logger) { + _ = logger.Close() + }(logger) + + // TODO доделать + + http.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) { + _, _ = fmt.Fprintf(w, "ok") + }) + + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + _, _ = fmt.Fprintf(w, "Hello world!") + }) + + fmt.Printf("Starting server at port %d...", conf.Port) + if err = http.ListenAndServe(fmt.Sprintf(":%d", conf.Port), nil); err != nil { + return err + } + + return nil +} diff --git a/pink_fox_app/internal/app/config/config.go b/pink_fox_app/internal/app/config/config.go new file mode 100644 index 0000000..e02542e --- /dev/null +++ b/pink_fox_app/internal/app/config/config.go @@ -0,0 +1,41 @@ +package config + +import ( + "fmt" + "gopkg.in/yaml.v3" + "os" +) + +type DB struct { + Host string `yaml:"host"` + User string `yaml:"user"` + Password string `yaml:"password"` + Port string `yaml:"port"` + Database string `yaml:"database"` +} + +type Config struct { + Port int `yaml:"port"` + Db DB `yaml:"db"` + LogFile string `yaml:"logFile"` +} + +func LoadConfig(defaultConfig string, defaultPort int) (*Config, error) { + data, err := os.ReadFile(defaultConfig) + if err != nil { + return nil, fmt.Errorf("ошибка чтения файла конфига: %s", err) + } + var config Config + err = yaml.Unmarshal(data, &config) + if err != nil { + return nil, fmt.Errorf("не получилось распарсить конфиг: %s", err) + } + return setDefaultValue(&config, defaultPort), nil +} + +func setDefaultValue(config *Config, defaultPort int) *Config { + if config.Port == 0 { + config.Port = defaultPort + } + return config +} diff --git a/pink_fox_app/internal/app/db/db.go b/pink_fox_app/internal/app/db/db.go new file mode 100644 index 0000000..9f1ecee --- /dev/null +++ b/pink_fox_app/internal/app/db/db.go @@ -0,0 +1,30 @@ +package db + +import ( + "database/sql" + "fmt" + _ "github.com/lib/pq" + "pink_fox/internal/app/config" + "time" +) + +func CreateConnection(dbConf *config.DB) (*sql.DB, error) { + psqlInfo := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable", + dbConf.Host, dbConf.Port, dbConf.User, dbConf.Password, dbConf.Database) + + var err error + var db *sql.DB + + for i := 0; i < 10; i++ { + db, err = sql.Open("postgres", psqlInfo) + if err == nil { + err = db.Ping() + if err == nil { + return db, nil + } + } + time.Sleep(200 * time.Millisecond) + } + + return nil, fmt.Errorf("не удалось подключиться к базе данных: %v", err) +} diff --git a/pink_fox_app/internal/app/log/log.go b/pink_fox_app/internal/app/log/log.go new file mode 100644 index 0000000..b880bbf --- /dev/null +++ b/pink_fox_app/internal/app/log/log.go @@ -0,0 +1,30 @@ +package log + +import ( + "fmt" + "log/slog" + "os" +) + +type Logger struct { + file *os.File + Logger *slog.Logger +} + +func NewLogger(path string) (*Logger, error) { + file, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) + if err != nil { + return nil, fmt.Errorf("не удалось открыть файл лога: %s", err) + } + + logger := slog.New(slog.NewTextHandler(file, nil)) + + return &Logger{ + file: file, + Logger: logger, + }, nil +} + +func (it *Logger) Close() error { + return it.file.Close() +} diff --git a/pink_fox_app/internal/app/timer/timer.go b/pink_fox_app/internal/app/timer/timer.go new file mode 100644 index 0000000..2193db2 --- /dev/null +++ b/pink_fox_app/internal/app/timer/timer.go @@ -0,0 +1,3 @@ +package timer + +// TODO diff --git a/pink_fox_app/main.go b/pink_fox_app/main.go new file mode 100644 index 0000000..c0a5a50 --- /dev/null +++ b/pink_fox_app/main.go @@ -0,0 +1,15 @@ +package main + +import ( + "fmt" + "os" + "pink_fox/internal/app/cmd" +) + +func main() { + err := cmd.Execute() + if err != nil { + _, _ = fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } +} diff --git a/services/site/build.sh b/services/site/build.sh index af020aa..29689b4 100755 --- a/services/site/build.sh +++ b/services/site/build.sh @@ -14,29 +14,32 @@ if [[ ! -d "/go/bin" ]]; then fi if [ "$ARG1" = "debug" ]; then - # Приложение готовое для дебага + # Собираем приложение для дебага cd /app || exit 1 - rm -f "./dist/local_app_name" - echo "" > out.log + rm -f "/dist/local_app_name" + echo "" > /app/out.log + echo "" > /app/err.log + echo "" > /app/dlv.log - pkill -f /app/dist/local_app_name + pkill -f /dist/local_app_name - go build -gcflags "all=-N -l" -o ./dist/local_app_name 2> /app/out.log + go build -gcflags "all=-N -l" -o /dist/local_app_name > /app/out.log 2> /app/err.log - if [ ! -s "/app/out.log" ]; then - dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec /app/dist/local_app_name > /app/out.log 2>&1 + if [ ! -s "/app/err.log" ]; then + dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec /dist/local_app_name server > /app/out.log 2> /app/dlv.log fi else - # Простое приложение + # Собираем приложение cd /app || exit 1 - rm -f "./dist/local_app_name" - echo "" > out.log + rm -f "/dist/local_app_name" + echo "" > /app/out.log + echo "" > /app/err.log - pkill -f /app/dist/local_app_name + pkill -f /dist/local_app_name - go build -o "./dist/local_app_name" 2> /app/out.log + go build -o "/dist/local_app_name" > /app/out.log 2> /app/err.log - if [ ! -s "/app/out.log" ]; then - /app/dist/local_app_name > /app/out.log 2>&1 + if [ ! -s "/app/err.log" ]; then + /dist/local_app_name server > /app/out.log 2> /app/err.log fi fi diff --git a/services/site/rerun.py b/services/site/rerun.py index 91d0d10..41601c6 100755 --- a/services/site/rerun.py +++ b/services/site/rerun.py @@ -6,6 +6,10 @@ import subprocess import sys import os +file_out = "out.log" +file_err = "err.log" +url_ping = "http://localhost:12001/ping" + # Останавливаем контейнер без задержки subprocess.run(["docker", "compose", "stop", "site", "-t", "0"]) @@ -22,30 +26,36 @@ attempt_count = 0 while True: try: # Отправляем запрос для проверки поднялся ли HTTP сервер - response = requests.get("http://localhost:12001/ping", timeout=5) - - # Проверяем ответ + response = requests.get(url_ping, timeout=5) if response.status_code == 200: print("Сервер запущен") break except requests.ConnectionError: + # смотрим есть ли ошибки в err.log try: - with open("out.log", 'r') as file: + with open(file_err, 'r') as ferr: + err_content = ferr.read().strip() + if err_content: + print("Имеется ошибка компиляции или запуска, смотри файл " + file_err) + exit(1) + except FileNotFoundError: + print("Лог файл" + file_err + " не найден, проверьте путь") + print("Текущая директория" + os.getcwd()) + + # смотрим есть ли запись о старте дебагера + try: + with open(file_out, 'r') as file: content = file.read().strip() if content: - # Лог файл не пуст, возможно, есть ошибки сборки + # Лог файл не пуст, возможно запущен дебагер и ping дожидаться не стоит if content.startswith("API server listening at: [::]:2345"): # Лог файл начинается с сообщения о старте дебагера, ошибок нет break - else: - print("Имеется ошибка компиляции, смотри файл out.log") - exit(1) - except FileNotFoundError: - print("Лог файл не найден, проверьте путь") + print("Лог файл " + file_out + " не найден, проверьте путь") print("Текущая директория" + os.getcwd()) - # Если не удалось подключиться, увеличиваем счетчик попыток + # Если не удалось подключиться или не обнаружен старт дебагера то увеличиваем счетчик попыток attempt_count += 1 print(f"Ждем... ({attempt_count})")