Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use goroutines to start services #104

Merged
merged 1 commit into from
Oct 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 0 additions & 52 deletions cmd/cartesi-node/full.go

This file was deleted.

5 changes: 3 additions & 2 deletions cmd/cartesi-node/no-backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ package main
import "github.com/spf13/cobra"

var noBackend = &cobra.Command{
Use: "no-backend",
Short: "Starts the node in no-backend mode",
Use: "no-backend",
Short: "Starts the node in no-backend mode",
DisableFlagsInUseLine: true,
Run: func(cmd *cobra.Command, args []string) {
println("TODO")
},
Expand Down
5 changes: 3 additions & 2 deletions cmd/cartesi-node/reader.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ package main
import "github.com/spf13/cobra"

var reader = &cobra.Command{
Use: "reader",
Short: "Starts the node in reader mode",
Use: "reader",
Short: "Starts the node in reader mode",
DisableFlagsInUseLine: true,
Run: func(cmd *cobra.Command, args []string) {
println("TODO")
},
Expand Down
6 changes: 3 additions & 3 deletions cmd/cartesi-node/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ package main
import "github.com/spf13/cobra"

var rootCmd = &cobra.Command{
Use: "cartesi-node [reader|validator|full|no-backend]",
Run: func(cmd *cobra.Command, args []string) { cmd.Usage() },
Use: "cartesi-node",
CompletionOptions: cobra.CompletionOptions{HiddenDefaultCmd: true},
DisableFlagsInUseLine: true,
}

func init() {
rootCmd.AddCommand(reader)
rootCmd.AddCommand(validator)
rootCmd.AddCommand(full)
rootCmd.AddCommand(noBackend)
}
22 changes: 16 additions & 6 deletions cmd/cartesi-node/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,22 @@

package main

import "github.com/spf13/cobra"
import (
"github.com/cartesi/rollups-node/internal/pkg/services"
"github.com/spf13/cobra"
)

var validator = &cobra.Command{
Use: "validator",
Short: "Starts the node in validator mode",
Run: func(cmd *cobra.Command, args []string) {
println("TODO")
},
Use: "validator",
Short: "Starts the node in validator mode",
DisableFlagsInUseLine: true,
Run: runValidatorNode,
}

func runValidatorNode(cmd *cobra.Command, args []string) {
validatorServices := []services.Service{
services.GraphQLService{},
}

services.Run(validatorServices)
}
45 changes: 45 additions & 0 deletions internal/pkg/services/graphql-service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

package services

import (
"context"
"fmt"
"os"
"os/exec"
"syscall"
)

const (
serviceName = "graphql-server"
binaryName = "cartesi-rollups-graphql-server"
)

type GraphQLService struct{}

func (g GraphQLService) Start(ctx context.Context) error {
cmd := exec.Command(binaryName)
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout

if err := cmd.Start(); err != nil {
return err
}

go func() {
<-ctx.Done()
fmt.Printf("%v: %v\n", g.String(), ctx.Err())
cmd.Process.Signal(syscall.SIGTERM)
}()

err := cmd.Wait()
if err != nil && cmd.ProcessState.ExitCode() != int(syscall.SIGTERM) {
torives marked this conversation as resolved.
Show resolved Hide resolved
return err
}
return nil
}

func (g GraphQLService) String() string {
return serviceName
}
69 changes: 69 additions & 0 deletions internal/pkg/services/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// (c) Cartesi and individual authors (see AUTHORS)
// SPDX-License-Identifier: Apache-2.0 (see LICENSE)

// Provide mechanisms to start multiple services in the background
package services
torives marked this conversation as resolved.
Show resolved Hide resolved

import (
"context"
"fmt"
"time"
)

// A service that runs in the background endlessly until the context is canceled
type Service interface {
torives marked this conversation as resolved.
Show resolved Hide resolved
fmt.Stringer

// Start a service that will run until completion or until the context is
// canceled
Start(ctx context.Context) error
}

const DefaultServiceTimeout = 15 * time.Second

// The Run function serves as a very simple supervisor: it will start all the
// services provided to it and will run until the first of them finishes. Next
// it will try to stop the remaining services or timeout if they take too long
func Run(services []Service) {
if len(services) == 0 {
panic("there are no services to run")
}

// start services
ctx, cancel := context.WithCancel(context.Background())
exit := make(chan struct{})
for _, service := range services {
service := service
go func() {
if err := service.Start(ctx); err != nil {
msg := "main: service '%v' exited with error: %v\n"
fmt.Printf(msg, service.String(), err)
} else {
msg := "main: service '%v' exited successfully\n"
fmt.Printf(msg, service.String())
}
exit <- struct{}{}
}()
}

// wait for first service to exit
<-exit

// send stop message to all other services and wait for them to finish
// or timeout
wait := make(chan struct{})
go func() {
cancel()
for i := 0; i < len(services)-1; i++ {
<-exit
}
wait <- struct{}{}
}()

select {
case <-wait:
fmt.Println("main: all services exited")
gligneul marked this conversation as resolved.
Show resolved Hide resolved
case <-time.After(DefaultServiceTimeout):
torives marked this conversation as resolved.
Show resolved Hide resolved
fmt.Println("main: exited after timeout")
}
}
Loading