Skip to content

Commit

Permalink
More internal process control
Browse files Browse the repository at this point in the history
  • Loading branch information
AlinaNova21 committed Sep 6, 2019
1 parent ad53b81 commit 83165ff
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 24 deletions.
6 changes: 5 additions & 1 deletion launcher/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"io/ioutil"
"log"
"math"
"path/filepath"
"runtime"
"strconv"

Expand Down Expand Up @@ -68,9 +69,12 @@ func NewConfig() *Config {
}

// GetConfig loads a config from config.yml
func (c *Config) GetConfig() (*Config, error) {
func (c *Config) GetConfig(dir string) (*Config, error) {
files := []string{"config.yml", "config.yaml"}
for _, file := range files {
if dir != "" {
file = filepath.Join(dir, file)
}
configFile, err := ioutil.ReadFile(file)
if err == nil {
err = yaml.Unmarshal(configFile, c)
Expand Down
62 changes: 58 additions & 4 deletions launcher/launcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ import (
"log"
"os"
"os/exec"
"os/signal"
"path/filepath"
"strings"
"syscall"
"time"

"github.com/otiai10/copy"
"github.com/screepers/screeps-launcher/v1/install"
// "path/filepath"
// "strings"
Expand All @@ -22,7 +26,7 @@ type Launcher struct {
// Prepare loads config
func (l *Launcher) Prepare() {
c := NewConfig()
_, err := c.GetConfig()
_, err := c.GetConfig("")
if err != nil {
log.Fatalf("Error loading config: %v", err)
}
Expand Down Expand Up @@ -95,7 +99,8 @@ func (l *Launcher) Apply() error {
}
if l.needsInit {
log.Print("Initializing server")
initServer(l.config)
copy.Copy(filepath.Join("node_modules", "@screeps", "launcher", "init_dist"), ".")
os.RemoveAll(filepath.Join("node_modules", ".hooks"))
}
log.Print("Writing mods.json")
err = writeMods(l.config)
Expand All @@ -112,8 +117,57 @@ func (l *Launcher) Start() error {
return err
}
log.Print("Starting Server")
runServer(l.config)
return nil
s := NewServer(l.config)
if err := s.Start(); err != nil {
log.Printf("Error while starting: %v", err)
} else {
log.Print("Started")
}
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, os.Kill, syscall.SIGHUP)
for {
select {
case sig := <-c:
switch sig {
case syscall.SIGHUP:
log.Printf("SIGHUP Received")
log.Printf("Applying config")
_, err := l.config.GetConfig("")
if err != nil {
log.Fatalf("Error loading config: %v", err)
}
select {
case <-time.After(2 * time.Second):
l.Apply()
case <-c:
l.Upgrade()
}
log.Print("Stopping")
if err := s.Stop(); err != nil {
log.Printf("Error while stopping: %v", err)
} else {
log.Print("Stopped")
}
time.Sleep(1 * time.Second)
log.Print("Starting")
if err := s.Start(); err != nil {
log.Printf("Error while starting: %v", err)
} else {
log.Print("Started")
}
case syscall.SIGINT:
fallthrough
case syscall.SIGKILL:
log.Printf("Stopping")
if err := s.Stop(); err != nil {
log.Printf("Error while stopping: %v", err)
} else {
log.Print("Stopped")
}
return nil
}
}
}
}

// Cli Opens a CLI
Expand Down
99 changes: 80 additions & 19 deletions launcher/server.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package launcher

import (
"context"
"fmt"
"log"
"os"
Expand All @@ -14,47 +15,94 @@ import (
"github.com/screepers/screeps-launcher/v1/install"
)

func initServer(c *Config) {
copy.Copy(filepath.Join("node_modules", "@screeps", "launcher", "init_dist"), ".")
os.RemoveAll(filepath.Join("node_modules", ".hooks"))
// Status is the status of the server
type Status int

//
const (
StatusStopped Status = iota
StatusUpgrading
StatusStarting
StatusRunning
StatusStopping
)

// Server is a screeps server instance
type Server struct {
ctx context.Context
status Status
config *Config
cancel context.CancelFunc
}

func runServer(c *Config) {
// NewServer returns a new Server instance
func NewServer(c *Config) *Server {
return &Server{
config: c,
status: StatusStopped,
}
}

// Status returns the status of the server
func (s Server) Status() Status {
return s.status
}

// Start the server
func (s *Server) Start() error {
if s.status != StatusStopped {
return fmt.Errorf("Server not stopped. Status: %v", s.status)
}
s.status = StatusStarting
s.ctx, s.cancel = context.WithCancel(context.Background())
needsStorage := true
for _, mod := range c.Mods {

for _, mod := range s.config.Mods {
if mod == "screepsmod-mongo" {
needsStorage = false
}
}
if key := os.Getenv("STEAM_KEY"); key == "" && c.Env.Backend["STEAM_KEY"] == "" {
if key := os.Getenv("STEAM_KEY"); key == "" && s.config.Env.Backend["STEAM_KEY"] == "" {
log.Print("STEAM_KEY is not set, either set an environment variable or steamKey in the config.yml")
log.Print("Steam key can be obtained from https://steamcommunity.com/dev/apikey")
os.Exit(1)
}
os.Mkdir("logs", 0777)
if needsStorage {
go runModule("storage", "screeps-storage", c.Env.Storage)
go s.runModule(s.ctx, "storage", "screeps-storage", s.config.Env.Storage)
time.Sleep(3 * time.Second) // Give storage time to launch
}
go runModule("runner", "screeps-engine-runner", c.Env.Engine)
for i := 0; i < c.Processors; i++ {
go runModule(fmt.Sprintf("processor_%d", i), "screeps-engine-processor", c.Env.Engine)
go s.runModule(s.ctx, "runner", "screeps-engine-runner", s.config.Env.Engine)
for i := 0; i < s.config.Processors; i++ {
go s.runModule(s.ctx, fmt.Sprintf("processor_%d", i), "screeps-engine-processor", s.config.Env.Engine)
}
go runModule("main", "screeps-engine-main", c.Env.Engine)
go runModule("backend", "screeps-backend", c.Env.Backend)
select {}
go s.runModule(s.ctx, "main", "screeps-engine-main", s.config.Env.Engine)
go s.runModule(s.ctx, "backend", "screeps-backend", s.config.Env.Backend)
s.status = StatusRunning
return nil
}

// Stop the server
func (s *Server) Stop() error {
if s.status != StatusRunning {
return fmt.Errorf("Server not running. Status: %v", s.status)
}
s.status = StatusStopping
s.cancel()
s.status = StatusStopped
return nil
}

func runModule(name string, module string, env map[string]string) {
func (s *Server) runModule(ctx context.Context, name string, module string, env map[string]string) {
if runtime.GOOS == "windows" {
module = module + ".cmd"
}
os.Mkdir("logs", 0777)
n := filepath.Join("logs", fmt.Sprintf("%s.log", name))
f, err := os.OpenFile(n, os.O_WRONLY|os.O_APPEND|os.O_CREATE, 0666)
if err != nil {
log.Fatalf("Error opening log %s: %v", n, err)
}
// logger := log.New(f, fmt.Sprintf("[%s]", name), log.lstdFlags)
defer f.Close()
for {
log.Printf("[%s] exec: %s", name, module)
newPath := filepath.SplitList(os.Getenv("PATH"))
Expand All @@ -66,15 +114,28 @@ func runModule(name string, module string, env map[string]string) {
}
lenv = append(lenv, fmt.Sprintf("PATH=%s", strings.Join(newPath, string(filepath.ListSeparator))))
fmt.Fprintf(f, "==== %s Starting ====\n", name)
cmd := exec.Command(filepath.Join("node_modules", ".bin", module))
cmd := exec.CommandContext(ctx, filepath.Join("node_modules", ".bin", module))
cmd.Stdout = f
cmd.Stderr = f
cmd.Env = lenv
err := cmd.Run()
log.Printf("[%s] Exited with error: %v", name, err)
fmt.Fprintf(f, "==== %s Exited ====\n", name)
if err != nil {
time.Sleep(1 * time.Second) // Wait before trying to restart
select {
case <-ctx.Done():
return
case <-time.After(1 * time.Second):
}
}
}

func initServer(c *Config) {
copy.Copy(filepath.Join("node_modules", "@screeps", "launcher", "init_dist"), ".")
os.RemoveAll(filepath.Join("node_modules", ".hooks"))
}

func runServer(c *Config) {
s := NewServer(c)
s.Start()
select {}
}

0 comments on commit 83165ff

Please sign in to comment.