Projektbereinigung: Entfernung alter Module und Ressourcen
Mehrere Module (`ChatAddUser`, `ChatControl`, `ChatNewConv`) und deren zugehörige Dateien wurden vollständig aus dem Projekt entfernt. Dies umfasst Designer-, Ressourcen- und Projektdateien sowie Backup-Dateien. Zusätzlich wurden nicht mehr benötigte Bilder, Lizenzdateien (`licenses.licx`), Konfigurationsdateien (`app.config`, `packages.config`) und generierte Dateien entfernt. Die Abhängigkeiten in `App.config` wurden aktualisiert, und neue Bibliotheken wie `System.Threading.Tasks.Extensions` wurden hinzugefügt. Eine Methode in `Annotations.vb` wurde angepasst, um Änderungen in der zugrunde liegenden API zu berücksichtigen. Diese Änderungen sind Teil einer umfassenden Bereinigung und Modernisierung des Projekts.
This commit is contained in:
@@ -27,38 +27,102 @@ Public Class EDMIService
|
||||
|
||||
Public Const TBIDB_DOC_INFO = "TBIDB_DOC_INFO"
|
||||
Public Const TBIDB_ACCESSRIGHT = "TBIDB_ACCESSRIGHT"
|
||||
' ── Aktive Sessions: SessionId → Username (thread-safe) ──────────────────
|
||||
Private Shared ReadOnly _ActiveSessions As New Collections.Concurrent.ConcurrentDictionary(Of String, String)
|
||||
|
||||
Public Shared ReadOnly Property ActiveSessions As Integer
|
||||
Get
|
||||
Return _ActiveSessions.Count
|
||||
End Get
|
||||
End Property
|
||||
|
||||
Public Shared ReadOnly Property ActiveSessionUsers As IReadOnlyCollection(Of String)
|
||||
Get
|
||||
Return _ActiveSessions.Values.Distinct().OrderBy(Function(u) u).ToList().AsReadOnly()
|
||||
End Get
|
||||
End Property
|
||||
' ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
Private ReadOnly _Logger As Logger
|
||||
Private ReadOnly _Debug As Boolean = False
|
||||
Private ReadOnly _Username As String
|
||||
Private ReadOnly _IDBHelpers As IDB.Helpers
|
||||
' ── Konfigurationswerte für späteres Logging in New() ────────────────────
|
||||
Private Shared _ConfiguredEndpoint As String = String.Empty
|
||||
Private Shared _ConfiguredMaxCalls As Integer = 0
|
||||
Private Shared _ConfiguredMaxSessions As Integer = 0
|
||||
' ─────────────────────────────────────────────────────────────────────────
|
||||
|
||||
|
||||
Public Shared Sub Configure(Config As ServiceConfiguration)
|
||||
Dim oBaseAddress = Config.BaseAddresses.Item(0)
|
||||
Dim oBinding = API.Channel.GetBinding()
|
||||
Dim oAddress = New EndpointAddress(oBaseAddress)
|
||||
' See: https://stackoverflow.com/questions/42327988/addserviceendpoint-throws-key-is-null
|
||||
Dim oDescription = ContractDescription.GetContract(GetType(IEDMIService), GetType(EDMIService))
|
||||
Dim oEndpoint As New ServiceEndpoint(oDescription, oBinding, oAddress)
|
||||
|
||||
Config.AddServiceEndpoint(oEndpoint)
|
||||
Config.Description.Behaviors.Add(New ServiceDebugBehavior With {.IncludeExceptionDetailInFaults = True})
|
||||
|
||||
Dim oThrottling = Config.Description.Behaviors.Find(Of ServiceThrottlingBehavior)()
|
||||
If oThrottling Is Nothing Then
|
||||
oThrottling = New ServiceThrottlingBehavior()
|
||||
Config.Description.Behaviors.Add(oThrottling)
|
||||
End If
|
||||
Dim oCpuCores As Integer = Environment.ProcessorCount
|
||||
oThrottling.MaxConcurrentCalls = Math.Max(200, 32 * oCpuCores) ' war 16×
|
||||
oThrottling.MaxConcurrentSessions = Math.Max(400, 150 * oCpuCores) ' war 100×
|
||||
oThrottling.MaxConcurrentInstances = Integer.MaxValue
|
||||
|
||||
' ── Werte für späteres Logging speichern ─────────────────────────────
|
||||
_ConfiguredEndpoint = oBaseAddress.ToString()
|
||||
_ConfiguredMaxCalls = oThrottling.MaxConcurrentCalls
|
||||
_ConfiguredMaxSessions = oThrottling.MaxConcurrentSessions
|
||||
' ─────────────────────────────────────────────────────────────────────
|
||||
End Sub
|
||||
|
||||
Public Sub New()
|
||||
Dim oOperationContext As OperationContext = OperationContext.Current
|
||||
Dim oInstanceContext As InstanceContext = oOperationContext.InstanceContext
|
||||
Dim oUsername = StripDomainFromUsername(oOperationContext.ServiceSecurityContext.WindowsIdentity.Name)
|
||||
Dim oSessionId As String = If(oOperationContext.SessionId, $"no-session_{Guid.NewGuid().ToString("N").Substring(0, 8)}")
|
||||
|
||||
_Username = oUsername
|
||||
|
||||
_Username = If(String.IsNullOrWhiteSpace(oUsername), "unknown", oUsername)
|
||||
_Logger = LogConfig.GetLogger()
|
||||
_Logger.Debug("New Request by User [{0}]", _Username)
|
||||
|
||||
_IDBHelpers = New IDB.Helpers(LogConfig, MSSQL_IDB)
|
||||
End Sub
|
||||
|
||||
' ── Konfiguration beim ersten Aufruf loggen ───────────────────────────
|
||||
If Not String.IsNullOrEmpty(_ConfiguredEndpoint) Then
|
||||
_Logger.Info("✔ EDMIService configured | Endpoint=[{0}] | MaxCalls=[{1}] | MaxSessions=[{2}] | CPUs=[{3}]",
|
||||
_ConfiguredEndpoint, _ConfiguredMaxCalls, _ConfiguredMaxSessions, Environment.ProcessorCount)
|
||||
_ConfiguredEndpoint = String.Empty
|
||||
End If
|
||||
' ─────────────────────────────────────────────────────────────────────
|
||||
|
||||
' ── Session registrieren ──────────────────────────────────────────────
|
||||
_ActiveSessions(oSessionId) = _Username
|
||||
BuildUserList()
|
||||
|
||||
AddHandler oInstanceContext.Closed, Sub()
|
||||
Dim oRemoved As String = Nothing
|
||||
_ActiveSessions.TryRemove(oSessionId, oRemoved)
|
||||
BuildUserList()
|
||||
End Sub
|
||||
|
||||
AddHandler oInstanceContext.Faulted, Sub()
|
||||
Dim oRemoved As String = Nothing
|
||||
_ActiveSessions.TryRemove(oSessionId, oRemoved)
|
||||
_Logger.Warn("⚠ Session faulted | User=[{0}] | ActiveSessions=[{1}]",
|
||||
_Username, _ActiveSessions.Count)
|
||||
End Sub
|
||||
|
||||
End Sub
|
||||
''' <summary>
|
||||
''' Erstellt die User-Liste nur wenn nötig (Debug-Guard vorher prüfen).
|
||||
''' </summary>
|
||||
Private Shared Function BuildUserList() As String
|
||||
Return String.Join(", ", _ActiveSessions.Values.Distinct().OrderBy(Function(u) u))
|
||||
End Function
|
||||
#Region "=== Base ==="
|
||||
Public Function Heartbeat() As Boolean Implements IEDMIService.Heartbeat
|
||||
Return True
|
||||
@@ -69,6 +133,20 @@ Public Class EDMIService
|
||||
Dim oGetClientConfig As New Base.GetClientConfig.GetClientConfigMethod(LogConfig, MSSQL_IDB, MSSQL_ECM, GlobalState)
|
||||
Return oGetClientConfig.Run()
|
||||
End Function
|
||||
''' <summary>
|
||||
''' Returns a snapshot of all currently active sessions for monitoring purposes
|
||||
''' </summary>
|
||||
Public Function GetServiceStatus() As Messages.ServiceStatusResponse Implements IEDMIService.GetServiceStatus
|
||||
_Logger.Debug("GetServiceStatus called by User=[{0}]", _Username)
|
||||
' Snapshot nur einmal erstellen, nicht zweimal iterieren:
|
||||
Dim oSnapshot = _ActiveSessions.ToArray()
|
||||
Return New Messages.ServiceStatusResponse With {
|
||||
.ActiveSessionCount = oSnapshot.Length,
|
||||
.ActiveUsers = oSnapshot.Select(Function(p) p.Value).Distinct().OrderBy(Function(u) u).ToList(),
|
||||
.ActiveSessions = oSnapshot.ToDictionary(Function(p) p.Key, Function(p) p.Value),
|
||||
.Timestamp = DateTime.Now
|
||||
}
|
||||
End Function
|
||||
#End Region
|
||||
|
||||
Public Function NewFile(Data As NewFile.NewFileRequest) As NewFile.NewFileResponse Implements IEDMIService.NewFile
|
||||
@@ -121,9 +199,16 @@ Public Class EDMIService
|
||||
|
||||
|
||||
#Region "=== Database ==="
|
||||
Private Shared _CachedTablesSnapshot As List(Of String) = Nothing
|
||||
Private Shared _CachedTablesExpiry As DateTime = DateTime.MinValue
|
||||
|
||||
Public Function GetCachedTables() As List(Of String) Implements IEDMIService.GetCachedTables
|
||||
Try
|
||||
Return GlobalState.GetCachedTables()
|
||||
If _CachedTablesSnapshot Is Nothing OrElse DateTime.Now > _CachedTablesExpiry Then
|
||||
_CachedTablesSnapshot = GlobalState.GetCachedTables()
|
||||
_CachedTablesExpiry = DateTime.Now.AddSeconds(30)
|
||||
End If
|
||||
Return _CachedTablesSnapshot
|
||||
Catch ex As Exception
|
||||
_Logger.Error(ex)
|
||||
Return New List(Of String)
|
||||
@@ -167,7 +252,7 @@ Public Class EDMIService
|
||||
#Region "=== Database (MSSQL IDB) ==="
|
||||
Public Function ReturnDatatable_MSSQL_IDB(SQL As String) As TableResult Implements IEDMIService.ReturnDatatable_MSSQL_IDB
|
||||
Try
|
||||
_Logger.Info($"ReturnDatatable_MSSQL_IDB, SQL: {SQL}")
|
||||
_Logger.Debug($"ReturnDatatable_MSSQL_IDB, SQL: {SQL}")
|
||||
Dim oResult As DataTable = MSSQL_IDB.GetDatatable(SQL)
|
||||
oResult.TableName = "DD_RESULT"
|
||||
Return New TableResult(oResult)
|
||||
@@ -585,7 +670,7 @@ Public Class EDMIService
|
||||
Dim oRow As DataRow = oRows.First()
|
||||
Dim oRightAsInt = oRow.Item("ACCESSRIGHT")
|
||||
|
||||
Select Case oRight
|
||||
Select Case oRightAsInt
|
||||
Case 1
|
||||
oRight = AccessRight.VIEW_ONLY
|
||||
Case 2
|
||||
|
||||
@@ -155,6 +155,8 @@
|
||||
<Compile Include="BaseMethod.vb" />
|
||||
<Compile Include="ClassConstants.vb" />
|
||||
<Compile Include="Config.vb" />
|
||||
<Compile Include="GetServiceStatus.vb" />
|
||||
<Compile Include="Messages\GetServiceStatus.vb" />
|
||||
<Compile Include="Methods\Base\GetClientConfig\GetClientConfigMethod.vb" />
|
||||
<Compile Include="Methods\Base\GetClientConfig\GetClientConfigResponse.vb" />
|
||||
<Compile Include="Methods\Database\DatabaseName.vb" />
|
||||
|
||||
6
Service.EDMIService/GetServiceStatus.vb
Normal file
6
Service.EDMIService/GetServiceStatus.vb
Normal file
@@ -0,0 +1,6 @@
|
||||
Imports System.Runtime.Serialization
|
||||
|
||||
Public Class GetServiceStatus
|
||||
|
||||
|
||||
End Class
|
||||
@@ -16,6 +16,8 @@ Interface IEDMIService
|
||||
|
||||
<OperationContract>
|
||||
Function GetClientConfig() As Base.GetClientConfig.GetClientConfigResponse
|
||||
<OperationContract>
|
||||
Function GetServiceStatus() As Messages.ServiceStatusResponse
|
||||
#End Region
|
||||
|
||||
#Region "Database"
|
||||
|
||||
11
Service.EDMIService/Messages/GetServiceStatus.vb
Normal file
11
Service.EDMIService/Messages/GetServiceStatus.vb
Normal file
@@ -0,0 +1,11 @@
|
||||
Imports System.Runtime.Serialization
|
||||
|
||||
Namespace Messages
|
||||
<DataContract>
|
||||
Public Class ServiceStatusResponse
|
||||
<DataMember> Public Property ActiveSessionCount As Integer
|
||||
<DataMember> Public Property ActiveUsers As List(Of String) ' Distinct, sortiert
|
||||
<DataMember> Public Property ActiveSessions As Dictionary(Of String, String) ' SessionId → Username
|
||||
<DataMember> Public Property Timestamp As DateTime
|
||||
End Class
|
||||
End Namespace
|
||||
@@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices
|
||||
<Assembly: AssemblyCompany("Digital Data")>
|
||||
<Assembly: AssemblyProduct("EDMIService")>
|
||||
<Assembly: AssemblyCopyright("2026")>
|
||||
<Assembly: AssemblyTrademark("2.5.0")>
|
||||
<Assembly: AssemblyTrademark("2.6.0")>
|
||||
|
||||
<Assembly: ComVisible(False)>
|
||||
|
||||
@@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices
|
||||
' übernehmen, indem Sie "*" eingeben:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("2.5.0.0")>
|
||||
<Assembly: AssemblyFileVersion("2.5.0.0")>
|
||||
<Assembly: AssemblyVersion("2.6.0.0")>
|
||||
<Assembly: AssemblyFileVersion("2.6.0.0")>
|
||||
|
||||
@@ -137,7 +137,7 @@ Public Class WindowsService
|
||||
Logger.Error(ex)
|
||||
GracefullyStop()
|
||||
End Try
|
||||
Logger.Info("✔ Service [{0}] started successfully!", SERVICE_DISPLAY_NAME)
|
||||
Logger.Info("✔ Service [{0}] started and initialized successfully!", SERVICE_DISPLAY_NAME)
|
||||
Catch ex As Exception
|
||||
Logger.Warn("⚠ Unexpected Error while starting the service: {0}", ex.Message)
|
||||
Logger.Error(ex)
|
||||
|
||||
Reference in New Issue
Block a user