private async Task RunAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { RbTraceLog.WriteLog("Working"); await Task.Delay(1000); } }
Task IEventProcessor.OpenAsync(PartitionContext context) { RbTraceLog.Initialize(rbTraceStorageConnString, rbTraceTableName, "CloudRoboticsFX"); string msg = string.Format("RoboticsEventProcessor initialize. Partition:{0}, Offset:{1}", context.Lease.PartitionId, context.Lease.Offset); RbTraceLog.WriteLog(msg); return(Task.FromResult <object>(null)); }
public override void OnStop() { RbTraceLog.WriteLog("CloudRoboticsWoker is stopping"); this.runCompleteEvent.Set(); eventProcessorHost.UnregisterEventProcessorAsync().Wait(); base.OnStop(); RbTraceLog.WriteLog("CloudRoboticsWoker has stopped"); }
public override void Run() { RbTraceLog.WriteLog("CloudRoboticsWoker is running"); // Delete archived DLL directory string archivedDirectory = Environment.CurrentDirectory + @"\" + archivedDirectoryName; if (Directory.Exists(archivedDirectory)) { Directory.Delete(archivedDirectory, true); } // Event Processor Host eventProcessorHost.RegisterEventProcessorAsync <RoboticsEventProcessor>(); //Wait for shutdown to be called, else the role will recycle this.runCompleteEvent.WaitOne(); }
JArray ProcessControlMessage(RbHeader rbh) { JArray ja_messages = new JArray(); try { RbAppMasterCache rbappmc = GetAppMasterInfo(rbh); RbMessage message = new RbMessage(); message.RbHeader = rbh; message.RbBody = JsonConvert.DeserializeObject <JObject>(rbappmc.AppInfoDevice); string json_message = JsonConvert.SerializeObject(message); JObject jo = (JObject)JsonConvert.DeserializeObject(json_message); ja_messages.Add(jo); } catch (Exception ex) { RbTraceLog.WriteError("E004", ex.ToString()); ae = new ApplicationException("Error ** <<CONTROL Message Processing>> Exception occured during JSON processing on RBFX.AppMaster[AppInfoDevice]"); throw ae; } return(ja_messages); }
private async Task ProcessMessage(EventData eventData, long partitionKey, RbTraceLog rbTraceLog) { // Receive a message and system properties string iothub_deviceId = (string)eventData.SystemProperties["iothub-connection-device-id"]; DateTime iothub_enqueuedTimeUtc = (DateTime)eventData.SystemProperties.EnqueuedTimeUtc; string text_message = Encoding.UTF8.GetString(eventData.Body.Array); // RbTrace (Table Storage) if (rbTraceLevel == RbTraceType.Detail) { rbTraceLog.WriteLog($"Received a message. Partition({partitionKey}), DeviceId({iothub_deviceId}), Message:{text_message}"); } // Loop of retry for reconfiguration on SQL Database int loopCounter = 0; while (true) { JObject jo_message = null; // Routing switch bool devRouting = false; bool appRouting = false; try { // Check RbHeader if (text_message.IndexOf(RbFormatType.RbHeader) < 0) { rbTraceLog.WriteLog(RbExceptionMessage.RbHeaderNotFound + $" Partition({partitionKey}), DeviceId({iothub_deviceId}), Message:{text_message}"); return; } // Check RbHeader simplly jo_message = JsonConvert.DeserializeObject <JObject>(text_message); var jo_rbh = (JObject)jo_message[RbFormatType.RbHeader]; var v_rbhRoutingType = jo_rbh[RbHeaderElement.RoutingType]; if (v_rbhRoutingType == null) { rbTraceLog.WriteError("W001", "** Message skipped because RoutingType is null **", jo_message); return; } string s_rbhRoutingType = (string)v_rbhRoutingType; if (s_rbhRoutingType == RbRoutingType.LOG || s_rbhRoutingType == string.Empty) { // RoutingType == LOG -> only using IoT Hub with Stream Analytics return; } // Check RbHeader in detail RbHeaderBuilder hdBuilder = new RbHeaderBuilder(jo_message, iothub_deviceId); RbHeader rbh = null; try { rbh = hdBuilder.ValidateJsonSchema(); } catch (Exception ex) { rbTraceLog.WriteError("W002", "** Message skipped because of bad RbHeader **", ex); return; } // Check StorageQueueSendEnabled property in RbHeader prevStorageQueueSendEnabled = storageQueueSendEnabled; string messageStorageQueueSendEnabled = null; if (storageQueueSendEnabled != "true") { try { messageStorageQueueSendEnabled = (string)jo_rbh[typeStorageQueueSendEnabled]; } catch { messageStorageQueueSendEnabled = null; } if (messageStorageQueueSendEnabled == "true") { storageQueueSendEnabled = messageStorageQueueSendEnabled; } } // Check RoutingType (CALL, D2D, CONTROL) if (rbh.RoutingType == RbRoutingType.CALL || rbh.RoutingType == RbRoutingType.CALL_ASYNC) { appRouting = true; } else if (rbh.RoutingType == RbRoutingType.D2D) { devRouting = true; if (rbh.AppProcessingId != string.Empty) { appRouting = true; } } else if (rbh.RoutingType == RbRoutingType.CONTROL) { devRouting = false; appRouting = false; } else { rbTraceLog.WriteError("W003", "** Message skipped because of bad RoutingType **", jo_message); return; } // Device Router builds RbHeader DeviceRouter dr = null; if (devRouting) { dr = new DeviceRouter(rbh, sqlConnectionString); rbh = dr.GetDeviceRouting(); string new_header = JsonConvert.SerializeObject(rbh); jo_message[RbFormatType.RbHeader] = JsonConvert.DeserializeObject <JObject>(new_header); } else { rbh.TargetDeviceId = rbh.SourceDeviceId; rbh.TargetType = RbTargetType.Device; } // Application Routing JArray ja_messages = null; if (appRouting) { // Application Call Logic JObject jo_temp; string rbBodyString; try { jo_temp = (JObject)jo_message[RbFormatType.RbBody]; rbBodyString = JsonConvert.SerializeObject(jo_temp); } catch (Exception ex) { rbTraceLog.WriteError("E001", $"** RbBody is not regular JSON format ** {ex.ToString()}", jo_message); return; } try { if (rbh.RoutingType == RbRoutingType.CALL_ASYNC) { await CallAppsWithQueue(rbh, rbBodyString, partitionKey.ToString()); } else { ja_messages = await CallAppsWithHttp(rbh, rbBodyString, partitionKey.ToString()); } } catch (Exception ex) { rbTraceLog.WriteError("E002", $"** Error occured in CallApps ** {ex.ToString()}", jo_message); return; } } else { ja_messages = new JArray(); ja_messages.Add(jo_message); } // Send C2D Message if (rbh.RoutingType == RbRoutingType.CALL || rbh.RoutingType == RbRoutingType.D2D || rbh.RoutingType == RbRoutingType.CONTROL) { if (storageQueueSendEnabled == "true") { // Send C2D message to Queue storage RbC2dMessageToQueue c2dsender = null; c2dsender = new RbC2dMessageToQueue(ja_messages, storageQueueConnString, sqlConnectionString); await c2dsender.SendToDeviceAsync(); } else { // Send C2D message to IoT Hub RbC2dMessageSender c2dsender = null; c2dsender = new RbC2dMessageSender(ja_messages, iotHubConnectionString, sqlConnectionString); await c2dsender.SendToDeviceAsync(); } // StorageQueueSendEnabled property in RbHeader storageQueueSendEnabled = prevStorageQueueSendEnabled; } // Get out of retry loop because of normal completion break; } catch (Exception ex) { rbTraceLog.WriteError("E003", $"** Critical error occured ** {ex.ToString()}", jo_message); bool continueLoop = false; if (ex != null && ex is SqlException) { foreach (SqlError error in (ex as SqlException).Errors) { if (sqlErrorListForRetry.Contains(error.Number)) { continueLoop = true; break; // Exit foreach loop } } if (continueLoop) { ++loopCounter; rbTraceLog.WriteLog($"Transaction retry has started. Count({loopCounter})"); if (loopCounter > maxLoopCounter) { break; // Get out of retry loop because counter reached max number } else { Thread.Sleep(sleepInterval); } } else { break; // Get out of retry loop because of another sql error } } else { throw; } } } }
/// <summary> /// This is a main entry point of Service replica. /// This method can be executable when the replica is primary. /// </summary> /// <param name="cancellationToken">When Service Fabric needs to shutdown this Service replica, it is cancelled.</param> protected override async Task RunAsync(CancellationToken cancellationToken) { // Environment variables InitializeSetting(); // Initialize RbTraceLog rbTraceLog = new RbTraceLog(rbTraceStorageConnString, rbTraceStorageTableName, "CloudRoboticsFx3", this.Context.TraceId.ToString()); rbTraceLog.CreateLogTableIfNotExists(); // These Reliable Dictionaries are used to keep track of our position in IoT Hub. // If this service fails over, this will allow it to pick up where it left off in the event stream. IReliableDictionary <string, string> offsetDictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <string, string> >(OffsetDictionaryName); IReliableDictionary <string, long> epochDictionary = await this.StateManager.GetOrAddAsync <IReliableDictionary <string, long> >(EpochDictionaryName); // Each partition of this service corresponds to a partition in IoT Hub. // IoT Hub partitions are numbered 0..n-1, up to n = 32. // This service needs to use an identical partitioning scheme. // The low key of every partition corresponds to an IoT Hub partition. Int64RangePartitionInformation partitionInfo = (Int64RangePartitionInformation)this.Partition.PartitionInfo; long servicePartitionKey = partitionInfo.LowKey; EventHubClient client = null; PartitionReceiver partitionReceiver = null; int retryCount = 0; try { // ETW Trace ServiceEventSource.Current.ServiceMessage(this.Context, $"CloudRoboFxSvc has started. Partition({servicePartitionKey})"); // RbTrace (Table Storage) rbTraceLog.WriteLog($"CloudRoboFxSvc has started. Partition({servicePartitionKey})"); // Get a partitionReceiver with EventHubClient. // The partitionReceiver is used to get events from IoT Hub. client = EventHubClient.CreateFromConnectionString(compatibleEventHubConnString); partitionReceiver = await this.ConnectToIoTHubAsync(client, iotHubConsumerGroup, servicePartitionKey, epochDictionary, offsetDictionary); string previousOffset = string.Empty; // Loop of Processing EventData while (true) { cancellationToken.ThrowIfCancellationRequested(); try { int maxReceivedBatchSize = 50; int maxWaitTimeMilliSec = 5000; IEnumerable <EventData> receivedEvents = await partitionReceiver.ReceiveAsync(maxReceivedBatchSize, TimeSpan.FromMilliseconds(maxWaitTimeMilliSec)); if (receivedEvents == null) { continue; } // Process event data foreach (var eventData in receivedEvents) { await ProcessMessage(eventData, servicePartitionKey, rbTraceLog); // Save the current Iot Hub data stream offset. // This will allow the service to pick up from its current location if it fails over. // Duplicate device messages may still be sent to the the tenant service // if this service fails over after the message is sent but before the offset is saved. ServiceEventSource.Current.ServiceMessage(this.Context, "Saving offset {0}", eventData.SystemProperties.Offset); using (ITransaction tx = this.StateManager.CreateTransaction()) { await offsetDictionary.SetAsync(tx, "offset", eventData.SystemProperties.Offset); await tx.CommitAsync(); } } } catch (TimeoutException te) { // transient error. Retry. ServiceEventSource.Current.ServiceMessage(this.Context, $"TimeoutException in RunAsync: {te.ToString()}"); rbTraceLog.WriteError("E004", $"** TimeoutException in RunAsync ** {te.ToString()}"); } catch (FabricTransientException fte) { // transient error. Retry. ServiceEventSource.Current.ServiceMessage(this.Context, $"FabricTransientException in RunAsync: {fte.ToString()}"); rbTraceLog.WriteError("E005", $"** FabricTransientException in RunAsync ** {fte.ToString()}"); } catch (FabricNotPrimaryException) { // not primary any more, time to quit. rbTraceLog.WriteError("E006", $"** FabricNotPrimaryException in RunAsync **"); return; } catch (Exception ex) { if (ex is ServerBusyException || ex is TimeoutException) { ++retryCount; if (retryCount > maxEventProcessingRetryCount) { throw; } rbTraceLog.WriteLog("** Retrying to open IoT Hub connection... **"); if (partitionReceiver != null) { try { await partitionReceiver.CloseAsync(); } catch { /* None */ } partitionReceiver = null; } await Task.Delay(new TimeSpan(0, 0, 5)); partitionReceiver = await this.ConnectToIoTHubAsync(client, iotHubConsumerGroup, servicePartitionKey, epochDictionary, offsetDictionary); previousOffset = string.Empty; continue; } else { ServiceEventSource.Current.ServiceMessage(this.Context, ex.ToString()); rbTraceLog.WriteError("E007", $"** Critical error occured ** {ex.ToString()}"); throw; } } } } finally { if (partitionReceiver != null) { await partitionReceiver.CloseAsync(); } } }
public override bool OnStart() { // Max connection Limit ServicePointManager.DefaultConnectionLimit = 16; // Get properties iotHubConnectionString = CloudConfigurationManager.GetSetting("IoTHub.ConnectionString"); iotHubClassicConnString = CloudConfigurationManager.GetSetting("IoTHub.ClassicConnectionString"); int pos = iotHubClassicConnString.IndexOf("sb://"); if (pos == 0) { int pos2 = iotHubConnectionString.IndexOf("SharedAccessKeyName="); string sharedAccessKey = iotHubConnectionString.Substring(pos2); iotHubClassicConnString = "Endpoint=" + iotHubClassicConnString + ";" + sharedAccessKey; } iotHubName = CloudConfigurationManager.GetSetting("IoTHub.HubName"); iotHubConsumerGroupName = CloudConfigurationManager.GetSetting("IoTHub.ConsumerGroupName"); storageAccountName = CloudConfigurationManager.GetSetting("IoTHub.StorageAccountName"); storageAccountKey = CloudConfigurationManager.GetSetting("IoTHub.StorageAccountKey"); storageConnectionString = string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", storageAccountName, storageAccountKey); storageQueueSendEnabled = CloudConfigurationManager.GetSetting("StorageQueue.SendEnabled"); c2dLogEnabled = CloudConfigurationManager.GetSetting("RbC2dLog.Enable"); traceStorageAccountName = CloudConfigurationManager.GetSetting("RbTrace.StorageAccountName"); traceStorageAccountKey = CloudConfigurationManager.GetSetting("RbTrace.StorageAccountKey"); traceStorageConnectionString = string.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}", traceStorageAccountName, traceStorageAccountKey); traceTableName = CloudConfigurationManager.GetSetting("RbTrace.StorageTableName"); traceLevel = CloudConfigurationManager.GetSetting("RbTrace.TraceLevel"); // Set properties to Event Processor if (c2dLogEnabled != null && c2dLogEnabled.ToLower() == "true") { RoboticsEventProcessor.rbC2dLogEnabled = true; RoboticsEventProcessor.rbC2dLogEventHubConnString = CloudConfigurationManager.GetSetting("RbC2dLog.EventHubConnString"); RoboticsEventProcessor.rbC2dLogEventHubName = CloudConfigurationManager.GetSetting("RbC2dLog.EventHubName"); } else { RoboticsEventProcessor.rbC2dLogEnabled = false; } RoboticsEventProcessor.rbTraceStorageConnString = traceStorageConnectionString; RoboticsEventProcessor.rbTraceTableName = traceTableName; RoboticsEventProcessor.rbTraceLevel = traceLevel; RoboticsEventProcessor.rbIotHubConnString = iotHubConnectionString; if (storageQueueSendEnabled != null && storageQueueSendEnabled.ToLower() == "true") { RoboticsEventProcessor.rbStorageQueueSendEnabled = true; RoboticsEventProcessor.rbStorageQueueConnString = storageConnectionString; } else { RoboticsEventProcessor.rbStorageQueueSendEnabled = false; } RoboticsEventProcessor.rbSqlConnectionString = CloudConfigurationManager.GetSetting("SqlConnectionString"); RoboticsEventProcessor.rbEncPassPhrase = CloudConfigurationManager.GetSetting("RbEnc.PassPhrase"); RoboticsEventProcessor.rbCacheExpiredTimeSec = int.Parse(CloudConfigurationManager.GetSetting("RbCache.ExpiredTimeSec")); RoboticsEventProcessor.archivedDirectoryName = archivedDirectoryName; // Event Processor Host string eventProcessorHostName = RoleEnvironment.CurrentRoleInstance.Id; eventProcessorHost = new EventProcessorHost(eventProcessorHostName, iotHubName, iotHubConsumerGroupName, iotHubClassicConnString, storageConnectionString); RbTraceLog.Initialize(traceStorageConnectionString, traceTableName, "CloudRoboticsFX"); RbTraceLog.CreateLogTableIfNotExists(); bool result = base.OnStart(); RbTraceLog.WriteLog("CloudRoboticsWorker has been started"); return(result); }
async Task IEventProcessor.ProcessEventsAsync(PartitionContext context, IEnumerable <EventData> messages) { try { #region *** Handling unexpected exceptions *** DateTime startDateTimeUtc = DateTime.UtcNow; int messagecnt = 0; bool sqlex_on = false; foreach (EventData eventData in messages) { try { // Go forward read pointer await context.CheckpointAsync(); } catch (Exception ex) { // Handling the exception of Microsoft.ServiceBus.Messaging.LeaseLostException // This exception is usually able to occur. ApplicationException ae = new ApplicationException(checkpointExMessage, ex); throw ae; } ++messagecnt; int retryCount = 0; bool devRouting = false; bool appRouting = false; bool rbHeaderNotFound = false; string sqlConnString = rbSqlConnectionString; string iothub_deviceId = (string)eventData.SystemProperties["iothub-connection-device-id"]; DateTime iothub_enqueuedTimeUtc = (DateTime)eventData.SystemProperties["EnqueuedTimeUtc"]; string text_message = string.Empty; // Retry loop logic for SQLDB reconfiguration exception while (true) { text_message = Encoding.UTF8.GetString(eventData.GetBytes()); string text_message_100 = text_message.Substring(0, 100); if (text_message_100.IndexOf(RbFormatType.RbHeader) < 0) { rbHeaderNotFound = true; RbTraceLog.WriteLog(string.Format(RbExceptionMessage.RbHeaderNotFound + " Partition:{0}, Message:{1}, DeviceId:{2}", context.Lease.PartitionId, text_message_100, iothub_deviceId)); } if (rbTraceLevel == RbTraceType.Detail) { DateTime dt = iothub_enqueuedTimeUtc; TimeSpan ts = DateTime.UtcNow - dt; RbTraceLog.WriteLog(string.Format("RoboticsEventProcessor Message received. Delayed time:{0}, Partition:{1}, DeviceId:{2}, Message:{3}", ts.ToString(), context.Lease.PartitionId, iothub_deviceId, text_message)); if (ts > new TimeSpan(0, 0, 5)) { RbTraceLog.WriteLog(string.Format("** Delayed time is over 5 seconds !! ** DelayedTime:{0}, Partition:{1}, DeviceId:{2}, Message:{3}", ts.ToString(), context.Lease.PartitionId, iothub_deviceId, text_message)); } } JObject jo_message = null; if (!rbHeaderNotFound) // Skip invalid data { try { jo_message = JsonConvert.DeserializeObject <JObject>(text_message); // Check RbHeader simplly var jo_rbh = (JObject)jo_message[RbFormatType.RbHeader]; if (jo_rbh != null) { string jo_rbh_RoutingType = (string)jo_rbh[RbHeaderElement.RoutingType]; // Check RoutingType (LOG, null) if (jo_rbh_RoutingType == null) { RbTraceLog.WriteError("W001", "** Message skipped because RoutingType is null **", jo_message); goto LoopExitLabel; } else if (jo_rbh_RoutingType == RbRoutingType.LOG) { // RoutingType == LOG -> only using IoT Hub with Stream Analytics goto LoopExitLabel; } } // Check RbHeader in detail RbHeaderBuilder hdBuilder = new RbHeaderBuilder(jo_message, iothub_deviceId); RbHeader rbh = hdBuilder.ValidateJsonSchema(); // Check RoutingType (CALL, D2D, CONTROL) if (rbh.RoutingType == RbRoutingType.CALL) { appRouting = true; } else if (rbh.RoutingType == RbRoutingType.D2D) { devRouting = true; if (rbh.AppProcessingId != string.Empty) { appRouting = true; } } else if (rbh.RoutingType == RbRoutingType.CONTROL) { devRouting = false; appRouting = false; } else { RbTraceLog.WriteError("W002", "** Message skipped because of bad RoutingType **", jo_message); goto LoopExitLabel; } // Device Router builds RbHeader DeviceRouter dr = null; if (devRouting) { dr = new DeviceRouter(rbh, sqlConnString); rbh = dr.GetDeviceRouting(); string new_header = JsonConvert.SerializeObject(rbh); jo_message[RbFormatType.RbHeader] = JsonConvert.DeserializeObject <JObject>(new_header); } else { rbh.TargetDeviceId = rbh.SourceDeviceId; rbh.TargetType = RbTargetType.Device; } // Application Routing JArray ja_messages = null; if (appRouting) { // Application Call Logic JObject jo_temp = (JObject)jo_message[RbFormatType.RbBody]; string rbBodyString = JsonConvert.SerializeObject(jo_temp); ja_messages = CallApps(rbh, rbBodyString, context.Lease.PartitionId); } else if (rbh.RoutingType != RbRoutingType.CONTROL) { ja_messages = new JArray(); ja_messages.Add(jo_message); } // RoutingType="CONTROL" and AppProcessingId="ReqAppInfo" if (rbh.RoutingType == RbRoutingType.CONTROL) { if (rbh.AppProcessingId == null) { RbTraceLog.WriteError("W003", "** Message skipped because AppProcessingId is null when CONTROL RoutingType **", jo_message); goto LoopExitLabel; } else if (rbh.AppProcessingId == RbControlType.ReqAppInfo) { ja_messages = ProcessControlMessage(rbh); } else { RbTraceLog.WriteError("W004", "** Message skipped because of bad AppProcessingId when CONTROL RoutingType **", jo_message); goto LoopExitLabel; } } // Send C2D Message if (rbh.RoutingType == RbRoutingType.CALL || rbh.RoutingType == RbRoutingType.D2D || rbh.RoutingType == RbRoutingType.CONTROL) { if (rbStorageQueueSendEnabled) { // Send C2D message to Queue storage RbC2dMessageToQueue c2dsender = null; c2dsender = new RbC2dMessageToQueue(ja_messages, rbStorageQueueConnString, sqlConnString); c2dsender.SendToDevice(); } else { // Send C2D message to IoT Hub RbC2dMessageSender c2dsender = null; c2dsender = new RbC2dMessageSender(ja_messages, rbIotHubConnString, sqlConnString); c2dsender.SendToDevice(); } } // C2D Message Logging to Event Hub if (rbC2dLogEnabled) { RbEventHubs rbEventHubs = new RbEventHubs(rbC2dLogEventHubConnString, rbC2dLogEventHubName); foreach (JObject jo in ja_messages) { string str_message = JsonConvert.SerializeObject(jo); rbEventHubs.SendMessage(str_message, iothub_deviceId); } } } catch (Exception ex) { sqlex_on = false; if (ex != null && ex is SqlException) // "is" matches extended type as well { foreach (SqlError error in (ex as SqlException).Errors) { if (sqlErrorListForRetry.Contains(error.Number)) { sqlex_on = true; break; // Exit foreach loop } } if (sqlex_on) { ++retryCount; if (retryCount > maxRetryCount) { sqlex_on = false; RbTraceLog.WriteError("E001", ex.ToString(), jo_message); } else { RbTraceLog.WriteLog($"Transaction retry has started. Count({retryCount})"); Thread.Sleep(sleepTime); } } else { RbTraceLog.WriteError("E001", ex.ToString(), jo_message); } } else { RbTraceLog.WriteError("E001", ex.ToString(), jo_message); } } } if (!sqlex_on) { goto LoopExitLabel; } } // Label - Loop exit LoopExitLabel :; if (rbTraceLevel == RbTraceType.Detail) { TimeSpan ts = DateTime.UtcNow - startDateTimeUtc; RbTraceLog.WriteLog(string.Format("RoboticsEventProcessor Message processed. Duration:{0}, Partition:{1}, DeviceId{2}, Message:{3}", ts.ToString(), context.Lease.PartitionId, iothub_deviceId, text_message)); } } #endregion *** Handling unexpected exceptions *** } catch (Exception ex) { if (ex.Message == checkpointExMessage) { RbTraceLog.WriteLog("** Retrying message processing because of CheckPointAsync error ** Info => " + ex.InnerException.ToString()); } else { RbTraceLog.WriteError("E999", ex.ToString()); } } }
CachedDllFileInfo CopyBlobToLocalDir(RbAppMasterCache rbappmc, RbAppRouterCache rbapprc, string partitionId) { //string curdir = Environment.CurrentDirectory; CachedDllFileInfo cachedDllFileInfo = new CachedDllFileInfo(); string curdir = AppDomain.CurrentDomain.BaseDirectory; cachedDllFileInfo.BaseDirectory = curdir; cachedDllFileInfo.PrivateDllDirectory = Path.Combine(curdir, "P" + partitionId); string blobTargetFilePath = string.Empty; RbAppDllCacheInfo rbAppDllInfo = null; RbAppDllCacheInfo rbAppDllInfo_partition = null; bool loadAction = true; bool blobCopyAction = true; string partitionedFileNameKey = "P" + partitionId + "_" + rbapprc.FileName; // Check original DLL info if (rbAppDllCacheInfoDic.ContainsKey(rbapprc.FileName)) { // Original DLL rbAppDllInfo = (RbAppDllCacheInfo)rbAppDllCacheInfoDic[rbapprc.FileName]; blobTargetFilePath = Path.Combine(rbAppDllInfo.CacheDir, rbAppDllInfo.CachedFileName); // Use cached original DLL if Registered_Datetime not changed. if (rbAppDllInfo.AppId == rbapprc.AppId && rbAppDllInfo.AppProcessingId == rbapprc.AppProcessingId && rbAppDllInfo.Registered_DateTime == rbapprc.Registered_DateTime) { blobCopyAction = false; } } // Check partitioned DLL info if (rbAppDllCacheInfoDic.ContainsKey(partitionedFileNameKey)) { // DLL copied into each partition directory rbAppDllInfo_partition = (RbAppDllCacheInfo)rbAppDllCacheInfoDic[partitionedFileNameKey]; cachedDllFileInfo.PrivateDllFilePath = Path.Combine(rbAppDllInfo_partition.CacheDir, rbAppDllInfo_partition.CachedFileName); // Use cached DLL copied into each partition directory if Registered_Datetime not changed. if (rbAppDllInfo_partition.AppId == rbapprc.AppId && rbAppDllInfo_partition.AppProcessingId == rbapprc.AppProcessingId && rbAppDllInfo_partition.Registered_DateTime == rbapprc.Registered_DateTime) { loadAction = false; } } if (loadAction) { if (blobTargetFilePath != string.Empty) { AppDomain appDomain = null; if (appDomainList.ContainsKey(partitionId)) { appDomain = appDomainList[partitionId]; AppDomain.Unload(appDomain); appDomainList[partitionId] = null; } if (blobCopyAction) { // Move current DLL to archive directory if (File.Exists(blobTargetFilePath)) { string archivedDirectory = Path.Combine(curdir, archivedDirectoryName); string archivedDllFilePath = archivedDirectory + @"\" + rbapprc.FileName + ".bk" + DateTime.Now.ToString("yyyyMMddHHmmssfffffff"); if (!Directory.Exists(archivedDirectory)) { Directory.CreateDirectory(archivedDirectory); } File.Move(blobTargetFilePath, archivedDllFilePath); } } } if (blobCopyAction) { // Download DLL from BLOB RbAzureStorage rbAzureStorage = new RbAzureStorage(rbappmc.StorageAccount, rbappmc.StorageKey); rbAppDllInfo = new RbAppDllCacheInfo(); rbAppDllInfo.FileName = rbapprc.FileName; rbAppDllInfo.CacheDir = Path.Combine(curdir, "cache"); if (!Directory.Exists(rbAppDllInfo.CacheDir)) { Directory.CreateDirectory(rbAppDllInfo.CacheDir); } rbAppDllInfo.AppId = rbapprc.AppId; rbAppDllInfo.AppProcessingId = rbapprc.AppProcessingId; rbAppDllInfo.Registered_DateTime = rbapprc.Registered_DateTime; //rbAppDllInfo.GenerateCachedFileName(); rbAppDllInfo.CachedFileName = rbAppDllInfo.FileName; blobTargetFilePath = Path.Combine(rbAppDllInfo.CacheDir, rbAppDllInfo.CachedFileName); using (var fileStream = File.OpenWrite(blobTargetFilePath)) { rbAzureStorage.BlockBlobDownload(fileStream, rbapprc.BlobContainer, rbapprc.FileName); } // Update cache info if DLL download from BLOB is successful. rbAppDllCacheInfoDic[rbapprc.FileName] = rbAppDllInfo; // Logging if (rbTraceLevel == RbTraceType.Detail) { RbTraceLog.WriteLog(string.Format("App DLL is copied from BLOB strage. Dir:{0}, FileName:{1}", curdir, rbAppDllInfo.CachedFileName)); } } // Copy original DLL into partition directory rbAppDllInfo_partition = new RbAppDllCacheInfo(); rbAppDllInfo_partition.FileName = rbapprc.FileName; rbAppDllInfo_partition.CacheDir = cachedDllFileInfo.PrivateDllDirectory; rbAppDllInfo_partition.AppId = rbapprc.AppId; rbAppDllInfo_partition.AppProcessingId = rbapprc.AppProcessingId; rbAppDllInfo_partition.Registered_DateTime = rbapprc.Registered_DateTime; rbAppDllInfo_partition.CachedFileName = rbAppDllInfo_partition.FileName; string sourceFilePath = Path.Combine(rbAppDllInfo.CacheDir, rbAppDllInfo.CachedFileName); string targetFilePath = Path.Combine(rbAppDllInfo_partition.CacheDir, rbAppDllInfo_partition.CachedFileName); cachedDllFileInfo.PrivateDllFilePath = targetFilePath; if (!Directory.Exists(rbAppDllInfo_partition.CacheDir)) { Directory.CreateDirectory(rbAppDllInfo_partition.CacheDir); } File.Copy(sourceFilePath, targetFilePath, true); // Update cache info if DLL copied successfully. rbAppDllCacheInfoDic[partitionedFileNameKey] = rbAppDllInfo_partition; // Logging if (rbTraceLevel == RbTraceType.Detail) { RbTraceLog.WriteLog(string.Format("Original App DLL is copied into partition directory. Dir:{0}, FileName:{1}, PartitionId:{2}", curdir, rbAppDllInfo.CachedFileName, partitionId)); } } return(cachedDllFileInfo); }
JArray CallApps(RbHeader rbh, string rbBodyString, string partitionId) { // Get App Master Info RbAppMasterCache rbappmc = GetAppMasterInfo(rbh); // Get App Routing Info RbAppRouterCache rbapprc = GetAppRoutingInfo(rbh); JArrayString ja_messagesString = null; JArray ja_messages = null; string dllFilePath = string.Empty; IAppRouterDll routedAppDll = null; Assembly assembly = null; // Load DLL from BLOB string baseDirectory = string.Empty; string privateDllDirectory = string.Empty; string cachedFileName = string.Empty; string cachedFileNameWithoutExt = string.Empty; if (rbapprc.DevMode == "True") { string devdir = rbapprc.DevLocalDir; int pos = devdir.Length - 1; if (devdir.Substring(pos, 1) == @"\") { dllFilePath = rbapprc.DevLocalDir + rbapprc.FileName; } else { dllFilePath = rbapprc.DevLocalDir + @"\" + rbapprc.FileName; } baseDirectory = Path.GetDirectoryName(dllFilePath); privateDllDirectory = baseDirectory; cachedFileName = Path.GetFileName(dllFilePath); cachedFileNameWithoutExt = Path.GetFileNameWithoutExtension(dllFilePath); } else { CachedDllFileInfo cachedDllFileInfo = null; lock (thisLock2) { cachedDllFileInfo = CopyBlobToLocalDir(rbappmc, rbapprc, partitionId); } baseDirectory = cachedDllFileInfo.BaseDirectory; privateDllDirectory = cachedDllFileInfo.PrivateDllDirectory; cachedFileName = Path.GetFileName(cachedDllFileInfo.PrivateDllFilePath); cachedFileNameWithoutExt = Path.GetFileNameWithoutExtension(cachedDllFileInfo.PrivateDllFilePath); } ////Static load without AppDomain //assembly = System.Reflection.Assembly.LoadFrom(dllFilePath); //routedAppDll = assembly.CreateInstance(rbapprc.ClassName) as IAppRouterDll; //Dynamic load using AppDomain try { string appDomainName = appDomanNameBase + partitionId; AppDomain appDomain = null; if (appDomainList.ContainsKey(partitionId)) { appDomain = appDomainList[partitionId]; } if (appDomain == null) { appDomain = CreateAppDomain(appDomainName, baseDirectory, privateDllDirectory); lock (thisLock2) { appDomainList[partitionId] = appDomain; } } routedAppDll = appDomain.CreateInstanceAndUnwrap(cachedFileNameWithoutExt, rbapprc.ClassName) as IAppRouterDll; } catch (Exception ex) { RbTraceLog.WriteError("E003", ex.ToString()); ae = new ApplicationException("Error ** Exception occured during creating AppDomain & Instance(App DLL)"); throw ae; } // ProcessMessage try { rbh.ProcessingStack = rbapprc.FileName; ja_messagesString = routedAppDll.ProcessMessage(rbappmc, rbapprc, rbh, rbBodyString); ja_messages = ja_messagesString.ConvertToJArray(); } catch (Exception ex) { RbTraceLog.WriteError("E002", ex.ToString()); ae = new ApplicationException("Error ** Exception occured in routed App DLL"); throw ae; } return(ja_messages); }