123 lines
5.2 KiB
C#
123 lines
5.2 KiB
C#
// Copyright (c) 2017 schick Informatik
|
|
// Description: Diese Klasse überwacht Änderungen in Datenbankobjekten (durch zykl. Abfrage eines Threads
|
|
// und Vgl. des "Changed" Felds bezogen auf den Beginn der Überwachung. Voraussetzung ist das die Entität ein
|
|
// entsprechendes "Changed" Feld besitzt. (aktuell nur MessageCore, generisch nicht so einfach weil DatabaseEntity
|
|
// aktuell eine abstrakte Klasse ist und daher nicht direkt instanziert werden kann (DBManager)
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Timers;
|
|
|
|
using bsmd.database;
|
|
|
|
namespace ENI2.Util
|
|
{
|
|
internal class DatabaseEntityWatchdog
|
|
{
|
|
private readonly Dictionary<MessageCore, DateTime> _watchedEntities = new Dictionary<MessageCore, DateTime>();
|
|
private readonly object _entityLock = new object();
|
|
private readonly Timer bgTimer;
|
|
|
|
public delegate void DatabaseEntityChangedHandler (DatabaseEntity entity);
|
|
|
|
public event DatabaseEntityChangedHandler DatabaseEntityChanged;
|
|
public event DatabaseEntityChangedHandler VisitTransitIdUpdated;
|
|
|
|
public DatabaseEntityWatchdog()
|
|
{
|
|
this.bgTimer = new Timer();
|
|
this.bgTimer.Elapsed += BgTimer_Elapsed;
|
|
this.bgTimer.AutoReset = true;
|
|
this.bgTimer.Interval = Properties.Settings.Default.changeTimerTimeout;
|
|
}
|
|
|
|
public bool Idle => _watchedEntities.Count == 0;
|
|
|
|
private void BgTimer_Elapsed(object sender, ElapsedEventArgs e)
|
|
{
|
|
lock (this._entityLock)
|
|
{
|
|
List<MessageCore> changedCores = new List<MessageCore>();
|
|
|
|
foreach (MessageCore watchedEntity in this._watchedEntities.Keys)
|
|
{
|
|
MessageCore entity = DBManager.GetSingleCon(Properties.Settings.Default.ConnectionString).GetMessageCoreById(watchedEntity.Id ?? Guid.Empty);
|
|
if (entity != null)
|
|
{
|
|
// Der Core muss einen dieser Zustände einnehmen bevor das Highlighting erlaubt ist. Diese Zustände werden im Send Prozess gesetzt
|
|
// (wenn die Nachrichten bearbeitet sind)
|
|
bool isValidState = (entity.BSMDStatusInternal == MessageCore.BSMDStatus.FAILURE) ||
|
|
(entity.BSMDStatusInternal == MessageCore.BSMDStatus.SENT) ||
|
|
(entity.BSMDStatusInternal == MessageCore.BSMDStatus.PREPARE) ||
|
|
(entity.BSMDStatusInternal == MessageCore.BSMDStatus.RESPONDED);
|
|
|
|
if (isValidState && ((entity.Changed > this._watchedEntities[watchedEntity]) || watchedEntity.IsHighlighted))
|
|
{
|
|
OnDatabaseEntityChanged(entity);
|
|
changedCores.Add(entity);
|
|
}
|
|
|
|
// Test ob eventuell Visit/Transit-ID inzwischen gesetzt wurde
|
|
if(entity.IsTransit)
|
|
{
|
|
if (!entity.TransitId.IsNullOrEmpty() && watchedEntity.TransitId.IsNullOrEmpty() && !entity.TransitId.Equals(watchedEntity.TransitId))
|
|
{
|
|
OnVisitTransitIdUpdated(entity);
|
|
watchedEntity.TransitId = entity.TransitId;
|
|
}
|
|
}
|
|
else if (!entity.VisitId.IsNullOrEmpty() && watchedEntity.VisitId.IsNullOrEmpty() && !entity.VisitId.Equals(watchedEntity.VisitId))
|
|
{
|
|
OnVisitTransitIdUpdated(entity);
|
|
watchedEntity.VisitId = entity.VisitId;
|
|
}
|
|
}
|
|
}
|
|
|
|
foreach (MessageCore changedCore in changedCores)
|
|
this._watchedEntities[changedCore] = DateTime.Now; // nur einmal auslösen
|
|
}
|
|
}
|
|
|
|
public void Register(MessageCore entity)
|
|
{
|
|
lock (this._entityLock)
|
|
{
|
|
if (!this._watchedEntities.ContainsKey(entity))
|
|
{
|
|
this._watchedEntities.Add(entity, DateTime.Now);
|
|
if (this._watchedEntities.Count > 0)
|
|
this.bgTimer.Start();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void UnRegister(MessageCore entity)
|
|
{
|
|
|
|
lock (this._entityLock)
|
|
{
|
|
if (this._watchedEntities.ContainsKey(entity)) // hier wird mit Id verglichen (IEquatable<T> impl.)
|
|
this._watchedEntities.Remove(entity);
|
|
if (this._watchedEntities.Count == 0)
|
|
this.bgTimer.Stop();
|
|
}
|
|
}
|
|
|
|
#region private / protected
|
|
|
|
protected void OnDatabaseEntityChanged(DatabaseEntity entity)
|
|
{
|
|
this.DatabaseEntityChanged?.Invoke(entity);
|
|
}
|
|
|
|
protected void OnVisitTransitIdUpdated(DatabaseEntity entity)
|
|
{
|
|
this.VisitTransitIdUpdated?.Invoke(entity);
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|