Middle
// Тавсиф: // Ба ҷузъи backend-и барнома бояд иҷро шавад, ки 3 метод дорад: // 1) Ҳамроҳсозии фармон бо ID ва вақти оғоз. // 2) Гирифтани рӯйхати фармонҳои фаъол. // 3) Бекор кардани фармон бо ID. // Фармон бояд дар вақти дар аввалин метод дода шудааст, ба дақиқ иҷро шавад. // Методҳо тавассути сервери HTTP даъват мешаванд, шумораи дархостҳои ҳамзамон // барои ин методҳо муайян нашудааст. // Иҷрои фармон танҳо Print(ID) дар stdout хоҳад буд, барои имитатсияи иҷро.
sobes.tech AI
Ҷавоб аз 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))
}
Такой подход обеспечивает точное выполнение команд в заданное время, потокобезопасность и возможность отмены.