first commit

This commit is contained in:
2026-04-08 21:43:35 +03:00
commit be7a1a3ea2
33 changed files with 9609 additions and 0 deletions

148
cmd/futriis/main.go Normal file
View File

@@ -0,0 +1,148 @@
// Файл: cmd/futriis/main.go
// Назначение: Точка входа в приложение СУБД futriis. Инициализирует все компоненты:
// конфигурацию, логгер, хранилище, Raft координатор, ACL менеджер, HTTP API и REPL.
// Управляет жизненным циклом приложения.
package main
import (
"encoding/json"
"fmt"
"os"
"os/signal"
"syscall"
"time"
"futriis/internal/acl"
"futriis/internal/api"
"futriis/internal/cluster"
"futriis/internal/config"
"futriis/internal/log"
"futriis/internal/repl"
"futriis/internal/storage"
"futriis/pkg/utils"
)
func main() {
utils.SetColorEnabled(true)
cfg, err := config.LoadConfig("config.toml")
if err != nil {
utils.PrintError("Failed to load config: " + err.Error())
os.Exit(1)
}
logger, err := log.NewLogger(cfg.Log.LogFile, cfg.Log.LogLevel)
if err != nil {
utils.PrintError("Failed to initialize logger: " + err.Error())
os.Exit(1)
}
defer logger.Close()
logger.Info("futriis database starting...")
store := storage.NewStorage(cfg.Storage.PageSizeMB, logger)
// Инициализация ACL менеджера
aclManager := acl.NewACLManager()
logger.Info("ACL manager initialized")
raftCoordinator, err := cluster.NewRaftCoordinator(cfg, logger)
if err != nil {
logger.Error("Failed to start Raft coordinator: " + err.Error())
utils.PrintError("Failed to start Raft coordinator: " + err.Error())
os.Exit(1)
}
if cfg.Cluster.Bootstrap || len(cfg.Cluster.Nodes) <= 1 {
maxRetries := 10
for i := 0; i < maxRetries; i++ {
if raftCoordinator.IsLeader() {
break
}
time.Sleep(1 * time.Second)
}
}
node := cluster.NewNode(cfg.Cluster.NodeIP, cfg.Cluster.NodePort, store, logger)
maxRetries := 5
var registerErr error
for i := 0; i < maxRetries; i++ {
registerErr = raftCoordinator.RegisterNode(node)
if registerErr == nil {
break
}
if i < maxRetries-1 {
time.Sleep(2 * time.Second)
}
}
if registerErr != nil {
logger.Error("Failed to register node: " + registerErr.Error())
utils.PrintError("Failed to register node: " + registerErr.Error())
os.Exit(1)
}
// Запуск HTTP API сервера
httpPort := 8080
httpServer := api.NewHTTPServer(httpPort, store, raftCoordinator, aclManager, logger)
go func() {
if err := httpServer.Start(); err != nil {
logger.Error("HTTP server error: " + err.Error())
utils.PrintError("HTTP server error: " + err.Error())
}
}()
logger.Info(fmt.Sprintf("HTTP API server started on port %d", httpPort))
displayBanner(cfg.Cluster.Name)
replInstance := repl.NewRepl(store, raftCoordinator, logger, cfg)
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-sigChan
utils.Println("\nReceived shutdown signal")
logger.Info("Received shutdown signal")
httpServer.Stop()
raftCoordinator.Stop()
node.Stop()
replInstance.Close()
utils.DisableColorMode()
os.Exit(0)
}()
if err := replInstance.Run(); err != nil {
logger.Error("REPL error: " + err.Error())
utils.PrintError("REPL error: " + err.Error())
os.Exit(1)
}
}
func displayBanner(clusterName string) {
utils.Println("")
bannerLines := []string{
" futriix 3i²(by 02.04.2026) ",
" Distributed Document-Store in-memory database with support lua plugins ",
" Cluster status: enable (Raft consensus)",
" Cluster name: " + clusterName,
" HTTP API: http://localhost:8080/api/",
" Type 'quit' or 'exit' to quit",
" Type 'status' to see cluster status",
" Type 'acl login <user> <pass>' to authenticate",
}
for _, line := range bannerLines {
utils.PrintInfo(line)
}
}
// Вспомогательная функция для форматирования JSON (если понадобится)
func printJSON(data interface{}) {
jsonData, err := json.MarshalIndent(data, "", " ")
if err != nil {
utils.PrintError("Failed to marshal JSON: " + err.Error())
return
}
fmt.Println(string(jsonData))
}