Skip to content

Commit

Permalink
fix: server-manager timeout
Browse files Browse the repository at this point in the history
Set a fixed timeout for server-manager to finish executing after a call to Cmd.Wait(). For more information, check #201
torives authored and gligneul committed Feb 1, 2024
1 parent db0b303 commit 7301756
Showing 2 changed files with 83 additions and 2 deletions.
4 changes: 2 additions & 2 deletions cmd/cartesi-rollups-node/services.go
Original file line number Diff line number Diff line change
@@ -279,8 +279,8 @@ func newRedis() services.CommandService {
return s
}

func newServerManager() services.CommandService {
var s services.CommandService
func newServerManager() services.ServerManager {
var s services.ServerManager
s.Name = "server-manager"
s.HealthcheckPort = getPort(portOffsetServerManager)
s.Path = "server-manager"
81 changes: 81 additions & 0 deletions internal/services/server-manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

package services

import (
"context"
"fmt"
"net"
"os/exec"
"syscall"
"time"

"github.com/cartesi/rollups-node/internal/config"
)

type ServerManager struct {
// Name that identifies the service.
Name string

// Port used to verify if the service is ready.
HealthcheckPort int

// Path to the service binary.
Path string

// Args to the service binary.
Args []string

// Environment variables.
Env []string
}

const waitDelay = 200 * time.Millisecond

func (s ServerManager) Start(ctx context.Context, ready chan<- struct{}) error {
cmd := exec.CommandContext(ctx, s.Path, s.Args...)
cmd.Env = s.Env
cmd.Stderr = newLineWriter(commandLogger{s.Name})
cmd.Stdout = newLineWriter(commandLogger{s.Name})
cmd.WaitDelay = waitDelay
cmd.Cancel = func() error {
err := cmd.Process.Signal(syscall.SIGTERM)
if err != nil {
msg := "failed to send SIGTERM to %v: %v\n"
config.WarningLogger.Printf(msg, s, err)
}
return err
}
go s.pollTcp(ctx, ready)
err := cmd.Run()

if ctx.Err() != nil {
return ctx.Err()
}
return err
}

// Blocks until the service is ready or the context is canceled.
func (s ServerManager) pollTcp(ctx context.Context, ready chan<- struct{}) {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
for {
conn, err := net.Dial("tcp", fmt.Sprintf("0.0.0.0:%v", s.HealthcheckPort))
if err == nil {
config.DebugLogger.Printf("%s is ready\n", s)
conn.Close()
ready <- struct{}{}
return
}
select {
case <-ctx.Done():
return
case <-time.After(DefaultPollInterval):
}
}
}

func (s ServerManager) String() string {
return s.Name
}

0 comments on commit 7301756

Please sign in to comment.