github.com/futurehomeno/fimpgo@v1.14.0/edgeapp/lifecycle.go (about) 1 package edgeapp 2 3 import ( 4 log "github.com/sirupsen/logrus" 5 "sync" 6 ) 7 8 const ( 9 SystemEventTypeEvent = "EVENT" 10 SystemEventTypeState = "STATE" // APP state 11 SystemEventTypeAuthState = "AUTH_STATE" // AUTH state 12 SystemEventTypeConfigState = "CONFIG_STATE" // configuration state 13 SystemEventTypeConnectionState = "CONNECTION_STATE" // Connection state 14 15 16 AppStateStarting = "STARTING" 17 AppStateStartupError = "STARTUP_ERROR" 18 AppStateNotConfigured = "NOT_CONFIGURED" 19 AppStateError = "ERROR" 20 AppStateRunning = "RUNNING" 21 AppStateTerminate = "TERMINATING" 22 23 ConfigStateNotConfigured = "NOT_CONFIGURED" 24 ConfigStateConfigured = "CONFIGURED" 25 ConfigStatePartConfigured = "PART_CONFIGURED" 26 ConfigStateInProgress = "IN_PROGRESS" 27 ConfigStateNA = "NA" 28 29 AuthStateNotAuthenticated = "NOT_AUTHENTICATED" 30 AuthStateAuthenticated = "AUTHENTICATED" 31 AuthStateInProgress = "IN_PROGRESS" 32 AuthStateNA = "NA" 33 34 ConnStateConnecting = "CONNECTING" 35 ConnStateConnected = "CONNECTED" 36 ConnStateDisconnected = "DISCONNECTED" 37 ConnStateNA = "NA" 38 39 //EventStarting = "STARTING" 40 EventConfiguring = "CONFIGURING" // All configurations loaded and brokers configured 41 EventConfigError = "CONF_ERROR" // All configurations loaded and brokers configured 42 EventConfigured = "CONFIGURED" // All configurations loaded and brokers configured 43 EventRunning = "RUNNING" 44 ) 45 46 type State string 47 48 type AppStates struct { 49 App string `json:"app"` 50 Connection string `json:"connection"` 51 Config string `json:"config"` 52 Auth string `json:"auth"` 53 LastErrorText string `json:"last_error_text"` 54 LastErrorCode string `json:"last_error_code"` 55 } 56 57 type SystemEvent struct { 58 Type string // Event or State 59 Name string // 60 State State 61 Info string 62 Params map[string]string 63 } 64 65 type SystemEventChannel chan SystemEvent 66 67 type Lifecycle struct { 68 busMux sync.Mutex 69 systemEventBus map[string]SystemEventChannel 70 appState State 71 previousAppState State 72 connectionState State 73 authState State 74 configState State 75 lastError string 76 } 77 78 func NewAppLifecycle() *Lifecycle { 79 lf := &Lifecycle{systemEventBus: make(map[string]SystemEventChannel)} 80 lf.appState = AppStateStarting 81 lf.authState = AuthStateNA 82 lf.configState = ConfigStateNotConfigured 83 lf.connectionState = ConnStateNA 84 return lf 85 } 86 87 func (al *Lifecycle) GetAllStates() *AppStates { 88 appStates := AppStates{ 89 App: string(al.appState), 90 Connection: string(al.connectionState), 91 Config: string(al.configState), 92 Auth: string(al.authState), 93 LastErrorText: "", 94 LastErrorCode: "", 95 } 96 return &appStates 97 } 98 99 func (al *Lifecycle) ConfigState() State { 100 return al.configState 101 } 102 103 func (al *Lifecycle) SetConfigState(configState State) { 104 log.Debug("<sysEvt> New CONFIG state = ", configState) 105 al.configState = configState 106 for i := range al.systemEventBus { 107 select { 108 case al.systemEventBus[i] <- SystemEvent{Type: SystemEventTypeConfigState, State: configState, Info: "sys", Params: nil}: 109 default: 110 log.Debugf("<sysEvt> Config state listener %s is busy , event dropped", i) 111 } 112 } 113 } 114 115 func (al *Lifecycle) AuthState() State { 116 return al.authState 117 } 118 119 func (al *Lifecycle) SetAuthState(authState State) { 120 log.Debug("<sysEvt> New AUTH state = ", authState) 121 al.authState = authState 122 123 for i := range al.systemEventBus { 124 select { 125 case al.systemEventBus[i] <- SystemEvent{Type: SystemEventTypeAuthState, State: authState, Info: "sys", Params: nil}: 126 default: 127 log.Debugf("<sysEvt> Auth state listener %s is busy , event dropped", i) 128 } 129 } 130 } 131 132 func (al *Lifecycle) ConnectionState() State { 133 return al.connectionState 134 } 135 136 func (al *Lifecycle) SetConnectionState(connectivityState State) { 137 log.Debug("<sysEvt> New CONNECTION state = ", connectivityState) 138 al.connectionState = connectivityState 139 for i := range al.systemEventBus { 140 select { 141 case al.systemEventBus[i] <- SystemEvent{Type: SystemEventTypeConnectionState, State: connectivityState, Info: "sys", Params: nil}: 142 default: 143 log.Debugf("<sysEvt> Auth state listener %s is busy , event dropped", i) 144 } 145 } 146 } 147 148 func (al *Lifecycle) AppState() State { 149 return al.appState 150 } 151 152 func (al *Lifecycle) LastError() string { 153 return al.lastError 154 } 155 156 func (al *Lifecycle) SetLastError(lastError string) { 157 al.lastError = lastError 158 } 159 160 func (al *Lifecycle) SetAppState(currentState State, params map[string]string) { 161 al.busMux.Lock() 162 al.previousAppState = al.appState 163 al.appState = currentState 164 log.Debug("<sysEvt> New APP state = ", currentState) 165 for i := range al.systemEventBus { 166 select { 167 case al.systemEventBus[i] <- SystemEvent{Type: SystemEventTypeState, State: currentState, Info: "sys", Params: params}: 168 default: 169 log.Warnf("<sysEvt> State listener %s is busy , event dropped", i) 170 } 171 172 } 173 al.busMux.Unlock() 174 } 175 176 //PublishSystemEvent - published Application system events 177 func (al *Lifecycle) PublishSystemEvent(name, src string, params map[string]string) { 178 event := SystemEvent{Name: name} 179 al.Publish(event, src, params) 180 } 181 182 func (al *Lifecycle) Publish(event SystemEvent, src string, params map[string]string) { 183 al.busMux.Lock() 184 event.Type = SystemEventTypeEvent 185 event.State = al.AppState() 186 event.Params = params 187 for i := range al.systemEventBus { 188 select { 189 case al.systemEventBus[i] <- event: 190 default: 191 log.Warnf("<sysEvt> Event listener %s is busy , event dropped", i) 192 } 193 194 } 195 defer al.busMux.Unlock() 196 } 197 198 // Subscribe for lifecycle events 199 func (al *Lifecycle) Subscribe(subId string, bufSize int) SystemEventChannel { 200 msgChan := make(SystemEventChannel, bufSize) 201 al.busMux.Lock() 202 al.systemEventBus[subId] = msgChan 203 al.busMux.Unlock() 204 return msgChan 205 } 206 207 // Unsubscribe from for lifecycle events 208 func (al *Lifecycle) Unsubscribe(subId string) { 209 al.busMux.Lock() 210 delete(al.systemEventBus, subId) 211 al.busMux.Unlock() 212 } 213 214 // WaitForState blocks until target state is reached 215 func (al *Lifecycle) WaitForState(subId string,stateType string , targetState State) { 216 log.Debugf("<sysEvt> Waiting for state = %s , current state = %s", targetState, al.AppState()) 217 if al.AppState() == targetState && stateType == SystemEventTypeState || 218 al.ConfigState() == targetState && stateType == SystemEventTypeConfigState || 219 al.AuthState() == targetState && stateType == SystemEventTypeAuthState || 220 al.ConnectionState() == targetState && stateType == SystemEventTypeConnectionState { 221 return 222 } 223 ch := al.Subscribe(subId, 5) 224 for evt := range ch { 225 if evt.Type == stateType && evt.State == targetState { 226 al.Unsubscribe(subId) 227 return 228 } 229 } 230 }