Back to questions
Бюро 1440
Middle
4
// Описание: // Нужно реализовать backend часть приложения планировщика, в котором будет 3 метода: // 1) Создать команду с ID и временем запуска. // 2) Получить список активных команд. // 3) Отменить команду по ID. // Команда должна выполнится точно в переданное в первом методе // Методы будут вызываться через HTTP сервер, количество одновременных запросов // этих методов не определено // Само выполнение команды пускай будет Print(ID) в stdout, чтобы эмулировать выполнение.
Companies where asked
Answer from AI
sobes.tech AI
Для реализации backend части планировщика с тремя методами на Go можно использовать HTTP сервер с обработчиками для создания, получения и отмены команд. Для точного выполнения команды в заданное время удобно использовать таймеры или планировщик задач.
Основные моменты:
- Хранить команды в потокобезопасной структуре (например, sync.Map или с мьютексом).
- При создании команды запускать таймер, который сработает в нужное время и выведет ID.
- Метод получения активных команд возвращает список команд, которые ещё не выполнены и не отменены.
- Метод отмены команды удаляет её из хранилища и отменяет таймер.
Пример упрощённой реализации:
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"sync"
"time"
)
type Command struct {
ID string `json:"id"`
ExecTime time.Time `json:"exec_time"`
timer *time.Timer
}
var (
commands = make(map[string]*Command)
mu sync.Mutex
)
func createCommand(w http.ResponseWriter, r *http.Request) {
var cmd Command
if err := json.NewDecoder(r.Body).Decode(&cmd); err != nil {
http.Error(w, "Invalid input", http.StatusBadRequest)
return
}
mu.Lock()
defer mu.Unlock()
if _, exists := commands[cmd.ID]; exists {
http.Error(w, "Command already exists", http.StatusBadRequest)
return
}
dur := time.Until(cmd.ExecTime)
if dur <= 0 {
http.Error(w, "ExecTime must be in the future", http.StatusBadRequest)
return
}
cmd.timer = time.AfterFunc(dur, func() {
fmt.Println(cmd.ID)
mu.Lock()
delete(commands, cmd.ID)
mu.Unlock()
})
commands[cmd.ID] = &cmd
w.WriteHeader(http.StatusCreated)
}
func listCommands(w http.ResponseWriter, r *http.Request) {
mu.Lock()
defer mu.Unlock()
active := make([]Command, 0, len(commands))
for _, cmd := range commands {
active = append(active, Command{ID: cmd.ID, ExecTime: cmd.ExecTime})
}
json.NewEncoder(w).Encode(active)
}
func cancelCommand(w http.ResponseWriter, r *http.Request) {
id := r.URL.Query().Get("id")
if id == "" {
http.Error(w, "Missing id parameter", http.StatusBadRequest)
return
}
mu.Lock()
defer mu.Unlock()
cmd, exists := commands[id]
if !exists {
http.Error(w, "Command not found", http.StatusNotFound)
return
}
cmd.timer.Stop()
delete(commands, id)
w.WriteHeader(http.StatusOK)
}
func main() {
http.HandleFunc("/create", createCommand)
http.HandleFunc("/list", listCommands)
http.HandleFunc("/cancel", cancelCommand)
log.Println("Server started on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
Такой подход обеспечивает точное выполнение команд в заданное время, потокобезопасность и возможность отмены.