github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/engine/funcgroup/funcgroup.go (about) 1 package funcgroup 2 3 import ( 4 "context" 5 "fmt" 6 "reflect" 7 "strings" 8 "time" 9 10 "database/sql" 11 12 "github.com/mdaxf/iac/documents" 13 tcom "github.com/mdaxf/iac/engine/com" 14 funcs "github.com/mdaxf/iac/engine/function" 15 "github.com/mdaxf/iac/engine/types" 16 "github.com/mdaxf/iac/logger" 17 "github.com/mdaxf/iac-signalr/signalr" 18 ) 19 20 type FGroup struct { 21 FGobj types.FuncGroup 22 DBTx *sql.Tx 23 Ctx context.Context 24 CtxCancel context.CancelFunc 25 Nextfuncgroup string 26 SystemSession map[string]interface{} // {sessionanme: value} 27 UserSession map[string]interface{} // {sessionanme: value} 28 Externalinputs map[string]interface{} // {sessionanme: value} 29 Externaloutputs map[string]interface{} // {sessionanme: value} 30 funcCachedVariables map[string]interface{} 31 iLog logger.Log 32 DocDBCon *documents.DocDB 33 SignalRClient signalr.Client 34 ErrorMessage string 35 TestwithSc bool 36 TestResults map[string]interface{} 37 } 38 39 // NewFGroup creates a new instance of FGroup. 40 // It takes various parameters including DocDBCon, SignalRClient, dbTx, fgobj, nextfuncgroup, systemSession, userSession, externalinputs, externaloutputs, ctx, and ctxcancel. 41 // It initializes the FGroup struct with the provided values and returns a pointer to the newly created FGroup instance. 42 43 func NewFGroup(DocDBCon *documents.DocDB, SignalRClient signalr.Client, dbTx *sql.Tx, fgobj types.FuncGroup, nextfuncgroup string, systemSession, userSession, externalinputs, externaloutputs map[string]interface{}, ctx context.Context, ctxcancel context.CancelFunc) *FGroup { 44 log := logger.Log{} 45 log.ModuleName = logger.TranCode 46 log.ControllerName = "Function Group" 47 if systemSession["UserNo"] != nil { 48 log.User = systemSession["UserNo"].(string) 49 } else { 50 log.User = "System" 51 } 52 startTime := time.Now() 53 defer func() { 54 elapsed := time.Since(startTime) 55 log.PerformanceWithDuration("engine.funcgroup.NewFGroup", elapsed) 56 }() 57 /* 58 defer func() { 59 if err := recover(); err != nil { 60 log.Error(fmt.Sprintf("There is error to engine.funcgroup.NewFGroup with error: %s", err)) 61 return 62 } 63 }() 64 */ 65 return &FGroup{ 66 FGobj: fgobj, 67 DBTx: dbTx, 68 Ctx: ctx, 69 CtxCancel: ctxcancel, 70 Nextfuncgroup: nextfuncgroup, 71 SystemSession: systemSession, 72 UserSession: userSession, 73 Externalinputs: externalinputs, 74 Externaloutputs: externaloutputs, 75 funcCachedVariables: map[string]interface{}{}, 76 iLog: log, 77 DocDBCon: DocDBCon, 78 SignalRClient: SignalRClient, 79 ErrorMessage: "", 80 TestwithSc: false, 81 TestResults: map[string]interface{}{}, 82 } 83 84 } 85 86 // Execute executes the function group by iterating over its functions and executing each one. 87 // It also handles error recovery and logs performance metrics. 88 // It takes no parameters and returns no values. 89 func (c *FGroup) Execute() { 90 startTime := time.Now() 91 defer func() { 92 elapsed := time.Since(startTime) 93 c.iLog.PerformanceWithDuration("engine.funcgroup.Execute", elapsed) 94 }() 95 96 defer func() { 97 if r := recover(); r != nil { 98 99 c.iLog.Error(fmt.Sprintf("Panic: %s", r)) 100 c.ErrorMessage = fmt.Sprintf("Panic: %s", r) 101 c.DBTx.Rollback() 102 c.CtxCancel() 103 if c.TestwithSc { 104 tcom.SendTestResultMessageBus("", c.FGobj.ID, "", "End", "", 105 c.Externalinputs, c.Externaloutputs, c.SystemSession, c.UserSession, fmt.Errorf(c.ErrorMessage), c.SystemSession["ClientID"].(string), c.SystemSession["UserNo"].(string)) 106 } 107 return 108 } 109 }() 110 111 c.iLog.Info(fmt.Sprintf("Start process function group %s's %s ", c.FGobj.Name, reflect.ValueOf(c.Execute).Kind().String())) 112 c.iLog.Debug(fmt.Sprintf("systemSession: %s", logger.ConvertJson(c.SystemSession))) 113 c.iLog.Debug(fmt.Sprintf("userSession: %s", logger.ConvertJson(c.UserSession))) 114 c.iLog.Debug(fmt.Sprintf("externalinputs: %s", logger.ConvertJson(c.Externalinputs))) 115 c.iLog.Debug(fmt.Sprintf("externaloutputs: %s", logger.ConvertJson(c.Externaloutputs))) 116 117 systemSession := c.SystemSession 118 userSession := c.UserSession 119 funcCachedVariables := map[string]interface{}{} 120 externalinputs := c.Externalinputs 121 externaloutputs := c.Externaloutputs 122 123 if c.TestwithSc { 124 125 c.TestResults["Name"] = c.FGobj.Name 126 c.TestResults["Type"] = "FunctionGroup" 127 c.TestResults["Inputs"] = c.Externalinputs 128 c.TestResults["Outputs"] = c.Externaloutputs 129 c.TestResults["UserSession"] = c.UserSession 130 c.TestResults["SystemSession"] = systemSession 131 c.TestResults["StartTime"] = time.Now() 132 c.TestResults["Functions"] = []map[string]interface{}{} 133 134 tcom.SendTestResultMessageBus("", c.FGobj.ID, "", "Start", "", 135 externalinputs, externaloutputs, systemSession, userSession, nil, c.SystemSession["ClientID"].(string), c.SystemSession["UserNo"].(string)) 136 } 137 138 for _, fobj := range c.FGobj.Functions { 139 // f := *(funcs.NewFuncs(fobj, systemSession, userSession, externalinputs, externaloutputs, funcCachedVariables)) 140 c.iLog.Info(fmt.Sprintf("Start process function %s", fobj.Name)) 141 c.iLog.Debug(fmt.Sprintf("systemSession: %s", logger.ConvertJson(systemSession))) 142 c.iLog.Debug(fmt.Sprintf("funcCachedVariables: %s", logger.ConvertJson(c.funcCachedVariables))) 143 c.iLog.Debug(fmt.Sprintf("userSession: %s", logger.ConvertJson(userSession))) 144 c.iLog.Debug(fmt.Sprintf("externalinputs: %s", logger.ConvertJson(externalinputs))) 145 c.iLog.Debug(fmt.Sprintf("externaloutputs: %s", logger.ConvertJson(externaloutputs))) 146 147 f := &funcs.Funcs{ 148 Fobj: fobj, 149 Ctx: c.Ctx, 150 CtxCancel: c.CtxCancel, 151 DBTx: c.DBTx, 152 DocDBCon: c.DocDBCon, 153 SignalRClient: c.SignalRClient, 154 SystemSession: systemSession, 155 UserSession: userSession, 156 Externalinputs: externalinputs, 157 Externaloutputs: externaloutputs, 158 FuncCachedVariables: funcCachedVariables, 159 ErrorMessage: "", 160 TestwithSc: c.TestwithSc, 161 TestResults: make([]map[string]interface{}, 0), 162 } 163 164 f.Execute() 165 166 if c.TestwithSc { 167 funcTestResults := c.TestResults["Functions"].([]map[string]interface{}) 168 169 for _, ft := range f.TestResults { 170 funcTestResults = append(funcTestResults, ft) 171 } 172 173 c.TestResults["Functions"] = funcTestResults 174 175 tcom.SendTestResultMessageBus("", c.FGobj.ID, fobj.ID, "End", "", 176 f.Externalinputs, f.Externaloutputs, f.SystemSession, f.UserSession, fmt.Errorf(f.ErrorMessage), c.SystemSession["ClientID"].(string), c.SystemSession["UserNo"].(string)) 177 } 178 179 if f.ErrorMessage != "" { 180 c.ErrorMessage = f.ErrorMessage 181 c.iLog.Error(fmt.Sprintf("Error: %s", c.ErrorMessage)) 182 c.CtxCancel() 183 return 184 } 185 186 c.iLog.Info(fmt.Sprintf("End process function %s", fobj.Name)) 187 //c.iLog.Debug(fmt.Sprintf("systemSession: %s", logger.ConvertJson(systemSession))) 188 c.iLog.Debug(fmt.Sprintf("funcCachedVariables: %s", logger.ConvertJson(funcCachedVariables))) 189 c.iLog.Debug(fmt.Sprintf("userSession: %s", logger.ConvertJson(userSession))) 190 c.iLog.Debug(fmt.Sprintf("externalinputs: %s", logger.ConvertJson(externalinputs))) 191 c.iLog.Debug(fmt.Sprintf("externaloutputs: %s", logger.ConvertJson(externaloutputs))) 192 193 userSession = f.UserSession 194 funcCachedVariables = f.FuncCachedVariables 195 externalinputs = f.Externalinputs 196 externaloutputs = f.Externaloutputs 197 } 198 c.UserSession = userSession 199 c.Externalinputs = externalinputs 200 c.Externaloutputs = externaloutputs 201 c.funcCachedVariables = funcCachedVariables 202 c.Nextfuncgroup = c.CheckRouter(c.FGobj.RouterDef) 203 204 if c.TestwithSc { 205 c.TestResults["EndTime"] = time.Now() 206 c.TestResults["Outputs"] = c.Externaloutputs 207 c.TestResults["Error"] = c.ErrorMessage 208 tcom.SendTestResultMessageBus("", c.FGobj.ID, "", "End", "", 209 externalinputs, externaloutputs, systemSession, userSession, nil, c.SystemSession["ClientID"].(string), c.SystemSession["UserNo"].(string)) 210 211 } 212 c.iLog.Info(fmt.Sprintf("End process function group %s's %s ", c.FGobj.Name, reflect.ValueOf(c.Execute).Kind().String())) 213 c.iLog.Debug(fmt.Sprintf("systemSession: %s", logger.ConvertJson(c.SystemSession))) 214 c.iLog.Debug(fmt.Sprintf("funcCachedVariables: %s", logger.ConvertJson(c.funcCachedVariables))) 215 c.iLog.Debug(fmt.Sprintf("userSession: %s", logger.ConvertJson(c.UserSession))) 216 c.iLog.Debug(fmt.Sprintf("externalinputs: %s", logger.ConvertJson(c.Externalinputs))) 217 c.iLog.Debug(fmt.Sprintf("externaloutputs: %s", logger.ConvertJson(c.Externaloutputs))) 218 c.iLog.Debug(fmt.Sprintf("nextfuncgroup: %s", c.Nextfuncgroup)) 219 220 } 221 222 // CheckRouter checks the router definition and determines the next function group to execute based on the provided RouterDef. 223 // It returns the name of the next function group. 224 func (c *FGroup) CheckRouter(RouterDef types.RouterDef) string { 225 startTime := time.Now() 226 defer func() { 227 elapsed := time.Since(startTime) 228 c.iLog.PerformanceWithDuration("engine.funcgroup.CheckRouter", elapsed) 229 }() 230 231 c.iLog.Info(fmt.Sprintf("Start process function group %s's %s ", c.FGobj.Name, reflect.ValueOf(c.CheckRouter).Kind().String())) 232 c.iLog.Debug(fmt.Sprintf("RouterDef: %s", logger.ConvertJson(RouterDef))) 233 234 variable := RouterDef.Variable 235 vartype := RouterDef.Vartype 236 values := RouterDef.Values 237 nextfuncgroups := RouterDef.Nextfuncgroups 238 defaultfuncgroup := RouterDef.Defaultfuncgroup 239 240 c.iLog.Debug(fmt.Sprintf("variable: %s, vartype: %s, values: %s, nextfg:%s, defaultfg:%s", variable, vartype, logger.ConvertJson(values), logger.ConvertJson(nextfuncgroups), defaultfuncgroup)) 241 switch vartype { 242 case "systemSession": 243 c.iLog.Debug("start systemSession:") 244 if c.SystemSession[variable] != nil { 245 for i, value := range values { 246 if c.SystemSession[variable] == value { 247 c.iLog.Info(fmt.Sprintf("End process function group %s's %s 's Next func group: %s", c.FGobj.Name, reflect.ValueOf(c.CheckRouter).Kind().String(), nextfuncgroups[i])) 248 return nextfuncgroups[i] 249 } 250 } 251 } 252 case "userSession": 253 c.iLog.Debug("start userSession:") 254 if c.UserSession[variable] != nil { 255 for i, value := range values { 256 if c.UserSession[variable] == value { 257 c.iLog.Info(fmt.Sprintf("End process function group %s's %s 's Next func group: %s", c.FGobj.Name, reflect.ValueOf(c.CheckRouter).Kind().String(), nextfuncgroups[i])) 258 return nextfuncgroups[i] 259 } 260 } 261 } 262 /*case "": 263 case "funcCachedVariables": */ 264 default: 265 c.iLog.Debug("start default:") 266 arr := strings.Split(variable, ".") 267 c.iLog.Debug(fmt.Sprintf("variable: %s arr: %s", variable, logger.ConvertJson(arr))) 268 if len(arr) == 2 { 269 c.iLog.Debug(fmt.Sprintf("function variables: %s", logger.ConvertJson(c.funcCachedVariables))) 270 if c.funcCachedVariables[arr[0]] != nil { 271 tempobj := c.funcCachedVariables[arr[0]].(map[string]interface{}) 272 c.iLog.Debug(fmt.Sprintf("function variables: %s", logger.ConvertJson(tempobj))) 273 if tempobj[arr[1]] != nil { 274 c.iLog.Debug(fmt.Sprintf("function %s variable %s value: %s", arr[0], arr[1], logger.ConvertJson(tempobj[arr[1]]))) 275 for i, value := range values { 276 if tempobj[arr[1]] == value { 277 c.iLog.Info(fmt.Sprintf("End process function group %s's %s 's Next func group: %s", c.FGobj.Name, reflect.ValueOf(c.CheckRouter).Kind().String(), nextfuncgroups[i])) 278 return nextfuncgroups[i] 279 } 280 } 281 } 282 } 283 } 284 } 285 286 c.iLog.Info(fmt.Sprintf("End process function group %s's %s 's Next func group: %s", c.FGobj.Name, reflect.ValueOf(c.CheckRouter).Kind().String(), defaultfuncgroup)) 287 288 return defaultfuncgroup 289 }