diff --git a/GUIs.ClientSuite/Workers/HeartbeatWorker.vb b/GUIs.ClientSuite/Workers/HeartbeatWorker.vb index 7bba52ba..892b90bd 100644 --- a/GUIs.ClientSuite/Workers/HeartbeatWorker.vb +++ b/GUIs.ClientSuite/Workers/HeartbeatWorker.vb @@ -1,47 +1,44 @@ Imports System.Timers -Imports DigitalData.GUIs.ClientSuite Imports DigitalData.GUIs.ClientSuite.Base -Imports DigitalData.Modules.EDMIAPI.IDBServiceReference Imports DigitalData.Modules.Logging + Namespace Workers Public Class HeartbeatWorker Inherits BaseClass Implements IWorker - Private _Channel As IIDBServiceChannel - Public Event OnlineChanged As OnlineChangedEventHandler Public Delegate Sub OnlineChangedEventHandler(sender As Object, Online As Boolean) 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) MyBase.New(LogConfig) End Sub Public Sub Setup() Implements IWorker.Setup - _Channel = My.ChannelFactory.CreateChannel() - _Channel.Open() + Logger.Debug("Starting {0}", "HeartbeatWorker") 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 - Logger.Debug("Checking if Service is up...") - - If _Channel.State = ServiceModel.CommunicationState.Faulted Then - _Channel = My.ChannelFactory.CreateChannel() + If My.Channel.State = ServiceModel.CommunicationState.Faulted Then + My.Channel = My.ChannelFactory.CreateChannel() End If ' Connect to service and send hearbeat request - Dim oResult = Await _Channel.HeartbeatAsync() + Dim oResult = Await My.Channel.HeartbeatAsync() Logger.Debug("Service is online") SetOnlineState(True) Catch ex As Exception + Logger.Debug("Service is offline!") Logger.Error(ex) + Manager.StopWorkers() SetOnlineState(False) Finally My.Application.Service.LastChecked = DateTime.Now @@ -49,7 +46,7 @@ Namespace Workers End Sub Public Sub Teardown() Implements IWorker.Teardown - ' TODO: Close channel gracefully + Logger.Debug("Stopping {0}", Name) End Sub Private Sub SetOnlineState(NewState As Boolean) diff --git a/GUIs.ClientSuite/Workers/IWorker.vb b/GUIs.ClientSuite/Workers/IWorker.vb index 9405ca10..3a967712 100644 --- a/GUIs.ClientSuite/Workers/IWorker.vb +++ b/GUIs.ClientSuite/Workers/IWorker.vb @@ -3,6 +3,7 @@ Namespace Workers Public Interface IWorker ReadOnly Property Interval As Integer + ReadOnly Property Name As String Sub Setup() Sub Teardown() diff --git a/GUIs.ClientSuite/Workers/WorkerManager.vb b/GUIs.ClientSuite/Workers/WorkerManager.vb index e48e1fa9..e3407bc7 100644 --- a/GUIs.ClientSuite/Workers/WorkerManager.vb +++ b/GUIs.ClientSuite/Workers/WorkerManager.vb @@ -6,6 +6,14 @@ Namespace Workers Public Class WorkerManager Inherits BaseClass + ''' + ''' Holds information about a worker + ''' + Class WorkerState + Public Worker As IWorker + Public Timer As Timer + End Class + ''' ''' List of workers that will be started. ''' @@ -13,52 +21,73 @@ Namespace Workers GetType(HeartbeatWorker), GetType(WorkflowOverviewWorker) } - Private Workers As New List(Of IWorker) - Private TimerList As New List(Of Timer) + Private Workers As New List(Of WorkerState) Public Sub New(LogConfig As LogConfig, SyncronizingObject As frmMain) MyBase.New(LogConfig) - Workers = CreateWorkers() - - 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 + Workers = CreateWorkers(SyncronizingObject) End Sub Public Function GetWorker(Of T)() As T - For Each oWorker In Workers - If TypeOf oWorker Is T Then - Return oWorker + For Each oWorkerState As WorkerState In Workers + If TypeOf oWorkerState.Worker Is T Then + Return oWorkerState.Worker End If Next Return Nothing End Function - Private Function CreateWorkers() As List(Of IWorker) - Dim oWorkers As New List(Of IWorker) + Public Sub StopWorkers() + 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 + Dim oWorker As IWorker = Activator.CreateInstance(oWorkerType, New Object() {LogConfig}) + Try - Dim oWorker As IWorker = Activator.CreateInstance(oWorkerType, New Object() {LogConfig}) oWorker.Setup() - oWorkers.Add(oWorker) + + Dim oWorkerState As New WorkerState() With { + .Worker = oWorker, + .Timer = CreateTimer(oWorker, SyncronizingObject) + } + + oWorkers.Add(oWorkerState) 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) Continue For End Try diff --git a/GUIs.ClientSuite/Workers/WorkflowOverviewWorker.vb b/GUIs.ClientSuite/Workers/WorkflowOverviewWorker.vb index e7578624..1e70e8be 100644 --- a/GUIs.ClientSuite/Workers/WorkflowOverviewWorker.vb +++ b/GUIs.ClientSuite/Workers/WorkflowOverviewWorker.vb @@ -12,6 +12,7 @@ Namespace Workers End Sub 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 Throw New NotImplementedException() diff --git a/GUIs.ClientSuite/frmMain.vb b/GUIs.ClientSuite/frmMain.vb index 72e3aa99..257ecca3 100644 --- a/GUIs.ClientSuite/frmMain.vb +++ b/GUIs.ClientSuite/frmMain.vb @@ -37,11 +37,11 @@ Public Class frmMain End Sub Private Sub HandleOnlineChanged(sender As Object, Online As Boolean) + SetOnlineLabel(Online) If Online = False Then - + MessageBox.Show($"Application will be closed now.{vbNewLine}Reason: Service is offline.", "Critical Error", MessageBoxButtons.OK, MessageBoxIcon.Error) Application.Exit() End If - SetOnlineLabel(Online) End Sub Private Sub FrmMain_Load(sender As Object, e As EventArgs) Handles Me.Load