Skip to content

Commit

Permalink
wip lifecycle management
Browse files Browse the repository at this point in the history
  • Loading branch information
mansam committed Jul 10, 2024
1 parent 8bfd399 commit 9b04ba7
Show file tree
Hide file tree
Showing 12 changed files with 309 additions and 38 deletions.
31 changes: 31 additions & 0 deletions api/recovery.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package api

import (
"github.com/gin-gonic/gin"
"github.com/konveyor/tackle2-hub/lifecycle"
)

const (
StopRoute = "/service/stop"
StartRoute = "/service/start"
)

type RecoveryHandler struct {
Manager *lifecycle.Manager
}

func (h RecoveryHandler) AddRoutes(e *gin.Engine) {
routeGroup := e.Group("/")
routeGroup.POST(StopRoute, h.Stop)
routeGroup.POST(StartRoute, h.Start)
}

func (h RecoveryHandler) Stop(ctx *gin.Context) {
h.Manager.Stop()
ctx.Status(202)
}

func (h RecoveryHandler) Start(ctx *gin.Context) {
h.Manager.Run()
ctx.Status(202)
}
55 changes: 55 additions & 0 deletions api/server.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package api

import (
"context"
"errors"
"net/http"
"sync"
"time"

"github.com/jortel/go-utils/logr"
)

const (
Unit = time.Second
)

type Server struct {
Handler http.Handler
Address string
Name string
}

func (r *Server) Run(ctx context.Context, wg *sync.WaitGroup) {
Log = logr.WithName(r.Name)
srv := &http.Server{
Addr: r.Address,
Handler: r.Handler,
}
go func() {
Log.Info("api server starting", "address", r.Address)
err := srv.ListenAndServe()
if !errors.Is(err, http.ErrServerClosed) {
Log.Error(err, "api server failed", "address", r.Address)
}
}()

go func() {
defer wg.Done()
select {
case <-ctx.Done():
force, cancel := context.WithTimeout(context.Background(), r.timeout())
defer cancel()
err := srv.Shutdown(force)
if err != nil {
Log.Error(err, "api server shutdown failed", "address", r.Address)
}
return
}
}()
}

func (r *Server) timeout() (d time.Duration) {
d = Unit * time.Duration(Settings.Shutdown.Timeout)
return
}
49 changes: 38 additions & 11 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/konveyor/tackle2-hub/importer"
"github.com/konveyor/tackle2-hub/k8s"
crd "github.com/konveyor/tackle2-hub/k8s/api"
"github.com/konveyor/tackle2-hub/lifecycle"
"github.com/konveyor/tackle2-hub/metrics"
"github.com/konveyor/tackle2-hub/migration"
"github.com/konveyor/tackle2-hub/reaper"
Expand Down Expand Up @@ -155,49 +156,59 @@ func main() {
settings.Settings.Auth.Keycloak.Realm,
)
}

lf := lifecycle.NewManager(db)
//
// Task
taskManager := task.Manager{
Client: client,
DB: db,
}
taskManager.Run(context.Background())
lf.Register(&taskManager)
//
// Reaper
reaperManager := reaper.Manager{
Client: client,
DB: db,
}
reaperManager.Run(context.Background())
lf.Register(&reaperManager)
//
// Application import.
importManager := importer.Manager{
DB: db,
TaskManager: &taskManager,
Client: client,
}
importManager.Run(context.Background())
lf.Register(&importManager)
//
// Ticket trackers.
trackerManager := tracker.Manager{
DB: db,
}
trackerManager.Run(context.Background())
lf.Register(&trackerManager)

//
// Metrics
if Settings.Metrics.Enabled {
log.Info("Serving Prometheus metrics", "port", Settings.Metrics.Port)
http.Handle("/metrics", api.MetricsHandler())
go func() {
_ = http.ListenAndServe(Settings.Metrics.Address(), nil)
}()
mux := http.NewServeMux()
mux.Handle("/metrics", api.MetricsHandler())
metricsManager := metrics.Manager{
DB: db,
}
metricsManager.Run(context.Background())
metricsServer := api.Server{
Handler: mux,
Address: Settings.Metrics.Address(),
Name: "metrics",
}
lf.Register(&metricsServer)
lf.Register(&metricsManager)
}

// Web
router := gin.Default()
router := gin.New()
router.Use(gin.Logger())
router.Use(gin.Recovery())
router.Use(
func(ctx *gin.Context) {
rtx := api.RichContext(ctx)
Expand All @@ -212,5 +223,21 @@ func main() {
for _, h := range api.All() {
h.AddRoutes(router)
}
err = router.Run()
server := api.Server{
Handler: router.Handler(),
Address: ":8080",
Name: "api",
}
lf.Register(&server)
lf.Run()

// Recovery
recovery := gin.New()
recovery.Use(gin.Logger())
recovery.Use(gin.Recovery())
handler := api.RecoveryHandler{
Manager: lf,
}
handler.AddRoutes(recovery)
err = recovery.Run(Settings.Recovery.Address)
}
4 changes: 3 additions & 1 deletion importer/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"regexp"
"sync"

"strings"
"time"
Expand Down Expand Up @@ -32,8 +33,9 @@ type Manager struct {
}

// Run the manager.
func (m *Manager) Run(ctx context.Context) {
func (m *Manager) Run(ctx context.Context, wg *sync.WaitGroup) {
go func() {
defer wg.Done()
for {
select {
case <-ctx.Done():
Expand Down
63 changes: 63 additions & 0 deletions lifecycle/manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package lifecycle

import (
"sync"

"github.com/jortel/go-utils/logr"
"github.com/konveyor/tackle2-hub/database"
"golang.org/x/net/context"
"gorm.io/gorm"
)

var Log = logr.WithName("lifecycle")

type Runnable interface {
Run(ctx context.Context, wg *sync.WaitGroup)
}

func NewManager(db *gorm.DB) (m *Manager) {
m = &Manager{
db: db,
}
return
}

type Manager struct {
db *gorm.DB
running bool
cancel context.CancelFunc
wg sync.WaitGroup
runnable []Runnable
}

func (r *Manager) Register(runnable Runnable) {
r.runnable = append(r.runnable, runnable)
}

func (r *Manager) Run() {
if r.running {
return
}
r.wg = sync.WaitGroup{}
var ctx context.Context
ctx, r.cancel = context.WithCancel(context.Background())
for _, runnable := range r.runnable {
r.wg.Add(1)
runnable.Run(ctx, &r.wg)
}
r.running = true
}

func (r *Manager) Stop() {
if !r.running {
return
}
r.cancel()
r.wg.Wait()
err := database.Close(r.db)
if err != nil {
Log.Error(err, "could not close database after shutting down")
panic(err)
}
r.running = false
}
19 changes: 16 additions & 3 deletions metrics/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,22 @@ package metrics

import (
"context"
"sync"
"time"

"github.com/jortel/go-utils/logr"
"github.com/konveyor/tackle2-hub/model"
"github.com/konveyor/tackle2-hub/settings"
"gorm.io/gorm"
)

var (
Log = logr.WithName("metrics")
Settings = &settings.Settings
Log = logr.WithName("metrics")
)

const (
Unit = time.Second
)

// Manager provides metrics management.
Expand All @@ -20,22 +27,28 @@ type Manager struct {
}

// Run the manager.
func (m *Manager) Run(ctx context.Context) {
func (m *Manager) Run(ctx context.Context, wg *sync.WaitGroup) {
go func() {
Log.Info("Started.")
defer Log.Info("Died.")
defer wg.Done()
for {
select {
case <-ctx.Done():
return
default:
case <-time.After(m.pause()):
time.Sleep(time.Second * 30)
m.gaugeApplications()
}
}
}()
}

func (m *Manager) pause() (d time.Duration) {
d = Unit * time.Duration(Settings.Frequency.Metrics)
return
}

// gaugeApplications reports the number of applications in inventory
func (m *Manager) gaugeApplications() {
count := int64(0)
Expand Down
13 changes: 7 additions & 6 deletions reaper/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package reaper

import (
"context"
"sync"
"time"

"github.com/jortel/go-utils/logr"
Expand Down Expand Up @@ -31,7 +32,7 @@ type Manager struct {
}

// Run the manager.
func (m *Manager) Run(ctx context.Context) {
func (m *Manager) Run(ctx context.Context, wg *sync.WaitGroup) {
registered := []Reaper{
&TaskReaper{
Client: m.Client,
Expand All @@ -50,24 +51,24 @@ func (m *Manager) Run(ctx context.Context) {
go func() {
Log.Info("Started.")
defer Log.Info("Died.")
defer wg.Done()
for {
select {
case <-ctx.Done():
return
default:
case <-time.After(m.pause()):
for _, r := range registered {
r.Run()
}
m.pause()
}
}
}()
}

// Pause.
func (m *Manager) pause() {
d := Unit * time.Duration(Settings.Frequency.Reaper)
time.Sleep(d)
func (m *Manager) pause() (d time.Duration) {
d = Unit * time.Duration(Settings.Frequency.Reaper)
return
}

// Reaper interface.
Expand Down
5 changes: 5 additions & 0 deletions settings/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type TackleSettings struct {
Metrics
Addon
Auth
Lifecycle
}

func (r *TackleSettings) Load() (err error) {
Expand All @@ -31,6 +32,10 @@ func (r *TackleSettings) Load() (err error) {
if err != nil {
return
}
err = r.Lifecycle.Load()
if err != nil {
return
}
return
}

Expand Down
Loading

0 comments on commit 9b04ba7

Please sign in to comment.