Ejemplo n.º 1
0
        /// <summary>
        ///  result cache where we consolidate multiple routed items based on the same id.The result is added onto the id: key
        ///  which usually arrives in chronological order(Pending, Pending, Success) though not required
        /// </summary>
        /// <param name="Connection"></param>
        /// <param name="routedItem"></param>
        /// <param name="cache"></param>
        /// <returns></returns>
        public RoutedItem CacheResponse(Connection Connection, RoutedItem routedItem, Dictionary <string, List <RoutedItem> > cache)
        {
            Throw.IfNull(Connection);

            if (routedItem.id != null)
            {
                lock (cache)
                {
                    _logger.Log(LogLevel.Debug, $"incoming conn: {routedItem.fromConnection} id: {routedItem.id} InstanceID: {routedItem.InstanceID} status: {routedItem.status}");

                    _routedItemManager.Init(routedItem);
                    var riClone = (RoutedItem)_routedItemManager.Clone();

                    //                List<RoutedItem> list = new List<RoutedItem>() { routedItem };
                    _routedItemManager.Init(routedItem);
                    _routedItemManager.EnqueueCache(Connection, cache, nameof(cache));

                    // //add id to cache if not present. id is the record id from the requesting sou
                    // if (cache.TryAdd(routedItem.id, list))
                    // {
                    //     if (Logger.logger.FileTraceLevel == "Verbose") Logger.logger.Log(TraceEventType.Verbose, $"id: {routedItem.id} added to cache");

                    // }
                    // else
                    // {

                    //     if (Logger.logger.FileTraceLevel == "Verbose") Logger.logger.Log(TraceEventType.Verbose, $"id: {routedItem.id} exists in cache, consolidating");

                    //     cache[routedItem.id].Add(routedItem);

                    // }

                    //print out cache entries for this id
                    // if (Logger.logger.FileTraceLevel == "Verbose")
                    // {
                    //     foreach (var ri in cache[routedItem.id])
                    //     {
                    //         Logger.logger.Log(TraceEventType.Verbose, $"current cache conn: {routedItem.fromConnection} id: {routedItem.id} InstanceID: {ri.InstanceID} status: {ri.status}");
                    //     }
                    // }


                    //create a set by connection,
                    Dictionary <string, RoutedItem.Status> set = new Dictionary <string, RoutedItem.Status>();

                    foreach (var ri in cache[routedItem.id])
                    {
                        set.TryAdd(ri.fromConnection, ri.status);
                        if (ri.status == RoutedItem.Status.COMPLETED)
                        {
                            set[ri.fromConnection] = RoutedItem.Status.COMPLETED;
                        }

                        if (ri.status == RoutedItem.Status.FAILED)
                        {
                            set[ri.fromConnection] = RoutedItem.Status.FAILED;
                        }

                        //populate any previously known toConnections.  Use case is BOUR-85 hl7 determining route for dicom with same id(patientID+accession)
                        if (routedItem.type != RoutedItem.Type.RPC)
                        {
                            //route caching doesn't work yet for request framework since the same request and resulting response goes both directions!!!

                            foreach (var conn in ri.toConnections)
                            {
                                if (!riClone.toConnections.Contains(conn))
                                {
                                    _logger.Log(LogLevel.Debug, $"Adding cached destination {conn.connectionName} id: {routedItem.id}");
                                    riClone.toConnections.Add(conn);
                                }
                            }
                        }
                    }

                    //determine if each set is complete
                    var completed = set.Count(e => e.Value == RoutedItem.Status.COMPLETED);
                    var failed    = set.Count(e => e.Value == RoutedItem.Status.FAILED);
                    var statusnew = set.Count(e => e.Value == RoutedItem.Status.NEW);
                    var pending   = set.Count(e => e.Value == RoutedItem.Status.PENDING);
                    RoutedItem.Status statusOfSet = RoutedItem.Status.PENDING;
                    if (completed == set.Count)
                    {
                        statusOfSet = RoutedItem.Status.COMPLETED;
                    }
                    else if (completed + failed == set.Count)
                    {
                        statusOfSet = RoutedItem.Status.FAILED;
                    }

                    _logger.Log(LogLevel.Debug, $"id: {routedItem.id} set.Count: {set.Count} completed: {completed} failed: {failed} pending: {pending} new: {statusnew}");

                    if (statusOfSet == RoutedItem.Status.COMPLETED || statusOfSet == RoutedItem.Status.FAILED)
                    {
                        //we're done
                        _logger.Log(LogLevel.Information, $"id: {routedItem.id} status of set: {statusOfSet} ");

                        //now merge responses by connection
                        Dictionary <string, CloudTaskResults> merged = new Dictionary <string, CloudTaskResults>();

                        foreach (var ri in cache[routedItem.id])
                        {
                            var mergedElement = new CloudTaskResults
                            {
                                connectionName  = ri.fromConnection,
                                results         = ri.response,
                                accessionNumber = ri.AccessionNumber,
                                mrn             = ri.PatientID
                            };

                            if (!merged.TryAdd(ri.fromConnection, mergedElement))
                            {
                                foreach (var response in ri.response)
                                {
                                    if (!merged[ri.fromConnection].results.Contains(response))
                                    {
                                        merged[ri.fromConnection].results.Add(response);
                                    }
                                }

                                if (mergedElement.accessionNumber == null)
                                {
                                    mergedElement.accessionNumber = ri.AccessionNumber;
                                }
                                if (mergedElement.mrn == null)
                                {
                                    mergedElement.mrn = ri.PatientID;
                                }
                            }
                        }

                        riClone.cloudTaskResults.AddRange(merged.Values);
                        riClone.status = statusOfSet;
                    }
                    else
                    {
                        //not all connections are done
                        _logger.Log(LogLevel.Information, $"id: {routedItem.id} Not Complete ");
                        riClone.status = RoutedItem.Status.PENDING;
                    }

                    _logger.Log(LogLevel.Debug, $"cache total count after: {cache.Count}");

                    return(riClone);
                }
            }
            else
            {
                _logger.Log(LogLevel.Warning, $"Cannot cache RoutedItem because id is null: {routedItem.sourceFileName}");
                return(routedItem);
            }
        }