github.com/geniusesgroup/libgo@v0.0.0-20220713101832-828057a9d3d4/achaemenid/application.go (about) 1 /* For license and copyright information please see LEGAL file in repository */ 2 3 package achaemenid 4 5 import ( 6 goos "os" 7 "os/signal" 8 "sync" 9 "syscall" 10 "time" 11 12 "../connection" 13 er "../error" 14 "../ganjine" 15 "../log" 16 "../node" 17 "../protocol" 18 "../service" 19 ) 20 21 // App is the base object that use by other part of app and platforms! 22 // It is implement protocol.Application interface 23 var App appStructure 24 25 // appStructure represents application (server or client) requirements data to serving some functionality such as networks, ... 26 type appStructure struct { 27 softwareStatus protocol.SoftwareStatus 28 state protocol.ApplicationState 29 stateListeners []chan protocol.ApplicationState 30 stateChangeLocker sync.Mutex 31 32 Cryptography cryptography 33 34 ganjine.Cluster 35 log.Logger 36 node.Nodes 37 service.Services 38 er.Errors 39 connection.Connections 40 41 netAppMux 42 } 43 44 func (app *appStructure) SoftwareStatus() protocol.SoftwareStatus { return app.softwareStatus } 45 func (app *appStructure) Status() protocol.ApplicationState { return app.state } 46 func (app *appStructure) NotifyState(notifyBy chan protocol.ApplicationState) { 47 app.stateListeners = append(app.stateListeners, notifyBy) 48 } 49 50 // Init method use to initialize app object with default data in second phase. 51 func (app *appStructure) Init() { 52 defer app.PanicHandler() 53 54 protocol.App.Log(log.InfoEvent(domainEnglish, "-----------------------------Achaemenid Application-----------------------------")) 55 protocol.App.Log(log.InfoEvent(domainEnglish, "Try to initialize application...")) 56 57 app.changeState(protocol.ApplicationStateStarting) 58 59 if app.Manifest.DataNodes.TotalZones < 3 { 60 protocol.App.Log(protocol.Log_Warning, "ReplicationNumber set below 3! Loose write ability until two replication available again on replication failure!") 61 } 62 63 app.Services.Init() 64 app.Errors.Init() 65 app.Connections.Init() 66 67 // Get UserGivenPermission from OS 68 69 app.Manifest.init() 70 app.Cryptography.init() 71 72 registerServices() 73 } 74 75 // Start will start the app and block caller until app shutdown. 76 func (app *appStructure) Start() { 77 protocol.App.Log(log.InfoEvent(domainEnglish, "Try to start application ...")) 78 79 app.changeState(protocol.ApplicationStateRunning) 80 81 protocol.App.Log(log.InfoEvent(domainEnglish, "Application start successfully, Now listen to any OS signals ...")) 82 83 // Block main goroutine to handle OS signals. 84 var sig = make(chan goos.Signal, 1024) 85 signal.Notify(sig) 86 app.HandleOSSignals(sig) 87 } 88 89 // HandleOSSignals use to handle OS signals! Caller will block until app terminate or exit. 90 // https://en.wikipedia.org/wiki/Signal_(IPC) 91 func (app *appStructure) HandleOSSignals(sigChannel chan goos.Signal) { 92 for { 93 var sig = <-sigChannel 94 switch sig { 95 case syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGKILL: 96 protocol.App.Log(log.InfoEvent(domainEnglish, "Caught signal to stop app")) 97 if app.State() == protocol.ApplicationStateRunning { 98 go app.Shutdown() 99 } 100 case syscall.Signal(0x17): // syscall.SIGURG: 101 protocol.App.Log(protocol.Log_Warning, "Caught urgened signal: "+sig) 102 case syscall.Signal(10): // syscall.SIGUSR1 103 protocol.App.Log(log.InfoEvent(domainEnglish, "Caught signal to reload app")) 104 app.Reload() 105 // case syscall.Signal(12): // syscall.SIGUSR2 106 default: 107 protocol.App.Log(protocol.Log_Warning, "Caught un-managed signal: "+sig) 108 } 109 } 110 } 111 112 // Reload use to reload app 113 func (app *appStructure) Reload() {} 114 115 // Shutdown use to graceful stop app 116 func (app *appStructure) Shutdown() { 117 app.changeState(protocol.ApplicationStateStopping) 118 protocol.App.Log(log.InfoEvent(domainEnglish, "Waiting for app to finish and release proccess, It will take up to 60 seconds")) 119 120 app.changeState(protocol.ApplicationStateStopping) 121 122 app.Cryptography.shutdown() 123 app.Connections.Shutdown() 124 app.Nodes.Shutdown() 125 126 // write files to storage device if any change made 127 128 // Wait to finish above logic, or kill app in --- second 129 // time.Sleep(10 * time.Second) 130 var timer = time.NewTimer(app.Manifest.TechnicalInfo.ShutdownDelay) 131 select { 132 case <-timer.C: 133 if app.Status() == protocol.ApplicationStateStopping { 134 protocol.App.Log(log.InfoEvent(domainEnglish, "Application can't finish shutdown and release proccess in"+app.Manifest.TechnicalInfo.ShutdownDelay.String())) 135 goos.Exit(1) 136 } else { 137 protocol.App.Log(log.InfoEvent(domainEnglish, "Application stopped successfully")) 138 goos.Exit(0) 139 } 140 } 141 142 } 143 144 // Shutdown use to graceful stop app 145 func (app *appStructure) changeState(state protocol.ApplicationState) { 146 app.stateChangeLocker.Lock() 147 app.state = state 148 for _, listener := range app.stateListeners { 149 listener <- state 150 } 151 app.stateChangeLocker.Unlock() 152 }