/// <summary> /// Obtiene el filtro global /// </summary> /// <param name="assembly">asembly donde obtener la metadata</param> /// <returns></returns> public static GlobalFilters GetGlobalFilter(Assembly assembly) { // obtiene el assembly. var types = Common.GetTypeModel(assembly); // var toValueTypes = ToValueTypes(types); var toValues = GetToValues(types, toValueTypes); var ToProcesTypes = ToProcess.ToProcessTypes(types, 0, true, null); var toProcess = ToProcess.GetFilterProcess(types, 0, true, null); var tp = ToProcesTypes.First().toProcess.TargetType; var tpIndex = Reflection.Entities.GetIndex(tp).Value; return(new GlobalFilters { EntityForGlobalFilters = tp.Name, IndexEntityForGlobalFilters = tpIndex, ToProcess = toProcess, ToValue = toValues }); }
/// <summary> /// Writes all messages currently in the queue to MongoDb and acknowledges /// </summary> protected override void ProcessQueue() { // Will happen when ProcessQueue is called due to the timer, before we receive our first message if (Model == null) { return; } lock (LockObj) { if (ToProcess.Count == 0) { return; } Logger.Info($"Queue contains {ToProcess.Count} message to write"); foreach ((string modality, List <BsonDocument> modalityDocs) in MongoModalityGroups.GetModalityChunks(ToProcess.Select(x => x.Item1).ToList())) { Logger.Debug($"Attempting to write {modalityDocs.Count} documents of modality {modality}"); while (FailedWriteAttempts < FailedWriteLimit) { WriteResult imageWriteResult = MongoDbAdapter.WriteMany(modalityDocs, modality); if (imageWriteResult == WriteResult.Success) { Logger.Debug($"Wrote {modalityDocs.Count} documents successfully, sending ACKs"); // Hopefully this uses ReferenceEquals, otherwise will be slow... foreach (ulong deliveryTag in ToProcess .Where(x => modalityDocs.Contains(x.Item1)) .Select(x => x.Item2)) { Model.BasicAck(deliveryTag, false); } AckCount += modalityDocs.Count; FailedWriteAttempts = 0; break; } Logger.Warn($"Failed to write {FailedWriteAttempts + 1} time(s) in a row"); if (++FailedWriteAttempts < FailedWriteLimit) { continue; } throw new ApplicationException("Failed write attempts exceeded"); } } Logger.Debug("Wrote and acknowledged all documents in queue. Clearing and continutig"); ToProcess.Clear(); } }
public override int GetHashCode() { var hashCode = -1374379752; hashCode = hashCode * -1521134295 + Processed.GetHashCode(); hashCode = hashCode * -1521134295 + ToProcess.GetHashCode(); hashCode = hashCode * -1521134295 + Errors.GetHashCode(); hashCode = hashCode * -1521134295 + Processing.GetHashCode(); return(hashCode); }
/// <summary> /// Writes all messages currently in the queue to MongoDb and acknowledges /// </summary> protected override void ProcessQueue() { // Will happen when ProcessQueue is called before we receive our first message if (Model == null) { return; } lock (LockObj) { if (ToProcess.Count == 0) { return; } Logger.Debug("SeriesMessageProcessor: Queue contains " + ToProcess.Count + " message to write"); IEnumerable <string> batchDirectories = ToProcess.Select(t => t.Item1.GetValue("header")["DirectoryPath"].AsString).Distinct(); Logger.Trace($"Writing series from directories: {string.Join(", ", batchDirectories)}"); WriteResult seriesWriteResult = MongoDbAdapter.WriteMany(ToProcess.Select(t => t.Item1).ToList()); // Result => Need to differentiate between connection loss and error in the data to be written // As well as making sure either all are written or none if (seriesWriteResult == WriteResult.Success) { Logger.Debug("SeriesMessageProcessor: Wrote " + ToProcess.Count + " messages successfully, sending ACKs"); foreach (ulong deliveryTag in ToProcess.Select(t => t.Item2)) { Model.BasicAck(deliveryTag, false); } AckCount += ToProcess.Count; ToProcess.Clear(); FailedWriteAttempts = 0; } else { Logger.Warn($"SeriesMessageProcessor: Failed to write {FailedWriteAttempts + 1} time(s) in a row"); if (++FailedWriteAttempts < FailedWriteLimit) { return; } throw new ApplicationException("Failed write attempts exceeded"); } } }
public override void Serialize(GenericWriter writer) { base.Serialize(writer); writer.WriteEncodedInt(1); //version writer.Write(NextRecharge); writer.Write(m_Charges); if (DateTime.UtcNow > NextRecharge) { ToProcess.Add(this); } }
public override void AddToWriteQueue(SeriesMessage message, IMessageHeader header, ulong deliveryTag) { ToProcess.Enqueue(new Tuple <BsonDocument, ulong>(new BsonDocument { { "hello", "world" } }, deliveryTag)); }
public override void AddToWriteQueue(SeriesMessage message, IMessageHeader header, ulong deliveryTag) { // Only time we are not processing is if we are shutting down anyway if (IsStopping) { return; } if (Model == null) { throw new ApplicationException("Model needs to be set before messages can be processed"); } DicomDataset dataset; try { dataset = DicomTypeTranslater.DeserializeJsonToDataset(message.DicomDataset); } catch (Exception e) { throw new ApplicationException("Could not deserialize json to dataset", e); } BsonDocument datasetDoc; try { datasetDoc = DicomTypeTranslaterReader.BuildBsonDocument(dataset); } catch (Exception e) { throw new ApplicationException("Exception converting dataset to BsonDocument", e); } BsonDocument bsonHeader = MongoDocumentHeaders.SeriesDocumentHeader(message); BsonDocument document = new BsonDocument() .Add("header", bsonHeader) .AddRange(datasetDoc); int docByteLength = document.ToBson().Length; if (docByteLength > MaxDocumentSize) { throw new ApplicationException($"BsonDocument was larger than the max allowed size (have {docByteLength}, max is {MaxDocumentSize})"); } var forceProcess = false; lock (LockObj) { ToProcess.Enqueue(new Tuple <BsonDocument, ulong>(document, deliveryTag)); if (ToProcess.Count >= MaxQueueSize) { forceProcess = true; } } if (!forceProcess) { return; } Logger.Debug("SeriesMessageProcessor: Max queue size reached, calling ProcessQueue"); ProcessQueue(); }
/// <summary> /// Asigna los procesos (relaciones de filtro) involucrados en cada entidad. /// Esto permite asignar en la metadata que elementos filtran a otros. /// y que elementos son filtrados por otros. /// </summary> /// <param name="asm">Assembly del modelo</param> /// <param name="gfc">filtros globales del modelo</param> /// <param name="entity">metadata de la entidad</param> /// <param name="docProcess">Documentación de los filtros</param> /// <returns></returns> private static EntityMetadata GetEntityWithProcess(Assembly asm, GlobalFilters gfc, EntityMetadata entity, DocFilter[] docProcess) { // obtiene los tipos de tipo modelo (las relaciones de filtro solo se encuentran en el modelo). var mdlTypes = Common.GetTypeModel(asm); if (!docProcess.Any()) { throw new CustomException("No existe documentación de filtros"); } // desde la documentación encontrada, usa los índices para encontrar los filtros en todo el modelo. var filterProcess = docProcess.SelectMany(dp => ToProcess.GetFilterProcess(mdlTypes, dp.Index, false, gfc)); // si no existen filtros, retorna la metadata sin modificar. if (!filterProcess.Any()) { // no existen procesos en el modelo. return(entity); } // obtiene los filtros, que tengan como origen la entidad. var filterProcessForEntity = filterProcess.Where(s => s.SourceIndex == entity.Index); // si existen filtros que tengan la entidad como origen. if (filterProcessForEntity.Any()) { // busca documentación para el filtro. var docFiltersAvailableForEntity = docProcess.Where(s => filterProcessForEntity.Any(a => a.SourceIndex == entity.Index)); // documentación de filtros de la entidad. if (docFiltersAvailableForEntity.Any()) { // asigna a la entidad, la documentación de filtros encontrados. entity.DocFilters = docFiltersAvailableForEntity.ToArray(); // obtiene los procesos para la entidad. var targetProcesForEntity = filterProcessForEntity.Where(s => s.SourceIndex == entity.Index); // ToProcessFilter indica que entidades esta entidad puede filtrar. if (targetProcesForEntity.Any()) { entity.ToProcessFilter = targetProcesForEntity.ToArray(); } } } // se encuentan procesos que apunten a esta entidad. var filterAvailableForEntity = filterProcess.Where(s => s.TargetRealIndex == entity.Index).ToList(); // si existe un filtro global en el modelo. if (gfc != null) { // obtiene la colección de rutas del filtro global (índice 0). var globalTarget = ToProcess.GetFilterProcess(mdlTypes, 0, true, null); // procesos de índice 0 (filtro global). var docFiltersAvailableToEntity = docProcess.Where(s => s.Index == 0); // el IndexEntityForGlobalFilters determina una entidad en común por filtro global. // por ejemplo, para el modelo agricola, es barrack, debido a que // los filtros globales filtran barrack y barrack filtra el resto. // esta condición se cumplirá solo si el filtro global apunta a la entidad actual. if (gfc.IndexEntityForGlobalFilters == entity.Index) { // obtiene el listado de elementos que filtra la entidad var lst = entity.FiltersAvailable?.ToList() ?? new List <RelatedItem>(); // todos las entidades que pertenecen al globalFilter, filtran o apuntan // directa o indirectamente a una entidad principal. // se asignan como filtros lst.AddRange(globalTarget.Where(s => s.TargetRealIndex == entity.Index).Select(s => new RelatedItem { PathToEntity = s, ClassName = s.SourceName, docFilter = docFiltersAvailableToEntity.First(a => a.Index == s.Index), Index = s.Index })); entity.FiltersAvailable = lst.ToArray(); // se quitan los procesos del filtro global que apunten a la entidad principal filterAvailableForEntity = filterAvailableForEntity.Where(s => !(s.TargetRealIndex == entity.Index && s.Index == 0)).ToList(); } } // si existen filtros que apunten a la entidad if (filterAvailableForEntity.Any()) { // documentos que tangan los índices de los filtros que apuntan a la entidad. var docFiltersAvailableToEntity = docProcess.Where(s => filterAvailableForEntity.Any(a => s.Index == a.Index)).ToList(); if (!docFiltersAvailableToEntity.Any()) { throw new Exception($"no existe documentación para uno de los siguentes indices {string.Join(",", filterAvailableForEntity.Select(s => s.Index).Distinct().ToArray())}"); } var lst = entity.FiltersAvailable?.ToList() ?? new List <RelatedItem>(); // asigna todas las entidades que filtran la entidad. lst.AddRange(filterAvailableForEntity.Select(s => new RelatedItem { PathToEntity = s, ClassName = s.SourceName, docFilter = docFiltersAvailableToEntity.First(a => a.Index == s.Index), Index = s.Index })); entity.FiltersAvailable = lst.ToArray(); } // entidad con los procesos (filtros). return(entity); }