Files
egwmultienginemanager/EgwMultiEngineManager.Tray/Utility/EnvironmentManager.vb
T
Emmanuele Sassi 236c1f5be1 - aggiunto parametro FreeOrWaitingAnswerProcesses
- cambiato formato tempo di esecuzione in statistiche
- gestita risposta SubMode 4 in Rest
2026-01-29 10:25:23 +01:00

372 lines
18 KiB
VB.net

Imports System.IO
Imports System.Net.Http
Imports System.Text.Json.Nodes
Imports System.Windows.Threading
Imports EgtDotNETBasis
Imports EgwMultiEngineManager.Core
Imports EgwMultiEngineManager.Data
Imports EgwMultiEngineManager.Data.Constants
Imports Newtonsoft.Json
Imports RestSharp
Imports StackExchange.Redis
Public Class ExecEnvironmentManager
Implements IDisposable
Public Enum EnvironmentCommunicationTypes As Integer
NULL = 0
REDIS = 1
REST = 2
End Enum
Public Event StatisticUpdate(sGroupName As String, Statistics As Statistics)
Private ConstChnName_EgwEngineInput As String = "EgwEngineInput"
Private ConstChnName_EgwEngineOutput As String = "EgwEngineOutput"
Private ConstChnName_EgwStatistics As String = "EgwStatistics"
Private m_bDevMode As Boolean = False
Private ConstChnName_EgwDevEngineInput As String = "EgwDevEngineInput"
Private ConstChnName_EgwDevEngineOutput As String = "EgwDevEngineOutput"
Private ConstChnName_EgwDevStatistics As String = "EgwDevStatistics"
Private disposedValue As Boolean
Private m_nRequestCounter As Integer = 0
Private ReadOnly Property nRequestCounter As Integer
Get
m_nRequestCounter += 1
Return m_nRequestCounter
End Get
End Property
Private m_RestTimer As New DispatcherTimer
Friend ReadOnly Property RestTimer As DispatcherTimer
Get
Return m_RestTimer
End Get
End Property
Private m_EnvironmentCommunicationType As EnvironmentCommunicationTypes
Private m_ExecEnvironment As EXECENVIRONMENTS = EXECENVIRONMENTS.NULL
Friend ReadOnly Property ExecEnvironment As EXECENVIRONMENTS
Get
Return m_ExecEnvironment
End Get
End Property
Private m_sGroupName As String = String.Empty
Friend ReadOnly Property GroupName As String
Get
Return m_sGroupName
End Get
End Property
Private Shared m_RedisManager As RedisManager
Friend Shared Sub SetRedisManager(RedisManager As RedisManager)
m_RedisManager = RedisManager
End Sub
Friend ReadOnly Property ChnName_EgwEngineInput As String
Get
Return If(m_bDevMode, ConstChnName_EgwDevEngineInput, ConstChnName_EgwEngineInput)
End Get
End Property
Friend ReadOnly Property ChnName_EgwEngineOutput As String
Get
Return If(m_bDevMode, ConstChnName_EgwDevEngineOutput, ConstChnName_EgwEngineOutput)
End Get
End Property
Friend ReadOnly Property ChnName_EgwStatistics As String
Get
Return If(m_bDevMode, ConstChnName_EgwDevStatistics, ConstChnName_EgwStatistics)
End Get
End Property
Private m_bChannelFromAnswer As Boolean = False
Private m_ExecProcessManager As ExecProcessManager
Public ReadOnly Property ExecProcessManager As ExecProcessManager
Get
Return m_ExecProcessManager
End Get
End Property
Private m_Client As RestClient
Friend ReadOnly Property Client As RestClient
Get
Return m_Client
End Get
End Property
Private m_chnEgwEngineOutput As RedisChannel
Private m_chnEgwEngineInput As RedisChannel
Private m_chnEgwStatistics As RedisChannel
' statistics
Private m_stopWatch As New Stopwatch()
Private m_dMinProcessingTime As Double = 0
Private m_dMidProcessingTime As Double = 0
Private m_dMaxProcessingTime As Double = 0
Private m_nProcessingQty As Integer = 0
Friend Shared Function CreateExecEnvironmentManager(nType As EnvironmentCommunicationTypes, nGroupIndex As Integer, ByRef NewExecEnvironmentManager As ExecEnvironmentManager) As Boolean
Dim sConnection As String = "localhost"
GetMainPrivateProfileString(S_GENERAL, K_REDISCONNECTION, "", sConnection)
Dim sCamExePath As String = ""
GetMainPrivateProfileString(S_GENERAL, K_CAMEXEPATH, "", sCamExePath)
Dim sPipeLuaDirName As String = ""
GetMainPrivateProfileString(S_GENERAL, K_PIPELUADIRNAME, "", sPipeLuaDirName)
Dim sEnvironment As String = ""
Dim sPipeLuaFile As String = ""
Dim nMaxCamInstances As Integer = 0
Dim bDebug As Boolean = False
Dim sGroupName As String = If(nType = EnvironmentCommunicationTypes.REST, S_RESTEXECGROUP, S_EXECGROUP) & nGroupIndex.ToString()
If GetMainPrivateProfileString(sGroupName, K_ENVIRONMENT, "", sEnvironment) > 0 AndAlso
GetMainPrivateProfileString(sGroupName, K_PIPELUAFILE, "", sPipeLuaFile) AndAlso
GetMainPrivateProfileString(sGroupName, K_MAXCAMINSTANCES, "", nMaxCamInstances) Then
EgtOutLog(If(nType = EnvironmentCommunicationTypes.REST, "REST", "") & "Group" & nGroupIndex.ToString())
EgtOutLog("Environment = " & sEnvironment)
EgtOutLog("PipeLuaFile = " & sPipeLuaFile)
EgtOutLog("MaxCAMInstances = " & nMaxCamInstances)
If nMaxCamInstances <= 0 Then
EgtOutLog("No Cam instances assigned!")
EgtOutLog(String.Format(sGroupName & " will not be created!"))
nGroupIndex += 1
Return True
End If
Dim ExecEnvironment As EXECENVIRONMENTS = GetExecEnvironmentFromString(sEnvironment)
If ExecEnvironment = EXECENVIRONMENTS.NULL Then
EgtOutLog("No ExecEnvironment assigned!")
EgtOutLog(String.Format(sGroupName & " will not be created!"))
nGroupIndex += 1
Return True
End If
Dim sPipeLuaPath As String = Map.refMainWindowVM.sDataRoot & "\" & sPipeLuaDirName & "\" & sPipeLuaFile
If Not File.Exists(sPipeLuaPath) Then
EgtOutLog("Lua file not assigned or not found!")
EgtOutLog(String.Format(sGroupName & " will not be created!"))
nGroupIndex += 1
Return True
End If
Dim sProcessArguments As String = """" & sPipeLuaPath & """ " & """" & sConnection & """"
' leggo se modalita' debug
Dim nDebug As Integer = GetMainPrivateProfileInt(sGroupName, K_DEBUG, 0)
bDebug = (nDebug = 1)
NewExecEnvironmentManager = New ExecEnvironmentManager(nType, sGroupName, ExecEnvironment, nGroupIndex, sCamExePath, sProcessArguments, nMaxCamInstances, ExecProcessManager.ReturnModes.EVENT_, bDebug)
EgtOutLog(String.Format(sGroupName & " created"))
Return True
Else
Return False
End If
End Function
Sub New(nType As EnvironmentCommunicationTypes, sGroupName As String, nEnvironment As EXECENVIRONMENTS, nGroupId As Integer, sProcessFileName As String, sProcessArguments As String, nMaxCamInstances As Integer, bReturnMode As ExecProcessManager.ReturnModes, bDebug As Boolean)
m_EnvironmentCommunicationType = nType
m_sGroupName = sGroupName
Select Case m_EnvironmentCommunicationType
Case EnvironmentCommunicationTypes.REDIS
m_ExecEnvironment = nEnvironment
m_ExecProcessManager = New ExecProcessManager(nGroupId, nEnvironment, sProcessFileName, sProcessArguments, nMaxCamInstances, ExecProcessManager.ReturnModes.EVENT_, bDebug)
AddHandler m_ExecProcessManager.m_AnswerReceived, AddressOf ExecProcessManager_AnswerReceived
AddHandler m_ExecProcessManager.m_Statistics, AddressOf ExecProcessManager_Statistics
m_ExecProcessManager.StartExecutionThread()
' leggo canali input/output
Dim sIniGroup As String = S_EXECGROUP & nGroupId.ToString()
m_bChannelFromAnswer = (GetMainPrivateProfileInt(sIniGroup, K_CHANNELFROMANSWER, 0) = 1)
Dim sInputChannelName As String = ""
GetMainPrivateProfileString(sIniGroup, K_INPUTCHANNEL, "Egw%%EngineInput", sInputChannelName)
ConstChnName_EgwEngineInput = sInputChannelName.Replace("%%", "").Replace("@@", "")
ConstChnName_EgwDevEngineInput = sInputChannelName.Replace("%%", "Dev").Replace("@@", "")
Dim sOutputChannelName As String = ""
GetMainPrivateProfileString(sIniGroup, K_OUTPUTCHANNEL, "Egw%%EngineOutput", sOutputChannelName)
ConstChnName_EgwEngineOutput = sOutputChannelName.Replace("%%", "").Replace("@@", "")
ConstChnName_EgwDevEngineOutput = sOutputChannelName.Replace("%%", "Dev").Replace("@@", "")
Dim sStatisticsChannelName As String = ""
GetMainPrivateProfileString(sIniGroup, K_STATISTICSCHANNEL, "Egw%%Statistics@@", sStatisticsChannelName)
Dim sIpAddress As String = ":" & GetPcData.GetIPAddress().ToString
ConstChnName_EgwStatistics = sStatisticsChannelName.Replace("%%", "").Replace("@@", sIpAddress)
ConstChnName_EgwDevStatistics = sStatisticsChannelName.Replace("%%", "Dev").Replace("@@", sIpAddress)
m_chnEgwEngineOutput = New RedisChannel(ChnName_EgwEngineOutput, RedisChannel.PatternMode.Auto)
m_chnEgwEngineInput = New RedisChannel(ChnName_EgwEngineInput, RedisChannel.PatternMode.Auto)
m_chnEgwStatistics = New RedisChannel(ChnName_EgwStatistics, RedisChannel.PatternMode.Auto)
m_RedisManager.SubscribeChannel(m_chnEgwEngineInput, AddressOf EgwEngineInputHandler)
Case EnvironmentCommunicationTypes.REST
m_ExecEnvironment = nEnvironment
m_ExecProcessManager = New ExecProcessManager(nGroupId + 1000, nEnvironment, sProcessFileName, sProcessArguments, nMaxCamInstances, ExecProcessManager.ReturnModes.EVENT_, bDebug)
m_chnEgwStatistics = New RedisChannel(ChnName_EgwStatistics, RedisChannel.PatternMode.Auto)
AddHandler m_ExecProcessManager.m_AnswerReceived, AddressOf ExecProcessManager_AnswerReceived
AddHandler m_ExecProcessManager.m_Statistics, AddressOf ExecProcessManager_Statistics
m_ExecProcessManager.StartExecutionThread()
'm_Client = New RestClient("https://office.egalware.com/lux/srv/api")
m_Client = New RestClient("https://iis01.egalware.com/lux/srv/api")
m_RestTimer.Interval = TimeSpan.FromMilliseconds(1000)
AddHandler m_RestTimer.Tick, AddressOf RestTimer_Tick
m_RestTimer.Start()
'RestTimer_Tick(Nothing, Nothing)
End Select
End Sub
Friend Shared Function GetExecEnvironmentFromString(sEnvironment As String) As EXECENVIRONMENTS
Select Case sEnvironment
Case "WINDOW"
Return EXECENVIRONMENTS.WINDOW
Case "BEAM"
Return EXECENVIRONMENTS.BEAM
Case "WALL"
Return EXECENVIRONMENTS.WALL
Case "CABINET"
Return EXECENVIRONMENTS.CABINET
Case Else
Return EXECENVIRONMENTS.NULL
End Select
End Function
Private Async Sub RestTimer_Tick(sender As Object, e As EventArgs)
Dim nProcessedQuestion As Integer = 0
While m_ExecProcessManager.nFreeProcesses > 0 And m_ExecProcessManager.ArgumentsQueueCount < m_ExecProcessManager.nFreeProcesses And nProcessedQuestion < m_ExecProcessManager.nRunningProcesses
Dim request As New RestRequest("Prod/getnext", Method.Get)
Dim response = Await m_Client.ExecuteAsync(request)
If response.StatusCode = Net.HttpStatusCode.OK Then
m_stopWatch.Restart()
Dim Question As QuestionDTO = JsonConvert.DeserializeObject(Of QuestionDTO)(response.Content)
If Not IsNothing(Question) AndAlso Question.ExecEnvironment = m_ExecEnvironment Then
Question.SetId(nRequestCounter)
EgtOutLog(DateTime.Now.ToString("HH:mm:ss.fff") & " Environment=" & m_ExecEnvironment & " Channel=REST Question Id=" & Question.nId)
m_ExecProcessManager.ArgumentsEnqueue(Question)
nProcessedQuestion += 1
Else
EgtOutLog(DateTime.Now.ToString("HH:mm:ss.fff") & "Errore! Environment=" & m_ExecEnvironment & " Channel=REST Content=" & response.Content)
End If
Else
' se non ci sono domande, esco
Return
End If
End While
End Sub
Private Sub EgwEngineInputHandler(RedisChannel As RedisChannel, RedisValue As RedisValue)
m_stopWatch.Restart()
Dim Question As QuestionDTO = JsonConvert.DeserializeObject(Of QuestionDTO)(RedisValue)
If Question.ExecEnvironment = m_ExecEnvironment Then
Question.SetId(nRequestCounter)
EgtOutLog(DateTime.Now.ToString("HH:mm:ss.fff") & " Environment=" & m_ExecEnvironment & " Channel=" & RedisChannel.ToString() & " Question Id=" & Question.nId)
m_ExecProcessManager.ArgumentsEnqueue(Question)
End If
End Sub
Private Sub ExecProcessManager_AnswerReceived(Answer As AnswerDTO)
Select Case m_EnvironmentCommunicationType
Case EnvironmentCommunicationTypes.REDIS
Dim chnEgwEngineOutput As RedisChannel = m_chnEgwEngineOutput
If m_bChannelFromAnswer AndAlso Answer.Args.ContainsKey("OutputChannel") Then
Dim ChnName_Output As String = Answer.Args("OutputChannel")
If Not String.IsNullOrWhiteSpace(ChnName_Output) Then
chnEgwEngineOutput = New RedisChannel(ChnName_Output, RedisChannel.PatternMode.Auto)
End If
End If
EgtOutLog(DateTime.Now.ToString("HH:mm:ss.fff") & " Environment=" & m_ExecEnvironment & " Channel=" & chnEgwEngineOutput.ToString() & " Answer Id=" & Answer.nId)
m_RedisManager.Publish(chnEgwEngineOutput, JsonConvert.SerializeObject(Answer))
m_stopWatch.Stop()
' Format and display the TimeSpan value.
Dim elapsedTime As String = String.Format("{0:N3}", m_stopWatch.Elapsed.TotalMilliseconds)
m_nProcessingQty += 1
If m_dMinProcessingTime = 0 OrElse m_stopWatch.Elapsed.TotalMilliseconds < m_dMinProcessingTime Then m_dMinProcessingTime = m_stopWatch.Elapsed.TotalMilliseconds
If m_nProcessingQty > 1 Then
m_dMidProcessingTime = ((m_dMidProcessingTime * (m_nProcessingQty - 1)) / m_nProcessingQty) + (m_stopWatch.Elapsed.TotalMilliseconds / m_nProcessingQty)
Else
m_dMidProcessingTime = m_stopWatch.Elapsed.TotalMilliseconds
End If
If m_stopWatch.Elapsed.TotalMilliseconds > m_dMaxProcessingTime Then m_dMaxProcessingTime = m_stopWatch.Elapsed.TotalMilliseconds
EgtOutLog("Answer " & Answer.nId & " calculated in " & elapsedTime & "ms")
Case EnvironmentCommunicationTypes.REST
If Answer.Args.ContainsKey("Mode") AndAlso Answer.Args.ContainsKey("SubMode") Then
Dim request As RestRequest = Nothing
Dim nMode As Integer = Answer.Args("Mode")
Dim nSubMode As Integer = Answer.Args("SubMode")
Select Case nMode
Case 5
Select Case nSubMode
Case 1
request = New RestRequest("Prod/jobreturn", Method.Post)
Case 2
request = New RestRequest("Prod/jobreturn", Method.Post)
Case 3
request = New RestRequest("Prod/jobreturn", Method.Post)
Case 4
request = New RestRequest("Prod/jobreturn", Method.Post)
End Select
End Select
'request.AddBody(JsonConvert.SerializeObject(Answer))
request.AddStringBody(JsonConvert.SerializeObject(Answer), DataFormat.Json)
EgtOutLog(DateTime.Now.ToString("HH:mm:ss.fff") & " Environment=" & m_ExecEnvironment & " Channel=REST Answer Id=" & Answer.nId)
' Eseguo la chiamata
Dim response As RestResponse = Client.Execute(request)
' Controllo l'esito
If response.IsSuccessful Then
EgtOutLog("Answer Id=" & Answer.nId & "inviata con successo!")
Else
EgtOutLog("Errore! Answer Id=" & Answer.nId & " Description=" & response.StatusDescription)
End If
Else
EgtOutLog("Errore! Risposta senza Mode o SubMode!")
End If
m_stopWatch.Stop()
' Format and display the TimeSpan value.
Dim elapsedTime As String = String.Format("{0:N3}", m_stopWatch.Elapsed.TotalMilliseconds)
m_nProcessingQty += 1
If m_dMinProcessingTime = 0 OrElse m_stopWatch.Elapsed.TotalMilliseconds < m_dMinProcessingTime Then m_dMinProcessingTime = m_stopWatch.Elapsed.TotalMilliseconds
If m_nProcessingQty > 1 Then
m_dMidProcessingTime = ((m_dMidProcessingTime * (m_nProcessingQty - 1)) / m_nProcessingQty) + (m_stopWatch.Elapsed.TotalMilliseconds / m_nProcessingQty)
Else
m_dMidProcessingTime = m_stopWatch.Elapsed.TotalMilliseconds
End If
If m_stopWatch.Elapsed.TotalMilliseconds > m_dMaxProcessingTime Then m_dMaxProcessingTime = m_stopWatch.Elapsed.TotalMilliseconds
EgtOutLog("Answer " & Answer.nId & " calculated in " & elapsedTime & "ms")
End Select
End Sub
Private Sub ExecProcessManager_Statistics(e As Statistics)
Dim CurrManagerStatistics As Statistics = e
CurrManagerStatistics.SetProcessingTimes(m_dMinProcessingTime, m_dMidProcessingTime, m_dMaxProcessingTime)
RaiseEvent StatisticUpdate(m_sGroupName, CurrManagerStatistics)
If Not IsNothing(m_chnEgwStatistics) Then
m_RedisManager.Publish(m_chnEgwStatistics, JsonConvert.SerializeObject(CurrManagerStatistics))
End If
m_nProcessingQty = 0
m_dMinProcessingTime = 100000
m_dMidProcessingTime = 0
m_dMaxProcessingTime = 0
End Sub
Protected Overridable Sub Dispose(disposing As Boolean)
If Not disposedValue Then
If disposing Then
' TODO: dispose managed state (managed objects)
End If
' TODO: free unmanaged resources (unmanaged objects) and override finalizer
' TODO: set large fields to null
m_ExecProcessManager.Dispose()
disposedValue = True
End If
End Sub
' ' TODO: override finalizer only if 'Dispose(disposing As Boolean)' has code to free unmanaged resources
' Protected Overrides Sub Finalize()
' ' Do not change this code. Put cleanup code in 'Dispose(disposing As Boolean)' method
' Dispose(disposing:=False)
' MyBase.Finalize()
' End Sub
Public Sub Dispose() Implements IDisposable.Dispose
' Do not change this code. Put cleanup code in 'Dispose(disposing As Boolean)' method
Dispose(disposing:=True)
GC.SuppressFinalize(Me)
End Sub
End Class