X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=blobdiff_plain;f=pkg%2Fxapp%2Fxapp.go;h=6c7c5673658639de2ac75c89742b853e76aadcea;hb=f22b458846a20a4a9fcafb49e3195ab44a16840e;hp=124fbcfa34aa1b5b973168d7d898837b02050a1a;hpb=5120ec103eead26427b977f4b2456c2ce57b36ac;p=ric-plt%2Fxapp-frame.git diff --git a/pkg/xapp/xapp.go b/pkg/xapp/xapp.go index 124fbcf..6c7c567 100755 --- a/pkg/xapp/xapp.go +++ b/pkg/xapp/xapp.go @@ -23,9 +23,15 @@ import ( "fmt" "github.com/spf13/viper" "net/http" + "os" + "os/signal" + "sync/atomic" + "syscall" + "time" ) type ReadyCB func(interface{}) +type ShutdownCB func() var ( // XApp is an application instance @@ -37,8 +43,12 @@ var ( Logger *Log Config Configurator Subscription *Subscriber + Alarm *AlarmClient readyCb ReadyCB readyCbParams interface{} + shutdownCb ShutdownCB + shutdownFlag int32 + shutdownCnt int32 ) func IsReady() bool { @@ -51,11 +61,16 @@ func SetReadyCB(cb ReadyCB, params interface{}) { } func xappReadyCb(params interface{}) { + Alarm = NewAlarmClient(viper.GetString("alarm.MOId"), viper.GetString("alarm.APPId")) if readyCb != nil { readyCb(readyCbParams) } } +func SetShutdownCB(cb ShutdownCB) { + shutdownCb = cb +} + func init() { // Load xapp configuration Logger = LoadConfig() @@ -68,15 +83,61 @@ func init() { if viper.IsSet("db.namespaces") { namespaces := viper.GetStringSlice("db.namespaces") - if namespaces[0] != "" { + if len(namespaces) > 0 && namespaces[0] != "" { Sdl = NewSDLClient(viper.GetStringSlice("db.namespaces")[0]) } - if namespaces[1] != "" { + if len(namespaces) > 1 && namespaces[1] != "" { Rnib = NewRNIBClient(viper.GetStringSlice("db.namespaces")[1]) } } else { Sdl = NewSDLClient(viper.GetString("db.namespace")) } + + // + // Signal handlers to really exit program. + // shutdownCb can hang until application has + // made all needed gracefull shutdown actions + // hardcoded limit for shutdown is 20 seconds + // + interrupt := make(chan os.Signal, 1) + signal.Notify(interrupt, syscall.SIGINT, syscall.SIGTERM) + //signal handler function + go func() { + for _ = range interrupt { + if atomic.CompareAndSwapInt32(&shutdownFlag, 0, 1) { + // close function + go func() { + timeout := int(20) + sentry := make(chan struct{}) + defer close(sentry) + + // close callback + go func() { + if shutdownCb != nil { + shutdownCb() + } + sentry <- struct{}{} + }() + select { + case <-time.After(time.Duration(timeout) * time.Second): + Logger.Info("xapp-frame shutdown callback took more than %d seconds", timeout) + case <-sentry: + Logger.Info("xapp-frame shutdown callback handled within %d seconds", timeout) + } + os.Exit(0) + }() + } else { + newCnt := atomic.AddInt32(&shutdownCnt, 1) + Logger.Info("xapp-frame shutdown already ongoing. Forced exit counter %d/%d ", newCnt, 5) + if newCnt >= 5 { + Logger.Info("xapp-frame shutdown forced exit") + os.Exit(0) + } + continue + } + + } + }() } func RunWithParams(c MessageConsumer, sdlcheck bool) {