public async Task SendToRules(int taskID, ConnectionToRulesManagerAdapterArgs args, bool responsive = true) { var Connection = args.Connection; var toRules = args.toRules; var cache = args.cache; IConnectionRoutedCacheManager connectionRoutedCacheManager = args.connectionRoutedCacheManager; Throw.IfNull(Connection); var taskInfo = $"task: {taskID} connection: {Connection.name}"; // RoutedItem[] temp; _logger.Log(LogLevel.Debug, $"{taskInfo} Entering SendToRules."); try { do { RoutedItem routedItem = null; var count = 0; // bool newItems = false; // lock (toRules) // { // newItems = toRules.Any(e => e.attempts == 0); // } // if (count == 0 || !newItems) // { // bool success = await ToRulesSignal.WaitAsync(LITE.profile.kickoffInterval, LITETask.cts.Token).ConfigureAwait(false); // } // lock (toRules) // { // temp = toRules.ToArray(); // } //send everything in toRules // foreach (var routedItem in temp) // { // if (LITETask.cts.Token.IsCancellationRequested) // { routedItem = toRules.Take(_taskManager.cts.Token); //item removed from list prior to processing count = toRules.Count + 1; _logger.Log(LogLevel.Information, $"{taskInfo} toRules: {count} items to transfer."); // if (routedItem.lastAttempt != null && routedItem.lastAttempt < DateTime.Now.AddMinutes(-retryDelayMinutes)) //not attempted lately // { routedItem.attempts++; routedItem.lastAttempt = DateTime.Now; try { if (routedItem.attempts <= Connection.maxAttempts) { // shb 2019-03-15 BOUR-85 to support intelligent routing of items based on pre-determined routing info // EX: hl7 has the routing info while subsequent dicom items do not // Order of precedence // 0.5) No caching for request / response, done elsewhere // 1) No routing info - use connection - based rules // 2) Prior routing info for patientID and accession # - use provider routing rules // 3) Address - oriented routing in item - override all other rules if (routedItem.id != null && routedItem.type != RoutedItem.Type.RPC) { routedItem = _connectionCache.CacheResponse(Connection, routedItem, cache); //for a dicom/file item to look up prior toConnections of hl7 } var currentProfile = _profileStorage.Current; _rulesManager.Init(currentProfile.rules); routedItem = await _rulesManager.SendToRules(routedItem, _routedItemManager, connectionRoutedCacheManager); if (routedItem != null && routedItem.id != null && routedItem.type != RoutedItem.Type.RPC) { routedItem = _connectionCache.CacheResponse(Connection, routedItem, cache); //for an hl7 to record the toConnections } _routedItemManager.Init(routedItem); _routedItemManager.Dequeue(Connection, toRules, nameof(toRules), error: false); } else { _logger.Log(LogLevel.Warning, $"{taskInfo} {routedItem.RoutedItemMetaFile} exceeded maxAttempts"); _routedItemManager.Init(routedItem); _routedItemManager.Dequeue(Connection, toRules, nameof(toRules), error: true); } } catch (Exception e) { _logger.LogFullException(e, $"{taskInfo} returning item to queue: {routedItem.RoutedItemMetaFile}"); if (routedItem != null) { toRules.Add(routedItem, _taskManager.cts.Token); } } // } // ToRulesSignal.Dispose(); // ToRulesSignal = new SemaphoreSlim(0, 1); // // } // } } while (responsive); } catch (TaskCanceledException) { _logger.Log(LogLevel.Information, $"{taskInfo} Task was canceled."); } catch (Exception e) { _logger.LogFullException(e, taskInfo); } finally { _taskManager.Stop($"{Connection.name}.SendToRules"); } _logger.Log(LogLevel.Debug, $"{taskInfo} Exiting SendToRules."); }
public async Task SendFile(string filePath, int taskID, FileConnection connection, IConnectionRoutedCacheManager connectionManager) { Connection = connection; _logger.Log(LogLevel.Debug, $"Sending {filePath}"); RoutedItem routedItem = new RoutedItem(fromConnection: Connection.name, sourceFileName: filePath, taskID: taskID) { type = RoutedItem.Type.FILE }; try { routedItem.type = RoutedItem.Type.FILE; _routedItemManager.Init(routedItem); _routedItemManager.Enqueue(Connection, Connection.toRules, nameof(Connection.toRules)); await _rulesManager.SendToRules(routedItem, _routedItemManager, connectionManager); //await LITE.profile.rules.SendToRules(routedItem); _routedItemManager.Dequeue(Connection, Connection.toRules, nameof(Connection.toRules)); if (Connection.outpath != null && File.Exists(filePath)) { var expandedOutPath = _fileExpanderService.Expand(Connection.outpath); // collapse the duplicate part of the path, prob more simple way of thinking about this. string dir = $"{expandedOutPath}{filePath.Substring(0, filePath.LastIndexOf(Path.DirectorySeparatorChar)).Replace(_fileExpanderService.Expand("~"), "")}"; string file = $"{expandedOutPath}{filePath.Replace(_fileExpanderService.Expand("~"), "")}"; _logger.Log(LogLevel.Debug, $"Moving {filePath} to {file}"); Directory.CreateDirectory(dir); //await Task.Yield(); if (File.Exists(file)) { var orgFileDateTime = File.GetLastWriteTime(file).ToString() .Replace(Path.DirectorySeparatorChar, '-').Replace(":", "-"); var destinationBackupFileName = $"{file}.{orgFileDateTime}"; // Remove the file to guarantee the move works //File.Delete(file); File.Replace(filePath, file, destinationBackupFileName, true); } else { File.Move(filePath, file); } _logger.Log(LogLevel.Debug, $"Moved {filePath} to {file}"); } else { _logger.Log(LogLevel.Debug, $"outpath is null."); } } catch (TaskCanceledException) { _logger.Log(LogLevel.Information, $"Task was canceled."); } catch (Exception e) { _logger.LogFullException(e); _routedItemManager.Init(routedItem); _routedItemManager.Dequeue(Connection, Connection.toRules, nameof(Connection.toRules), error: true); } }