From 1001bb813ad44a8e418048d3c3485f25c2b8bba1 Mon Sep 17 00:00:00 2001 From: vitaliy Date: Wed, 18 Jun 2025 00:00:08 +0300 Subject: [PATCH] new: microservice --- code/go/agent_code/code.json | 15 ++ code/go/agent_code/py_agent.go | 165 ++++++++++++++++++ code/go/front_code/front.go | 85 +++++++++ code/go/front_code/templates/index.html | 63 +++++++ .../rabbit.go => rest_code/rest_server.go} | 26 ++- 5 files changed, 347 insertions(+), 7 deletions(-) create mode 100644 code/go/agent_code/code.json create mode 100644 code/go/agent_code/py_agent.go create mode 100644 code/go/front_code/front.go create mode 100644 code/go/front_code/templates/index.html rename code/go/{mq/rabbit.go => rest_code/rest_server.go} (83%) diff --git a/code/go/agent_code/code.json b/code/go/agent_code/code.json new file mode 100644 index 0000000..bd63b56 --- /dev/null +++ b/code/go/agent_code/code.json @@ -0,0 +1,15 @@ +{ + "id_task": "01975b05-647e-7ed5-abdd-f412a8a4882b", + "tp_runner": "python", + "code": "CmRlZiBoZWxsb193b3JsZCgpOgogICAgcHJpbnQoIkhlbGxvLCBXb3JsZCEiKQogICAg", + "test": "CmltcG9ydCB1bml0dGVzdAppbXBvcnQgaW8KaW1wb3J0IHN5cwpmcm9tIGNvbnRleHRsaWIgaW1wb3J0IHJlZGlyZWN0X3N0ZG91dApmcm9tIG1haW4gaW1wb3J0IGhlbGxvX3dvcmxkCgpjbGFzcyBUZXN0SGVsbG9Xb3JsZCh1bml0dGVzdC5UZXN0Q2FzZSk6CgogICAgZGVmIHRlc3RfaGVsbG9fd29ybGRfb3V0cHV0KHNlbGYpOgogICAgICAgICIiIgogICAgICAgIFRlc3QgdGhhdCBoZWxsb193b3JsZCgpIHByaW50cyAiSGVsbG8sIFdvcmxkISIgdG8gc3Rkb3V0LgogICAgICAgICIiIgogICAgICAgIGYgPSBpby5TdHJpbmdJTygpCiAgICAgICAgd2l0aCByZWRpcmVjdF9zdGRvdXQoZik6CiAgICAgICAgICAgIGhlbGxvX3dvcmxkKCkKICAgICAgICBzZWxmLmFzc2VydEVxdWFsKGYuZ2V0dmFsdWUoKSwgIkhlbGxvLCBXb3JsZCFcbiIpCgppZiBfX25hbWVfXyA9PSAnX19tYWluX18nOgogICAgdW5pdHRlc3QubWFpbigpCiAgICA=" +} + + +10 000 per sec +Redis 120G +key - 01975b05-647e-7ed5-abdd-f412a8a4882b +value - json + +10 000 +PostgreSQL \ No newline at end of file diff --git a/code/go/agent_code/py_agent.go b/code/go/agent_code/py_agent.go new file mode 100644 index 0000000..01454e1 --- /dev/null +++ b/code/go/agent_code/py_agent.go @@ -0,0 +1,165 @@ +package main + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "log" + "os" + "os/exec" + + "github.com/streadway/amqp" +) + +func main() { + + type Code struct { + IDTask string `json:"id_task"` + TpRunner string `json:"tp_runner"` + Code string `json:"code"` + Test string `json:"test"` + } + + // Define RabbitMQ server URL. + amqpServerURL := os.Getenv("AMQP_SERVER_URL") + if amqpServerURL == "" { + amqpServerURL = "amqp://guest:guest@localhost:5672/" // Default URL if not set + } + + // Create a new RabbitMQ connection. + connectRabbitMQ, err := amqp.Dial(amqpServerURL) + if err != nil { + panic(err) + } + defer connectRabbitMQ.Close() + + // Opening a channel to our RabbitMQ instance over + // the connection we have already established. + channelRabbitMQ, err := connectRabbitMQ.Channel() + if err != nil { + panic(err) + } + defer channelRabbitMQ.Close() + + // Subscribing to QueueService1 for getting messages. + messages, err := channelRabbitMQ.Consume( + "QueueService1", // queue name + "", // consumer + true, // auto-ack + false, // exclusive + false, // no local + false, // no wait + nil, // arguments + ) + if err != nil { + log.Println(err) + } + + // Build a welcome message. + log.Println("Successfully connected to RabbitMQ") + log.Println("Waiting for messages") + + // Make a channel to receive messages into infinite loop. + forever := make(chan bool) + + go func() { + for message := range messages { + // For example, show received message in a console. + log.Printf(" > Received message: %s\n", message.Body) + // Создание экземпляра структуры Task + + var code_obj Code + + // Разбор JSON строки в структуру + err := json.Unmarshal([]byte(message.Body), &code_obj) + if err != nil { + log.Fatalf("Ошибка при разборе JSON: %v", err) + } + mkdir(code_obj.IDTask) + mkfile(code_obj.IDTask, code_obj.Code, "main.py") + mkfile(code_obj.IDTask, code_obj.Test, "test_hello.py") + run(code_obj.IDTask) + + fmt.Println(code_obj.Code) + + } + }() + + <-forever +} + +func mkdir(dirName string) { + // Имя директории, которую нужно создать + + // Права доступа к директории (0755 - чтение, запись, выполнение для владельца, чтение и выполнение для группы и остальных) + permissions := os.ModeDir | 0755 + + // Создание директории + err := os.Mkdir(dirName, permissions) + if err != nil { + log.Printf("Ошибка при создании директории: %v", err) + } + + fmt.Printf("Директория '%s' успешно создана.\n", dirName) +} + +func mkfile(dirName string, base64String string, fName string) { + + // Декодирование Base64 строки + decodedBytes, er := base64.StdEncoding.DecodeString(base64String) + if er != nil { + log.Fatalf("Ошибка при декодировании Base64: %v", er) + } + + // Преобразование байтов в строку + fileContent := string(decodedBytes) + + // Права доступа к файлу (0644 - чтение и запись для владельца, чтение для группы и остальных) + fileName := "./" + dirName + "/" + fName + permissions := 0644 + + // Преобразование содержимого в слайс байтов + data := []byte(fileContent) + + // Создание файла и запись содержимого + err := os.WriteFile(fileName, data, os.FileMode(permissions)) + if err != nil { + log.Fatalf("Ошибка при создании файла: %v", err) + } + + fmt.Printf("Файл '%s' успешно создан с содержимым.\n", fileName) + +} + +func run(idTask string) { + + // Получение текущей рабочей директории + currentDir, err := os.Getwd() + if err != nil { + log.Fatalf("Ошибка при получении текущей директории: %v", err) + } + + dir := currentDir + "/" + idTask + + // Изменение текущей рабочей директории + err = os.Chdir(dir) + if err != nil { + log.Fatalf("Ошибка при изменении директории: %v", err) + } + + // Команда для запуска Python с кодом + fileName := "test_hello.py" + + + cmd := exec.Command("python", "-m", "unittest", fileName) + + // Запуск команды и получение вывода + output, err := cmd.CombinedOutput() + if err != nil { + log.Fatalf("Ошибка при выполнении Python кода: %v\nВывод: %s", err, string(output)) + } + + // Вывод результата + fmt.Printf("Вывод Python:\n%s\n", string(output)) + +} diff --git a/code/go/front_code/front.go b/code/go/front_code/front.go new file mode 100644 index 0000000..24d2d4b --- /dev/null +++ b/code/go/front_code/front.go @@ -0,0 +1,85 @@ +package main + +import ( + "database/sql" + "fmt" + "log" + "net/http" + + "github.com/gin-gonic/gin" + _ "github.com/lib/pq" // Import the PostgreSQL driver +) + +const ( + dbHost = "localhost" + dbPort = 5432 + dbUser = "postgres" + dbPassword = "123" // Замените на свой пароль + dbName = "auth" +) + +func main() { + // Строка подключения к базе данных + connStr := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable", + dbHost, dbPort, dbUser, dbPassword, dbName) + + + // to-do: написать обращение в кеш Redis + // Подключение к базе данных + db, err := sql.Open("postgres", connStr) + if err != nil { + log.Fatal(err) + } + defer db.Close() + + // Проверка подключения + err = db.Ping() + if err != nil { + log.Fatal(err) + } + + fmt.Println("Connected to the database!") + + router := gin.Default() + router.LoadHTMLGlob("./templates/*") + + // Обработчик для получения фрагмента кода + router.GET("/code/:id", func(c *gin.Context) { + id := c.Param("id") + var code string + err := db.QueryRow("SELECT json_text FROM task WHERE id = $1", id).Scan(&code) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + c.JSON(http.StatusOK, gin.H{"code": code}) + }) + + // Обработчик для обновления фрагмента кода + router.POST("/code/:id", func(c *gin.Context) { + id := c.Param("id") + var requestBody struct { + Code string `json:"code" binding:"required"` + } + + if err := c.BindJSON(&requestBody); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + + _, err := db.Exec("UPDATE snippets SET code = $1 WHERE id = $2", requestBody.Code, id) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) + return + } + + c.JSON(http.StatusOK, gin.H{"message": "Snippet updated successfully"}) + }) + + router.GET("/", func(c *gin.Context) { + c.HTML(http.StatusOK, "index.html", gin.H{}) + }) + + // Запуск сервера + router.Run(":8080") +} diff --git a/code/go/front_code/templates/index.html b/code/go/front_code/templates/index.html new file mode 100644 index 0000000..0175048 --- /dev/null +++ b/code/go/front_code/templates/index.html @@ -0,0 +1,63 @@ + + + + + + Code Editor + + + + + + +

Code Editor

+ + + + + + \ No newline at end of file diff --git a/code/go/mq/rabbit.go b/code/go/rest_code/rest_server.go similarity index 83% rename from code/go/mq/rabbit.go rename to code/go/rest_code/rest_server.go index 68e2211..db663b5 100644 --- a/code/go/mq/rabbit.go +++ b/code/go/rest_code/rest_server.go @@ -5,9 +5,11 @@ import ( "log" "os" + "encoding/json" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/logger" "github.com/streadway/amqp" + ) // Структура для JSON данных @@ -69,17 +71,27 @@ func main() { app.Get("/send", func(c *fiber.Ctx) error { // Create a message to publish. // to-do: дописать приемку json - p := new(Code) + mess := new(Code) // Разбираем JSON из тела запроса и заполняем структуру - _ = c.BodyParser(p); - - fmt.Println(p.Code) - message := amqp.Publishing{ - ContentType: "text/plain", - Body: []byte(c.Query("msg")), + _ = c.BodyParser(mess); + jsonBody, err := json.Marshal(mess) + if err != nil { + log.Fatalf("Error encoding JSON: %v", err) } + + fmt.Println(mess.Code) + message := amqp.Publishing{ + ContentType: "application/json", + Body: jsonBody, + } + + // message := amqp.Publishing{ + // ContentType: "text/plain", + // Body: []byte("Hello"), + // } + // Attempt to publish a message to the queue. if err := channelRabbitMQ.Publish( "", // exchange