ClientSuite: Improve WorkerManager

This commit is contained in:
Jonathan Jenne 2019-06-14 14:18:14 +02:00
parent f1c0a1efd6
commit d3b5955b45
5 changed files with 71 additions and 43 deletions

View File

@ -1,47 +1,44 @@
Imports System.Timers Imports System.Timers
Imports DigitalData.GUIs.ClientSuite
Imports DigitalData.GUIs.ClientSuite.Base Imports DigitalData.GUIs.ClientSuite.Base
Imports DigitalData.Modules.EDMIAPI.IDBServiceReference
Imports DigitalData.Modules.Logging Imports DigitalData.Modules.Logging
Namespace Workers Namespace Workers
Public Class HeartbeatWorker Public Class HeartbeatWorker
Inherits BaseClass Inherits BaseClass
Implements IWorker Implements IWorker
Private _Channel As IIDBServiceChannel
Public Event OnlineChanged As OnlineChangedEventHandler Public Event OnlineChanged As OnlineChangedEventHandler
Public Delegate Sub OnlineChangedEventHandler(sender As Object, Online As Boolean) Public Delegate Sub OnlineChangedEventHandler(sender As Object, Online As Boolean)
Public ReadOnly Property Interval As Integer = 4000 Implements IWorker.Interval Public ReadOnly Property Interval As Integer = 4000 Implements IWorker.Interval
Public ReadOnly Property Name As String = "Heartbeat Worker" Implements IWorker.Name
Public Sub New(LogConfig As LogConfig) Public Sub New(LogConfig As LogConfig)
MyBase.New(LogConfig) MyBase.New(LogConfig)
End Sub End Sub
Public Sub Setup() Implements IWorker.Setup Public Sub Setup() Implements IWorker.Setup
_Channel = My.ChannelFactory.CreateChannel() Logger.Debug("Starting {0}", "HeartbeatWorker")
_Channel.Open()
End Sub End Sub
Public Async Sub Callback(manager As WorkerManager, e As ElapsedEventArgs) Implements IWorker.Callback Public Async Sub Callback(Manager As WorkerManager, e As ElapsedEventArgs) Implements IWorker.Callback
Try Try
Logger.Debug("Checking if Service is up...") If My.Channel.State = ServiceModel.CommunicationState.Faulted Then
My.Channel = My.ChannelFactory.CreateChannel()
If _Channel.State = ServiceModel.CommunicationState.Faulted Then
_Channel = My.ChannelFactory.CreateChannel()
End If End If
' Connect to service and send hearbeat request ' Connect to service and send hearbeat request
Dim oResult = Await _Channel.HeartbeatAsync() Dim oResult = Await My.Channel.HeartbeatAsync()
Logger.Debug("Service is online") Logger.Debug("Service is online")
SetOnlineState(True) SetOnlineState(True)
Catch ex As Exception Catch ex As Exception
Logger.Debug("Service is offline!") Logger.Debug("Service is offline!")
Logger.Error(ex) Logger.Error(ex)
Manager.StopWorkers()
SetOnlineState(False) SetOnlineState(False)
Finally Finally
My.Application.Service.LastChecked = DateTime.Now My.Application.Service.LastChecked = DateTime.Now
@ -49,7 +46,7 @@ Namespace Workers
End Sub End Sub
Public Sub Teardown() Implements IWorker.Teardown Public Sub Teardown() Implements IWorker.Teardown
' TODO: Close channel gracefully Logger.Debug("Stopping {0}", Name)
End Sub End Sub
Private Sub SetOnlineState(NewState As Boolean) Private Sub SetOnlineState(NewState As Boolean)

View File

@ -3,6 +3,7 @@
Namespace Workers Namespace Workers
Public Interface IWorker Public Interface IWorker
ReadOnly Property Interval As Integer ReadOnly Property Interval As Integer
ReadOnly Property Name As String
Sub Setup() Sub Setup()
Sub Teardown() Sub Teardown()

View File

@ -6,6 +6,14 @@ Namespace Workers
Public Class WorkerManager Public Class WorkerManager
Inherits BaseClass Inherits BaseClass
''' <summary>
''' Holds information about a worker
''' </summary>
Class WorkerState
Public Worker As IWorker
Public Timer As Timer
End Class
''' <summary> ''' <summary>
''' List of workers that will be started. ''' List of workers that will be started.
''' </summary> ''' </summary>
@ -13,52 +21,73 @@ Namespace Workers
GetType(HeartbeatWorker), GetType(HeartbeatWorker),
GetType(WorkflowOverviewWorker) GetType(WorkflowOverviewWorker)
} }
Private Workers As New List(Of IWorker) Private Workers As New List(Of WorkerState)
Private TimerList As New List(Of Timer)
Public Sub New(LogConfig As LogConfig, SyncronizingObject As frmMain) Public Sub New(LogConfig As LogConfig, SyncronizingObject As frmMain)
MyBase.New(LogConfig) MyBase.New(LogConfig)
Workers = CreateWorkers() Workers = CreateWorkers(SyncronizingObject)
For Each oWorker As IWorker In Workers
Dim oTimer = New Timer(oWorker.Interval) With {
.SynchronizingObject = SyncronizingObject,
.Enabled = True
}
AddHandler oTimer.Elapsed, Sub(sender As Object, e As ElapsedEventArgs)
Try
oWorker.Callback(Me, e)
Catch ex As Exception
Logger.Warn("Worker {0} threw an error in callback.", oWorker.GetType.Name)
End Try
End Sub
TimerList.Add(oTimer)
Next
End Sub End Sub
Public Function GetWorker(Of T)() As T Public Function GetWorker(Of T)() As T
For Each oWorker In Workers For Each oWorkerState As WorkerState In Workers
If TypeOf oWorker Is T Then If TypeOf oWorkerState.Worker Is T Then
Return oWorker Return oWorkerState.Worker
End If End If
Next Next
Return Nothing Return Nothing
End Function End Function
Private Function CreateWorkers() As List(Of IWorker) Public Sub StopWorkers()
Dim oWorkers As New List(Of IWorker) Logger.Debug("Stopping all workers..")
For Each oWorkerState In Workers
oWorkerState.Timer.Stop()
Try
oWorkerState.Worker.Teardown()
Catch ex As Exception
Logger.Warn("Worker {0} threw an error during teardown.", oWorkerState.Worker.Name)
End Try
Next
Logger.Debug("All workers stopped.")
End Sub
Private Function CreateTimer(Worker As IWorker, SyncronizingObject As frmMain)
Dim oTimer = New Timer(Worker.Interval) With {
.SynchronizingObject = SyncronizingObject,
.Enabled = True
}
AddHandler oTimer.Elapsed, Sub(sender As Object, e As ElapsedEventArgs)
Try
Worker.Callback(Me, e)
Catch ex As Exception
Logger.Warn("Worker {0} threw an error in callback.", Worker.Name)
Logger.Error(ex)
End Try
End Sub
Return oTimer
End Function
Private Function CreateWorkers(SyncronizingObject As frmMain) As List(Of WorkerState)
Dim oWorkers As New List(Of WorkerState)
For Each oWorkerType In WorkerTypes For Each oWorkerType In WorkerTypes
Dim oWorker As IWorker = Activator.CreateInstance(oWorkerType, New Object() {LogConfig})
Try Try
Dim oWorker As IWorker = Activator.CreateInstance(oWorkerType, New Object() {LogConfig})
oWorker.Setup() oWorker.Setup()
oWorkers.Add(oWorker)
Dim oWorkerState As New WorkerState() With {
.Worker = oWorker,
.Timer = CreateTimer(oWorker, SyncronizingObject)
}
oWorkers.Add(oWorkerState)
Catch ex As Exception Catch ex As Exception
Logger.Warn("Worker {0} threw an error while creating. Skipping.", oWorkerType.Name) Logger.Warn("Worker {0} threw an error during setup. Skipping.", oWorker.Name)
Logger.Error(ex) Logger.Error(ex)
Continue For Continue For
End Try End Try

View File

@ -12,6 +12,7 @@ Namespace Workers
End Sub End Sub
Public ReadOnly Property Interval As Integer = 60000 Implements IWorker.Interval Public ReadOnly Property Interval As Integer = 60000 Implements IWorker.Interval
Public ReadOnly Property Name As String = "WorkflowOverview Worker" Implements IWorker.Name
Public Sub Setup() Implements IWorker.Setup Public Sub Setup() Implements IWorker.Setup
Throw New NotImplementedException() Throw New NotImplementedException()

View File

@ -37,11 +37,11 @@ Public Class frmMain
End Sub End Sub
Private Sub HandleOnlineChanged(sender As Object, Online As Boolean) Private Sub HandleOnlineChanged(sender As Object, Online As Boolean)
SetOnlineLabel(Online)
If Online = False Then If Online = False Then
MessageBox.Show($"Application will be closed now.{vbNewLine}Reason: Service is offline.", "Critical Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
Application.Exit() Application.Exit()
End If End If
SetOnlineLabel(Online)
End Sub End Sub
Private Sub FrmMain_Load(sender As Object, e As EventArgs) Handles Me.Load Private Sub FrmMain_Load(sender As Object, e As EventArgs) Handles Me.Load