github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/initialize.go (about) 1 // Copyright 2023 IAC. All Rights Reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package main 16 17 import ( 18 "encoding/json" 19 "fmt" 20 "io/ioutil" 21 "time" 22 23 config "github.com/mdaxf/iac/config" 24 dbconn "github.com/mdaxf/iac/databases" 25 "github.com/mdaxf/iac/documents" 26 "github.com/mdaxf/iac/framework/cache" 27 "github.com/google/uuid" 28 29 // iacmb "github.com/mdaxf/iac/framework/messagebus" 30 31 // "github.com/mdaxf/iac/integration/messagebus/nats" 32 33 "github.com/mdaxf/iac/integration/mqttclient" 34 35 // "github.com/mdaxf/iac/integration/opcclient" 36 "github.com/mdaxf/iac/com" 37 "github.com/mdaxf/iac/integration/signalr" 38 39 "github.com/mdaxf/iac/logger" 40 41 "github.com/mdaxf/iac/engine/trancode" 42 "github.com/mdaxf/iac/framework/callback_mgr" 43 44 "github.com/mdaxf/iac/integration/activemq" 45 "github.com/mdaxf/iac/integration/kafka" 46 ) 47 48 var err error 49 var ilog logger.Log 50 var Initialized bool 51 52 // initialize is a function that performs the initialization process of the application. 53 // It sets up the logger, initializes the cache, database, documents, MQTT client, and IAC message bus. 54 // It also connects to the IAC Message Bus using SignalR. 55 // The function measures the performance duration and logs any errors that occur during the initialization process. 56 // Finally, it sets the Initialized flag to true. 57 58 func initialize() { 59 ilog = logger.Log{ModuleName: logger.Framework, User: "System", ControllerName: "Initialization"} 60 startTime := time.Now() 61 fmt.Printf("initialize starttime: %v", startTime) 62 defer func() { 63 fmt.Printf("initialize defer time: %v", time.Now()) 64 elapsed := time.Since(startTime) 65 if Initialized { 66 ilog.PerformanceWithDuration("main.initialize", elapsed) 67 } else { 68 fmt.Printf("initialize defer time: %v, duration: %v", time.Now(), elapsed) 69 } 70 }() 71 com.NodeHeartBeats = make(map[string]interface{}) 72 com.InstanceID = uuid.New().String() 73 74 com.ApiKey = config.ApiKey 75 76 initializeloger() 77 78 ilog.Debug("initialize logger") 79 config.SessionCacheTimeout = 1800 80 initializecache() 81 initializeDatabase() 82 // nats.MB_NATS_CONN, err = nats.ConnectNATSServer() 83 84 initializedDocuments() 85 86 // initializeIACMessageBus() 87 wg.Add(1) 88 go func() { 89 defer wg.Done() 90 com.IACMessageBusClient, err = signalr.Connect(com.SingalRConfig) 91 if err != nil { 92 // fmt.Errorf("Failed to connect to IAC Message Bus: %v", err) 93 ilog.Error(fmt.Sprintf("Failed to connect to IAC Message Bus: %v", err)) 94 } 95 fmt.Printf("IAC Message Bus: %v", com.IACMessageBusClient) 96 ilog.Debug(fmt.Sprintf("IAC Message Bus: %v", com.IACMessageBusClient)) 97 }() 98 wg.Add(1) 99 go func() { 100 defer wg.Done() 101 ilog.Debug("Register the trancode execution interface") 102 tfr := trancode.TranFlowstr{} 103 callback_mgr.RegisterCallBack("TranCode_Execute", tfr.Execute) 104 105 }() 106 107 // integration point 108 109 //initializeMqttClient() 110 // initializeOPCClient() 111 112 //initializeKafka() 113 114 //initializeActiveMQConnection() 115 116 fmt.Printf("initialize end time: %v", time.Now()) 117 Initialized = true 118 } 119 120 // initializeDatabase initializes the database connection based on the configuration provided in the global configuration. 121 // It sets the database type, connection string, maximum idle connections, and maximum open connections. 122 // If any required configuration is missing or if there is an error connecting to the database, an error is logged. 123 func initializeDatabase() { 124 // function execution start time 125 startTime := time.Now() 126 127 // defer function to log the performance duration of initializeDatabase 128 defer func() { 129 elapsed := time.Since(startTime) 130 ilog.PerformanceWithDuration("main.initializeDatabase", elapsed) 131 }() 132 133 ilog.Debug("initialize Database") 134 databaseconfig := config.GlobalConfiguration.DatabaseConfig 135 136 // check if database type is missing 137 if databaseconfig["type"] == nil { 138 ilog.Error(fmt.Sprintf("initialize Database error: %s", "DatabaseType is missing")) 139 return 140 } 141 142 // check if database connection is missing 143 if databaseconfig["connection"] == nil { 144 ilog.Error(fmt.Sprintf("initialize Database error: %s", "DatabaseConnection is missing")) 145 return 146 } 147 148 // set the database type and connection string 149 dbconn.DatabaseType = databaseconfig["type"].(string) 150 dbconn.DatabaseConnection = databaseconfig["connection"].(string) 151 152 // set the maximum idle connections, default to 5 if not provided or if the value is not a float64 153 if databaseconfig["maxidleconns"] == nil { 154 dbconn.MaxIdleConns = 5 155 } else { 156 if v, ok := databaseconfig["maxidleconns"].(float64); ok { 157 dbconn.MaxIdleConns = int(v) 158 } else { 159 dbconn.MaxIdleConns = 5 160 } 161 } 162 163 // set the maximum open connections, default to 10 if not provided or if the value is not a float64 164 if databaseconfig["maxopenconns"] == nil { 165 dbconn.MaxOpenConns = 10 166 } else { 167 if v, ok := databaseconfig["maxopenconns"].(float64); ok { 168 dbconn.MaxOpenConns = int(v) 169 } else { 170 dbconn.MaxOpenConns = 10 171 } 172 } 173 174 // connect to the database 175 err := dbconn.ConnectDB() 176 if err != nil { 177 ilog.Error(fmt.Sprintf("initialize Database error: %s", err.Error())) 178 } 179 } 180 181 // initializecache initializes the cache based on the configuration provided in the global configuration. 182 // It checks the cache adapter and interval in the configuration and sets the session cache timeout accordingly. 183 // Depending on the cache adapter, it creates a new cache instance with the corresponding configuration. 184 // If the cache adapter is not recognized, it falls back to the default cache adapter with the session cache timeout. 185 // If there is an error initializing the cache, an error is logged. 186 func initializecache() { 187 startTime := time.Now() 188 defer func() { 189 elapsed := time.Since(startTime) 190 ilog.PerformanceWithDuration("main.initializecache", elapsed) 191 }() 192 /* 193 type cacheconfigstruct struct { 194 Adapter string 195 Interval int 196 } 197 var cache cacheconfigstruct 198 199 err := json.Unmarshal(cacheConfig, &cache) 200 if err != nil { 201 ilog.Error(fmt.Sprintf("initialize cache error: %s", err.Error())) 202 } */ 203 ilog.Debug("initialize Chche") 204 205 cacheConfig := config.GlobalConfiguration.CacheConfig 206 207 ilog.Debug(fmt.Sprintf("initialize cache, %v", cacheConfig)) 208 209 if cacheConfig["adapter"] == nil { 210 ilog.Error(fmt.Sprintf("initialize cache error: %s", "CacheType is missing")) 211 cacheConfig["adapter"] = "memory" 212 } 213 if cacheConfig["interval"] == nil { 214 ilog.Error(fmt.Sprintf("initialize cache error: %s", "CacheTTL is missing")) 215 cacheConfig["interval"] = 3600 216 } 217 218 if v, ok := cacheConfig["interval"].(float64); ok { 219 220 config.SessionCacheTimeout = v 221 } else { 222 config.SessionCacheTimeout = 3600 223 } 224 225 if cacheConfig["objectinterval"] == nil { 226 ilog.Error(fmt.Sprintf("initialize cache error: %s", "CacheTTL is missing")) 227 cacheConfig["objectinterval"] = 3600 228 } 229 230 if v, ok := cacheConfig["objectinterval"].(float64); ok { 231 232 config.ObjectCacheTimeout = v 233 } else { 234 config.ObjectCacheTimeout = 3600 235 } 236 237 if cacheConfig["testsessiontimeout"] == nil { 238 ilog.Error(fmt.Sprintf("initialize testsessiontimeout cache error: %s", "CacheTTL is missing")) 239 cacheConfig["testsessiontimeout"] = 1800 240 } 241 242 if v, ok := cacheConfig["testsessiontimeout"].(float64); ok { 243 244 config.TestSessionCacheTimeout = v 245 } else { 246 config.TestSessionCacheTimeout = 1800 247 } 248 // fmt.Printf("CacheType: %s, CacheTTL: %d", cacheConfig["adapter"], config.SessionCacheTimeout) 249 ilog.Debug(fmt.Sprintf("initialize cache with the configuration, %v", cacheConfig)) 250 ilog.Debug(fmt.Sprintf("SessionCacheinterval: %v, ObjectCacheTimeOut: %v, TestSessionCacheTimeOut: %v", config.SessionCacheTimeout, config.ObjectCacheTimeout, config.TestSessionCacheTimeout)) 251 252 switch cacheConfig["adapter"] { 253 case "memcache": 254 conn := "127.0.0.1:11211" 255 if cacheConfig["memcache"] != nil { 256 memcachecfg := cacheConfig["memcache"].(map[string]interface{}) 257 if memcachecfg["conn"] != nil { 258 conn = memcachecfg["conn"].(string) 259 } 260 } 261 config.SessionCache, err = cache.NewCache(cacheConfig["adapter"].(string), fmt.Sprintf(`{"conn":"%s"}`, conn)) 262 if err != nil { 263 ilog.Error(fmt.Sprintf("initialize Session cache error: %s", err.Error())) 264 } 265 266 case "redis": 267 key := "IAC_Cache" 268 conn := "6379" 269 dbNum := 0 270 password := "" 271 if cacheConfig["redis"] != nil { 272 rediscfg := cacheConfig["redis"].(map[string]interface{}) 273 if rediscfg["key"] != nil { 274 key = rediscfg["key"].(string) 275 } 276 if rediscfg["conn"] != nil { 277 conn = rediscfg["conn"].(string) 278 } 279 if rediscfg["dbNum"] != nil { 280 dbNum = int(rediscfg["dbNum"].(float64)) 281 } 282 if rediscfg["password"] != nil { 283 password = rediscfg["password"].(string) 284 } 285 } 286 config.SessionCache, err = cache.NewCache(cacheConfig["adapter"].(string), fmt.Sprintf(`{"key":"%s","conn":"%s","dbNum":%d,"password":"%s"}`, key, conn, dbNum, password)) 287 if err != nil { 288 ilog.Error(fmt.Sprintf("initialize Session cache error: %s", err.Error())) 289 } 290 291 case "file": 292 CachePath := "" 293 DirectoryLevel := 2 294 FileSuffix := ".cache" 295 EmbedExpiry := 0 296 if cacheConfig["file"] != nil { 297 filecfg := cacheConfig["file"].(map[string]interface{}) 298 299 if filecfg["CachePath"] != nil { 300 CachePath = filecfg["CachePath"].(string) 301 } 302 303 if filecfg["DirectoryLevel"] != nil { 304 DirectoryLevel = int(filecfg["DirectoryLevel"].(float64)) 305 } 306 307 if filecfg["FileSuffix"] != nil { 308 FileSuffix = filecfg["FileSuffix"].(string) 309 } 310 311 if filecfg["EmbedExpiry"] != nil { 312 EmbedExpiry = int(filecfg["EmbedExpiry"].(float64)) 313 } 314 } 315 316 config.SessionCache, err = cache.NewCache(cacheConfig["adapter"].(string), fmt.Sprintf(`{"CachePath":"%s","FileSuffix":"%s","DirectoryLevel":"%d","EmbedExpiry":"%d"}`, CachePath, FileSuffix, DirectoryLevel, EmbedExpiry)) 317 // ilog.Debug(fmt.Sprintf("initialize cache with the configuration, %v", cacheConfig)) 318 319 if err != nil { 320 ilog.Error(fmt.Sprintf("initialize cache error: %s", err.Error())) 321 } 322 case "documentdb": 323 conn := "mongodb://localhost:27017" 324 db := "IAC_Cache" 325 collection := "cache" 326 if cacheConfig["documentdb"] != nil { 327 documentdbcfg := cacheConfig["documentdb"].(map[string]interface{}) 328 if documentdbcfg["conn"] != nil { 329 conn = documentdbcfg["conn"].(string) 330 } 331 if documentdbcfg["db"] != nil { 332 db = documentdbcfg["db"].(string) 333 } 334 if documentdbcfg["collection"] != nil { 335 collection = documentdbcfg["collection"].(string) 336 } 337 } 338 //cachedb.Initalize() 339 config.SessionCache, err = cache.NewCache(cacheConfig["adapter"].(string), fmt.Sprintf(`{"conn":"%s","db":"%s","collection":"%s"}`, conn, db, collection)) 340 if err != nil { 341 ilog.Error(fmt.Sprintf("initialize Session cache error: %s", err.Error())) 342 } 343 344 case "memory": 345 interval := config.SessionCacheTimeout 346 config.SessionCache, err = cache.NewCache(cacheConfig["adapter"].(string), fmt.Sprintf(`{"interval":%v}`, interval)) 347 if err != nil { 348 ilog.Error(fmt.Sprintf("initialize cache error: %s", err.Error())) 349 } 350 351 default: 352 interval := config.SessionCacheTimeout 353 config.SessionCache, err = cache.NewCache("memory", fmt.Sprintf(`{"interval":%v}`, interval)) 354 if err != nil { 355 ilog.Error(fmt.Sprintf("initialize cache error: %s", err.Error())) 356 } 357 358 } 359 config.ObjectCache = config.SessionCache 360 config.TestSessionCache = config.SessionCache 361 } 362 363 // initializeloger initializes the logger based on the global configuration. 364 // It checks if the log configuration is missing and prints the log configuration. 365 // Then, it calls the logger.Init function with the log configuration. 366 func initializeloger() error { 367 if config.GlobalConfiguration.LogConfig == nil { 368 return fmt.Errorf("log configuration is missing") 369 } 370 fmt.Printf("log configuration: %v", config.GlobalConfiguration.LogConfig) 371 logger.Init(config.GlobalConfiguration.LogConfig) 372 return nil 373 } 374 375 // initializedDocuments initializes the documents for the application. 376 // It retrieves the document configuration from the global configuration and connects to the specified database. 377 // If any required configuration is missing, it logs an error and returns. 378 379 func initializedDocuments() { 380 startTime := time.Now() 381 defer func() { 382 elapsed := time.Since(startTime) 383 ilog.PerformanceWithDuration("main.initializedDocuments", elapsed) 384 }() 385 386 if config.GlobalConfiguration.DocumentConfig == nil { 387 fmt.Errorf("documentdb configuration is missing") 388 return 389 } 390 391 documentsConfig := config.GlobalConfiguration.DocumentConfig 392 393 ilog.Debug(fmt.Sprintf("initialize Documents, %v", documentsConfig)) 394 395 var DatabaseType = documentsConfig["type"].(string) // "mongodb" 396 var DatabaseConnection = documentsConfig["connection"].(string) //"mongodb://localhost:27017" 397 var DatabaseName = documentsConfig["database"].(string) //"IAC_CFG" 398 399 if DatabaseType == "" { 400 ilog.Error(fmt.Sprintf("initialize Documents error: %s", "DatabaseType is missing")) 401 return 402 } 403 if DatabaseConnection == "" { 404 ilog.Error(fmt.Sprintf("initialize Documents error: %s", "DatabaseConnection is missing")) 405 return 406 } 407 if DatabaseName == "" { 408 ilog.Error(fmt.Sprintf("initialize Documents error: %s", "DatabaseName is missing")) 409 return 410 } 411 412 documents.ConnectDB(DatabaseType, DatabaseConnection, DatabaseName) 413 414 } 415 416 // initializeMqttClient initializes the MQTT clients by reading the configuration file "mqttconfig.json" and creating MqttClient instances based on the configuration. 417 // It populates the config.MQTTClients map with the created MqttClient instances. 418 // The function also logs debug information about the configuration and created MQTT clients. 419 // It measures the performance duration of the function using the ilog.PerformanceWithDuration function. 420 421 func initializeMqttClient() { 422 startTime := time.Now() 423 defer func() { 424 elapsed := time.Since(startTime) 425 ilog.PerformanceWithDuration("main.initializeMqttClient", elapsed) 426 }() 427 428 // config.MQTTClients = make(map[string]*mqttclient.MqttClient) 429 430 wg.Add(1) 431 go func() { 432 defer wg.Done() 433 434 ilog.Debug("initialize MQTT Client") 435 436 data, err := ioutil.ReadFile("mqttconfig.json") 437 if err != nil { 438 ilog.Debug(fmt.Sprintf("failed to read configuration file: %v", err)) 439 440 } 441 ilog.Debug(fmt.Sprintf("MQTT Clients configuration file: %s", string(data))) 442 var mqttconfig mqttclient.MqttConfig 443 err = json.Unmarshal(data, &mqttconfig) 444 if err != nil { 445 ilog.Debug(fmt.Sprintf("failed to unmarshal the configuration file: %v", err)) 446 447 } 448 ilog.Debug(fmt.Sprintf("MQTT Clients configuration: %v", logger.ConvertJson(mqttconfig))) 449 i := 1 450 for _, mqttcfg := range mqttconfig.Mqtts { 451 ilog.Debug(fmt.Sprintf("MQTT Client configuration: %s", logger.ConvertJson(mqttcfg))) 452 mqtc := mqttclient.NewMqttClient(mqttcfg) 453 // fmt.Println("MQTT Client: %v", mqtc) 454 // ilog.Debug(fmt.Sprintf("MQTT Client: %v", mqtc)) 455 // config.MQTTClients[fmt.Sprintf("mqttclient_%d", i)] = mqtc 456 mqtc.Initialize_mqttClient() 457 // fmt.Sprintln("MQTT Client: %v", config.MQTTClients) 458 // ilog.Debug(fmt.Sprintf("MQTT Client: %v", config.MQTTClients)) 459 i++ 460 } 461 462 fmt.Println("MQTT Clients: %v, %d", config.MQTTClients, i) 463 ilog.Debug(fmt.Sprintf("MQTT Clients: %v, %d", config.MQTTClients, i)) 464 }() 465 466 } 467 468 /* 469 func initializeOPCClient() { 470 wg.Add(1) 471 go func() { 472 defer wg.Done() 473 ilog.Debug("initialize OPC Client") 474 data, err := ioutil.ReadFile("opcuaclient.json") 475 if err != nil { 476 ilog.Debug(fmt.Sprintf("failed to read configuration file: %v", err)) 477 478 } 479 ilog.Debug(fmt.Sprintf("OPC UA Clients configuration file: %s", string(data))) 480 481 var config opcclient.OPCConfig 482 483 err = json.Unmarshal(data, &config) 484 485 if err != nil { 486 ilog.Debug(fmt.Sprintf("failed to unmarshal the configuration file: %v", err)) 487 } 488 for _, opcuaclient := range config.OPCClients { 489 ilog.Debug(fmt.Sprintf("OPC UA Client configuration: %s", logger.ConvertJson(opcuaclient))) 490 opcclient.Initialize(opcuaclient) 491 } 492 }() 493 } */ 494 495 // initializeIACMessageBus initializes the IAC message bus. 496 // It starts a goroutine to handle the initialization process. 497 // The function measures the performance duration and logs it using ilog.PerformanceWithDuration. 498 // The function also logs debug information about the IAC message bus configuration and channel. 499 func initializeIACMessageBus() { 500 startTime := time.Now() 501 defer func() { 502 elapsed := time.Since(startTime) 503 ilog.PerformanceWithDuration("main.initializeIACMessageBus", elapsed) 504 }() 505 506 wg.Add(1) 507 go func() { 508 ilog.Debug("initialize IAC Message Bus") 509 defer wg.Done() 510 511 // iacmb.Initialize() 512 513 /* iacmb.Initialize(8888, "IAC") 514 515 ilog.Debug(fmt.Sprintf("IAC Message bus: %v", iacmb.IACMB)) 516 517 iacmb.IACMB.Channel.OnRead(func(data string) { 518 ilog.Debug(fmt.Sprintf("IAC Message bus channel read: %s", data)) 519 }) 520 521 iacmb.IACMB.Channel.Write("Start the Message bus channel IAC") 522 523 data := map[string]interface{}{"name": "IAC", "type": "messagebus", "port": 8888, "channel": "IAC"} 524 iacmb.IACMB.Channel.Write(logger.ConvertJson(data)) 525 iacmb.IACMB.Channel.Write("Start the Message bus channel IAC") */ 526 }() 527 } 528 529 func initializeKafka() { 530 startTime := time.Now() 531 defer func() { 532 elapsed := time.Since(startTime) 533 ilog.PerformanceWithDuration("main.initializeKafka", elapsed) 534 }() 535 536 config.Kakfas = make(map[string]*kafka.KafkaConsumer) 537 538 wg.Add(1) 539 go func() { 540 defer wg.Done() 541 542 ilog.Debug("initialize Kafka Connection") 543 544 data, err := ioutil.ReadFile("kafkaconfig.json") 545 if err != nil { 546 ilog.Debug(fmt.Sprintf("failed to read configuration file: %v", err)) 547 return 548 } 549 ilog.Debug(fmt.Sprintf("Kafka conenction configuration file: %s", string(data))) 550 var kafkacfgs kafka.KafkasConfig 551 552 err = json.Unmarshal(data, &kafkacfgs) 553 if err != nil { 554 ilog.Debug(fmt.Sprintf("failed to unmarshal the configuration file: %v", err)) 555 556 } 557 ilog.Debug(fmt.Sprintf("Kafka Connection configuration: %v", logger.ConvertJson(kafkacfgs))) 558 i := 1 559 for _, kafakacfg := range kafkacfgs.Kafkas { 560 ilog.Debug(fmt.Sprintf("Single Kafka Connection configuration: %s", logger.ConvertJson(kafakacfg))) 561 kafkacon := kafka.NewKafkaConsumer(kafakacfg) 562 563 config.Kakfas[fmt.Sprintf("activemq_%d", i)] = kafkacon 564 565 i++ 566 } 567 568 ilog.Debug(fmt.Sprintf("Kafka Connections: %v, %d", config.Kakfas, i)) 569 }() 570 571 } 572 573 func initializeActiveMQConnection() { 574 startTime := time.Now() 575 defer func() { 576 elapsed := time.Since(startTime) 577 ilog.PerformanceWithDuration("main.initializeActiveMQConnection", elapsed) 578 }() 579 580 config.ActiveMQs = make(map[string]*activemq.ActiveMQ) 581 582 wg.Add(1) 583 go func() { 584 defer wg.Done() 585 586 ilog.Debug("initialize ActiveMQ Connection") 587 588 data, err := ioutil.ReadFile("activemqconfig.json") 589 if err != nil { 590 ilog.Debug(fmt.Sprintf("failed to read configuration file: %v", err)) 591 return 592 } 593 ilog.Debug(fmt.Sprintf("ActiveMQ conenction configuration file: %s", string(data))) 594 var activemqconfigs activemq.ActiveMQconfigs 595 596 err = json.Unmarshal(data, &activemqconfigs) 597 if err != nil { 598 ilog.Debug(fmt.Sprintf("failed to unmarshal the configuration file: %v", err)) 599 600 } 601 ilog.Debug(fmt.Sprintf("ActiveMQ Connection configuration: %v", logger.ConvertJson(activemqconfigs))) 602 i := 1 603 for _, activemqcfg := range activemqconfigs.ActiveMQs { 604 ilog.Debug(fmt.Sprintf("Single ActiveMQ Connection configuration: %s", logger.ConvertJson(activemqcfg))) 605 activemqconn := activemq.NewActiveMQConnection(activemqcfg) 606 607 config.ActiveMQs[fmt.Sprintf("activemq_%d", i)] = activemqconn 608 i++ 609 } 610 611 ilog.Debug(fmt.Sprintf("ActiveMQ Connections: %v, %d", config.ActiveMQs, i)) 612 }() 613 614 }