09-12-2022
This commit is contained in:
parent
0a25b0925c
commit
8d6d81f488
@ -33,10 +33,34 @@
|
||||
<xs:element minOccurs="0" name="ErrorMessage" nillable="true" type="xs:string" />
|
||||
<xs:element minOccurs="0" name="JobName" nillable="true" type="xs:string" />
|
||||
<xs:element minOccurs="0" name="Message" nillable="true" type="xs:string" />
|
||||
<xs:element minOccurs="0" name="Steps" nillable="true" type="tns:ArrayOfHistoryItem.HistoryStep" />
|
||||
<xs:element minOccurs="0" name="Successful" type="xs:boolean" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="HistoryItem" nillable="true" type="tns:HistoryItem" />
|
||||
<xs:complexType name="ArrayOfHistoryItem.HistoryStep">
|
||||
<xs:sequence>
|
||||
<xs:element minOccurs="0" maxOccurs="unbounded" name="HistoryItem.HistoryStep" nillable="true" type="tns:HistoryItem.HistoryStep" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="ArrayOfHistoryItem.HistoryStep" nillable="true" type="tns:ArrayOfHistoryItem.HistoryStep" />
|
||||
<xs:complexType name="HistoryItem.HistoryStep">
|
||||
<xs:sequence>
|
||||
<xs:element minOccurs="0" name="Created" type="xs:dateTime" />
|
||||
<xs:element minOccurs="0" name="Level" type="tns:HistoryItem.StepLevel" />
|
||||
<xs:element minOccurs="0" name="Message" nillable="true" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
<xs:element name="HistoryItem.HistoryStep" nillable="true" type="tns:HistoryItem.HistoryStep" />
|
||||
<xs:simpleType name="HistoryItem.StepLevel">
|
||||
<xs:restriction base="xs:string">
|
||||
<xs:enumeration value="Debug" />
|
||||
<xs:enumeration value="Info" />
|
||||
<xs:enumeration value="Warning" />
|
||||
<xs:enumeration value="Error" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
<xs:element name="HistoryItem.StepLevel" nillable="true" type="tns:HistoryItem.StepLevel" />
|
||||
<xs:complexType name="ArrayOfStatusItem">
|
||||
<xs:sequence>
|
||||
<xs:element minOccurs="0" maxOccurs="unbounded" name="StatusItem" nillable="true" type="tns:StatusItem" />
|
||||
|
||||
@ -296,6 +296,9 @@ Namespace JobRunnerReference
|
||||
<System.Runtime.Serialization.OptionalFieldAttribute()> _
|
||||
Private MessageField As String
|
||||
|
||||
<System.Runtime.Serialization.OptionalFieldAttribute()> _
|
||||
Private StepsField() As JobRunnerReference.HistoryItem.HistoryStep
|
||||
|
||||
<System.Runtime.Serialization.OptionalFieldAttribute()> _
|
||||
Private SuccessfulField As Boolean
|
||||
|
||||
@ -361,6 +364,19 @@ Namespace JobRunnerReference
|
||||
End Set
|
||||
End Property
|
||||
|
||||
<System.Runtime.Serialization.DataMemberAttribute()> _
|
||||
Public Property Steps() As JobRunnerReference.HistoryItem.HistoryStep()
|
||||
Get
|
||||
Return Me.StepsField
|
||||
End Get
|
||||
Set
|
||||
If (Object.ReferenceEquals(Me.StepsField, value) <> true) Then
|
||||
Me.StepsField = value
|
||||
Me.RaisePropertyChanged("Steps")
|
||||
End If
|
||||
End Set
|
||||
End Property
|
||||
|
||||
<System.Runtime.Serialization.DataMemberAttribute()> _
|
||||
Public Property Successful() As Boolean
|
||||
Get
|
||||
@ -382,6 +398,101 @@ Namespace JobRunnerReference
|
||||
propertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(propertyName))
|
||||
End If
|
||||
End Sub
|
||||
|
||||
<System.Diagnostics.DebuggerStepThroughAttribute(), _
|
||||
System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0"), _
|
||||
System.Runtime.Serialization.DataContractAttribute(Name:="HistoryItem.HistoryStep", [Namespace]:="http://schemas.datacontract.org/2004/07/ECM.JobRunner.Windows"), _
|
||||
System.SerializableAttribute()> _
|
||||
Partial Public Class HistoryStep
|
||||
Inherits Object
|
||||
Implements System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged
|
||||
|
||||
<System.NonSerializedAttribute()> _
|
||||
Private extensionDataField As System.Runtime.Serialization.ExtensionDataObject
|
||||
|
||||
<System.Runtime.Serialization.OptionalFieldAttribute()> _
|
||||
Private CreatedField As Date
|
||||
|
||||
<System.Runtime.Serialization.OptionalFieldAttribute()> _
|
||||
Private LevelField As JobRunnerReference.HistoryItem.StepLevel
|
||||
|
||||
<System.Runtime.Serialization.OptionalFieldAttribute()> _
|
||||
Private MessageField As String
|
||||
|
||||
Public Property ExtensionData() As System.Runtime.Serialization.ExtensionDataObject Implements System.Runtime.Serialization.IExtensibleDataObject.ExtensionData
|
||||
Get
|
||||
Return Me.extensionDataField
|
||||
End Get
|
||||
Set
|
||||
Me.extensionDataField = value
|
||||
End Set
|
||||
End Property
|
||||
|
||||
<System.Runtime.Serialization.DataMemberAttribute()> _
|
||||
Public Property Created() As Date
|
||||
Get
|
||||
Return Me.CreatedField
|
||||
End Get
|
||||
Set
|
||||
If (Me.CreatedField.Equals(value) <> true) Then
|
||||
Me.CreatedField = value
|
||||
Me.RaisePropertyChanged("Created")
|
||||
End If
|
||||
End Set
|
||||
End Property
|
||||
|
||||
<System.Runtime.Serialization.DataMemberAttribute()> _
|
||||
Public Property Level() As JobRunnerReference.HistoryItem.StepLevel
|
||||
Get
|
||||
Return Me.LevelField
|
||||
End Get
|
||||
Set
|
||||
If (Me.LevelField.Equals(value) <> true) Then
|
||||
Me.LevelField = value
|
||||
Me.RaisePropertyChanged("Level")
|
||||
End If
|
||||
End Set
|
||||
End Property
|
||||
|
||||
<System.Runtime.Serialization.DataMemberAttribute()> _
|
||||
Public Property Message() As String
|
||||
Get
|
||||
Return Me.MessageField
|
||||
End Get
|
||||
Set
|
||||
If (Object.ReferenceEquals(Me.MessageField, value) <> true) Then
|
||||
Me.MessageField = value
|
||||
Me.RaisePropertyChanged("Message")
|
||||
End If
|
||||
End Set
|
||||
End Property
|
||||
|
||||
Public Event PropertyChanged As System.ComponentModel.PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
|
||||
|
||||
Protected Sub RaisePropertyChanged(ByVal propertyName As String)
|
||||
Dim propertyChanged As System.ComponentModel.PropertyChangedEventHandler = Me.PropertyChangedEvent
|
||||
If (Not (propertyChanged) Is Nothing) Then
|
||||
propertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(propertyName))
|
||||
End If
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
<System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0"), _
|
||||
System.Runtime.Serialization.DataContractAttribute(Name:="HistoryItem.StepLevel", [Namespace]:="http://schemas.datacontract.org/2004/07/ECM.JobRunner.Windows")> _
|
||||
Public Enum StepLevel As Integer
|
||||
|
||||
<System.Runtime.Serialization.EnumMemberAttribute()> _
|
||||
Debug = 0
|
||||
|
||||
<System.Runtime.Serialization.EnumMemberAttribute()> _
|
||||
Info = 1
|
||||
|
||||
<System.Runtime.Serialization.EnumMemberAttribute()> _
|
||||
Warning = 2
|
||||
|
||||
<System.Runtime.Serialization.EnumMemberAttribute()> _
|
||||
[Error] = 3
|
||||
End Enum
|
||||
End Class
|
||||
|
||||
<System.Diagnostics.DebuggerStepThroughAttribute(), _
|
||||
|
||||
@ -5,6 +5,6 @@
|
||||
<binding digest="System.ServiceModel.Configuration.NetTcpBindingElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089:<?xml version="1.0" encoding="utf-16"?><Data name="NetTcpBinding_IEDMIService" transferMode="Streamed"><security><transport sslProtocols="None" /></security></Data>" bindingType="netTcpBinding" name="NetTcpBinding_IEDMIService" />
|
||||
</bindings>
|
||||
<endpoints>
|
||||
<endpoint normalizedDigest="<?xml version="1.0" encoding="utf-16"?><Data address="net.tcp://localhost:9001/DigitalData/Services/JobRunner" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IEDMIService" contract="JobRunnerReference.IEDMIService" name="NetTcpBinding_IEDMIService"><identity><userPrincipalName value="Administrator@dd-san01.dd-gan.local.digitaldata.works" /></identity></Data>" digest="<?xml version="1.0" encoding="utf-16"?><Data address="net.tcp://localhost:9001/DigitalData/Services/JobRunner" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IEDMIService" contract="JobRunnerReference.IEDMIService" name="NetTcpBinding_IEDMIService"><identity><userPrincipalName value="Administrator@dd-san01.dd-gan.local.digitaldata.works" /></identity></Data>" contractName="JobRunnerReference.IEDMIService" name="NetTcpBinding_IEDMIService" />
|
||||
<endpoint normalizedDigest="<?xml version="1.0" encoding="utf-16"?><Data address="net.tcp://localhost:9001/DigitalData/Services/JobRunner" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IEDMIService" contract="JobRunnerReference.IEDMIService" name="NetTcpBinding_IEDMIService"><identity><servicePrincipalName value="host/sDD-VMP03-VM09.dd-san01.dd-gan.local.digitaldata.works" /></identity></Data>" digest="<?xml version="1.0" encoding="utf-16"?><Data address="net.tcp://localhost:9001/DigitalData/Services/JobRunner" binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IEDMIService" contract="JobRunnerReference.IEDMIService" name="NetTcpBinding_IEDMIService"><identity><servicePrincipalName value="host/sDD-VMP03-VM09.dd-san01.dd-gan.local.digitaldata.works" /></identity></Data>" contractName="JobRunnerReference.IEDMIService" name="NetTcpBinding_IEDMIService" />
|
||||
</endpoints>
|
||||
</configurationSnapshot>
|
||||
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<SavedWcfConfigurationInformation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="9.1" CheckSum="DoUniskVeDbP1hRdgocMLRvIRWWXBsyF6LnDt8ZDNTI=">
|
||||
<SavedWcfConfigurationInformation xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Version="9.1" CheckSum="ho0oZcIegSOp+ZGeQ1YrB58dDQqmy97E7VQqQI8HV80=">
|
||||
<bindingConfigurations>
|
||||
<bindingConfiguration bindingType="netTcpBinding" name="NetTcpBinding_IEDMIService">
|
||||
<properties>
|
||||
@ -150,14 +150,14 @@
|
||||
<property path="/identity/userPrincipalName" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.UserPrincipalNameElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<serializedValue>System.ServiceModel.Configuration.UserPrincipalNameElement</serializedValue>
|
||||
</property>
|
||||
<property path="/identity/userPrincipalName/value" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<serializedValue>Administrator@dd-san01.dd-gan.local.digitaldata.works</serializedValue>
|
||||
<property path="/identity/userPrincipalName/value" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<serializedValue />
|
||||
</property>
|
||||
<property path="/identity/servicePrincipalName" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.ServicePrincipalNameElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<serializedValue>System.ServiceModel.Configuration.ServicePrincipalNameElement</serializedValue>
|
||||
</property>
|
||||
<property path="/identity/servicePrincipalName/value" isComplexType="false" isExplicitlyDefined="false" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<serializedValue />
|
||||
<property path="/identity/servicePrincipalName/value" isComplexType="false" isExplicitlyDefined="true" clrType="System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<serializedValue>host/sDD-VMP03-VM09.dd-san01.dd-gan.local.digitaldata.works</serializedValue>
|
||||
</property>
|
||||
<property path="/identity/dns" isComplexType="true" isExplicitlyDefined="false" clrType="System.ServiceModel.Configuration.DnsElement, System.ServiceModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
|
||||
<serializedValue>System.ServiceModel.Configuration.DnsElement</serializedValue>
|
||||
|
||||
@ -93,7 +93,7 @@
|
||||
<wsa10:EndpointReference>
|
||||
<wsa10:Address>net.tcp://localhost:9001/DigitalData/Services/JobRunner</wsa10:Address>
|
||||
<Identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity">
|
||||
<Upn>Administrator@dd-san01.dd-gan.local.digitaldata.works</Upn>
|
||||
<Spn>host/sDD-VMP03-VM09.dd-san01.dd-gan.local.digitaldata.works</Spn>
|
||||
</Identity>
|
||||
</wsa10:EndpointReference>
|
||||
</wsdl:port>
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
binding="netTcpBinding" bindingConfiguration="NetTcpBinding_IEDMIService"
|
||||
contract="JobRunnerReference.IEDMIService" name="NetTcpBinding_IEDMIService">
|
||||
<identity>
|
||||
<userPrincipalName value="Administrator@dd-san01.dd-gan.local.digitaldata.works" />
|
||||
<servicePrincipalName value="host/sDD-VMP03-VM09.dd-san01.dd-gan.local.digitaldata.works" />
|
||||
</identity>
|
||||
</endpoint>
|
||||
</client>
|
||||
|
||||
5
ECM.JobRunner.Web/Components/StatusIcon.razor
Normal file
5
ECM.JobRunner.Web/Components/StatusIcon.razor
Normal file
@ -0,0 +1,5 @@
|
||||
<h3>StatusIcon</h3>
|
||||
|
||||
@code {
|
||||
|
||||
}
|
||||
@ -13,12 +13,18 @@
|
||||
<li class="list-group-item">Loading Job History..</li>
|
||||
</ul>
|
||||
}
|
||||
else
|
||||
else if (historyEntries.Count == 0)
|
||||
{
|
||||
<ul class="list-group">
|
||||
@foreach (var entry in historyEntries)
|
||||
{
|
||||
<li class="list-group-item d-flex justify-content-between align-items-start">
|
||||
<li class="list-group-item">No Job History yet.</li>
|
||||
</ul>
|
||||
}
|
||||
else
|
||||
{
|
||||
@foreach (var entry in historyEntries)
|
||||
{
|
||||
<ul class="list-group mb-3">
|
||||
<li class="list-group-item bg-light bg-gradient d-flex justify-content-between align-items-start">
|
||||
<div class="ms-2 me-auto">
|
||||
<div class="fw-bold">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check-circle text-success" viewBox="0 0 16 16">
|
||||
@ -28,10 +34,26 @@ else
|
||||
<span>@entry.JobName</span>
|
||||
</div>
|
||||
</div>
|
||||
<span class="badge bg-primary rounded-pill">@entry.CreatedAt.ToShortTimeString()</span>
|
||||
</li>
|
||||
}
|
||||
</ul>
|
||||
@foreach (var step in entry.Steps)
|
||||
{
|
||||
<li class="list-group-item">
|
||||
<strong>@step.Created.ToString("HH:mm")</strong> @step.Message
|
||||
</li>
|
||||
}
|
||||
<li class="list-group-item">
|
||||
<strong>@entry.CreatedAt.ToString("HH:mm")</strong> @entry.Message
|
||||
</li>
|
||||
@if (entry.Successful == false)
|
||||
{
|
||||
<li class="list-group-item text-danger">Job Failed</li>
|
||||
}
|
||||
else
|
||||
{
|
||||
<li class="list-group-item text-success">Job Succeeded</li>
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
}
|
||||
|
||||
@code {
|
||||
|
||||
@ -19,9 +19,14 @@
|
||||
}
|
||||
else if (executingEntries.Count == 0)
|
||||
{
|
||||
<h4>Executing</h4>
|
||||
<h4>Executing (0)</h4>
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">No jobs currently executing</li>
|
||||
<li class="list-group-item">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-cup-hot" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M.5 6a.5.5 0 0 0-.488.608l1.652 7.434A2.5 2.5 0 0 0 4.104 16h5.792a2.5 2.5 0 0 0 2.44-1.958l.131-.59a3 3 0 0 0 1.3-5.854l.221-.99A.5.5 0 0 0 13.5 6H.5ZM13 12.5a2.01 2.01 0 0 1-.316-.025l.867-3.898A2.001 2.001 0 0 1 13 12.5ZM2.64 13.825 1.123 7h11.754l-1.517 6.825A1.5 1.5 0 0 1 9.896 15H4.104a1.5 1.5 0 0 1-1.464-1.175Z" />
|
||||
<path d="m4.4.8-.003.004-.014.019a4.167 4.167 0 0 0-.204.31 2.327 2.327 0 0 0-.141.267c-.026.06-.034.092-.037.103v.004a.593.593 0 0 0 .091.248c.075.133.178.272.308.445l.01.012c.118.158.26.347.37.543.112.2.22.455.22.745 0 .188-.065.368-.119.494a3.31 3.31 0 0 1-.202.388 5.444 5.444 0 0 1-.253.382l-.018.025-.005.008-.002.002A.5.5 0 0 1 3.6 4.2l.003-.004.014-.019a4.149 4.149 0 0 0 .204-.31 2.06 2.06 0 0 0 .141-.267c.026-.06.034-.092.037-.103a.593.593 0 0 0-.09-.252A4.334 4.334 0 0 0 3.6 2.8l-.01-.012a5.099 5.099 0 0 1-.37-.543A1.53 1.53 0 0 1 3 1.5c0-.188.065-.368.119-.494.059-.138.134-.274.202-.388a5.446 5.446 0 0 1 .253-.382l.025-.035A.5.5 0 0 1 4.4.8Zm3 0-.003.004-.014.019a4.167 4.167 0 0 0-.204.31 2.327 2.327 0 0 0-.141.267c-.026.06-.034.092-.037.103v.004a.593.593 0 0 0 .091.248c.075.133.178.272.308.445l.01.012c.118.158.26.347.37.543.112.2.22.455.22.745 0 .188-.065.368-.119.494a3.31 3.31 0 0 1-.202.388 5.444 5.444 0 0 1-.253.382l-.018.025-.005.008-.002.002A.5.5 0 0 1 6.6 4.2l.003-.004.014-.019a4.149 4.149 0 0 0 .204-.31 2.06 2.06 0 0 0 .141-.267c.026-.06.034-.092.037-.103a.593.593 0 0 0-.09-.252A4.334 4.334 0 0 0 6.6 2.8l-.01-.012a5.099 5.099 0 0 1-.37-.543A1.53 1.53 0 0 1 6 1.5c0-.188.065-.368.119-.494.059-.138.134-.274.202-.388a5.446 5.446 0 0 1 .253-.382l.025-.035A.5.5 0 0 1 7.4.8Zm3 0-.003.004-.014.019a4.077 4.077 0 0 0-.204.31 2.337 2.337 0 0 0-.141.267c-.026.06-.034.092-.037.103v.004a.593.593 0 0 0 .091.248c.075.133.178.272.308.445l.01.012c.118.158.26.347.37.543.112.2.22.455.22.745 0 .188-.065.368-.119.494a3.198 3.198 0 0 1-.202.388 5.385 5.385 0 0 1-.252.382l-.019.025-.005.008-.002.002A.5.5 0 0 1 9.6 4.2l.003-.004.014-.019a4.149 4.149 0 0 0 .204-.31 2.06 2.06 0 0 0 .141-.267c.026-.06.034-.092.037-.103a.593.593 0 0 0-.09-.252A4.334 4.334 0 0 0 9.6 2.8l-.01-.012a5.099 5.099 0 0 1-.37-.543A1.53 1.53 0 0 1 9 1.5c0-.188.065-.368.119-.494.059-.138.134-.274.202-.388a5.446 5.446 0 0 1 .253-.382l.025-.035A.5.5 0 0 1 10.4.8Z" />
|
||||
</svg> No jobs currently executing.
|
||||
</li>
|
||||
</ul>
|
||||
}
|
||||
else
|
||||
@ -62,10 +67,15 @@
|
||||
}
|
||||
else if (completedEntries.Count == 0)
|
||||
{
|
||||
<h4>Completed</h4>
|
||||
<h4>Completed (0)</h4>
|
||||
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">No jobs currently executing</li>
|
||||
<li class="list-group-item">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-cup-hot" viewBox="0 0 16 16">
|
||||
<path fill-rule="evenodd" d="M.5 6a.5.5 0 0 0-.488.608l1.652 7.434A2.5 2.5 0 0 0 4.104 16h5.792a2.5 2.5 0 0 0 2.44-1.958l.131-.59a3 3 0 0 0 1.3-5.854l.221-.99A.5.5 0 0 0 13.5 6H.5ZM13 12.5a2.01 2.01 0 0 1-.316-.025l.867-3.898A2.001 2.001 0 0 1 13 12.5ZM2.64 13.825 1.123 7h11.754l-1.517 6.825A1.5 1.5 0 0 1 9.896 15H4.104a1.5 1.5 0 0 1-1.464-1.175Z" />
|
||||
<path d="m4.4.8-.003.004-.014.019a4.167 4.167 0 0 0-.204.31 2.327 2.327 0 0 0-.141.267c-.026.06-.034.092-.037.103v.004a.593.593 0 0 0 .091.248c.075.133.178.272.308.445l.01.012c.118.158.26.347.37.543.112.2.22.455.22.745 0 .188-.065.368-.119.494a3.31 3.31 0 0 1-.202.388 5.444 5.444 0 0 1-.253.382l-.018.025-.005.008-.002.002A.5.5 0 0 1 3.6 4.2l.003-.004.014-.019a4.149 4.149 0 0 0 .204-.31 2.06 2.06 0 0 0 .141-.267c.026-.06.034-.092.037-.103a.593.593 0 0 0-.09-.252A4.334 4.334 0 0 0 3.6 2.8l-.01-.012a5.099 5.099 0 0 1-.37-.543A1.53 1.53 0 0 1 3 1.5c0-.188.065-.368.119-.494.059-.138.134-.274.202-.388a5.446 5.446 0 0 1 .253-.382l.025-.035A.5.5 0 0 1 4.4.8Zm3 0-.003.004-.014.019a4.167 4.167 0 0 0-.204.31 2.327 2.327 0 0 0-.141.267c-.026.06-.034.092-.037.103v.004a.593.593 0 0 0 .091.248c.075.133.178.272.308.445l.01.012c.118.158.26.347.37.543.112.2.22.455.22.745 0 .188-.065.368-.119.494a3.31 3.31 0 0 1-.202.388 5.444 5.444 0 0 1-.253.382l-.018.025-.005.008-.002.002A.5.5 0 0 1 6.6 4.2l.003-.004.014-.019a4.149 4.149 0 0 0 .204-.31 2.06 2.06 0 0 0 .141-.267c.026-.06.034-.092.037-.103a.593.593 0 0 0-.09-.252A4.334 4.334 0 0 0 6.6 2.8l-.01-.012a5.099 5.099 0 0 1-.37-.543A1.53 1.53 0 0 1 6 1.5c0-.188.065-.368.119-.494.059-.138.134-.274.202-.388a5.446 5.446 0 0 1 .253-.382l.025-.035A.5.5 0 0 1 7.4.8Zm3 0-.003.004-.014.019a4.077 4.077 0 0 0-.204.31 2.337 2.337 0 0 0-.141.267c-.026.06-.034.092-.037.103v.004a.593.593 0 0 0 .091.248c.075.133.178.272.308.445l.01.012c.118.158.26.347.37.543.112.2.22.455.22.745 0 .188-.065.368-.119.494a3.198 3.198 0 0 1-.202.388 5.385 5.385 0 0 1-.252.382l-.019.025-.005.008-.002.002A.5.5 0 0 1 9.6 4.2l.003-.004.014-.019a4.149 4.149 0 0 0 .204-.31 2.06 2.06 0 0 0 .141-.267c.026-.06.034-.092.037-.103a.593.593 0 0 0-.09-.252A4.334 4.334 0 0 0 9.6 2.8l-.01-.012a5.099 5.099 0 0 1-.37-.543A1.53 1.53 0 0 1 9 1.5c0-.188.065-.368.119-.494.059-.138.134-.274.202-.388a5.446 5.446 0 0 1 .253-.382l.025-.035A.5.5 0 0 1 10.4.8Z" />
|
||||
</svg> No completed jobs yet.
|
||||
</li>
|
||||
</ul>
|
||||
}
|
||||
else
|
||||
@ -126,7 +136,7 @@ else
|
||||
|
||||
completedEntries = response.jobStatus.
|
||||
Where(s => !s.Executing).
|
||||
Where(s => s.StartTime.AddMinutes(1) > DateTime.Now).
|
||||
Where(s => s.StartTime.AddMinutes(10) > DateTime.Now).
|
||||
ToList();
|
||||
|
||||
InvokeAsync(StateHasChanged);
|
||||
|
||||
@ -10,14 +10,14 @@
|
||||
<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
|
||||
<nav class="flex-column">
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
|
||||
<NavLink class="nav-link px-3" href="" Match="NavLinkMatch.All">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-house" viewBox="0 0 16 16">
|
||||
<path d="M8.707 1.5a1 1 0 0 0-1.414 0L.646 8.146a.5.5 0 0 0 .708.708L2 8.207V13.5A1.5 1.5 0 0 0 3.5 15h9a1.5 1.5 0 0 0 1.5-1.5V8.207l.646.647a.5.5 0 0 0 .708-.708L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.707 1.5ZM13 7.207V13.5a.5.5 0 0 1-.5.5h-9a.5.5 0 0 1-.5-.5V7.207l5-5 5 5Z" />
|
||||
</svg> Start
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="profiles">
|
||||
<NavLink class="nav-link px-3" href="profiles">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-rocket" viewBox="0 0 16 16">
|
||||
<path d="M8 8c.828 0 1.5-.895 1.5-2S8.828 4 8 4s-1.5.895-1.5 2S7.172 8 8 8Z" />
|
||||
<path d="M11.953 8.81c-.195-3.388-.968-5.507-1.777-6.819C9.707 1.233 9.23.751 8.857.454a3.495 3.495 0 0 0-.463-.315A2.19 2.19 0 0 0 8.25.064.546.546 0 0 0 8 0a.549.549 0 0 0-.266.073 2.312 2.312 0 0 0-.142.08 3.67 3.67 0 0 0-.459.33c-.37.308-.844.803-1.31 1.57-.805 1.322-1.577 3.433-1.774 6.756l-1.497 1.826-.004.005A2.5 2.5 0 0 0 2 12.202V15.5a.5.5 0 0 0 .9.3l1.125-1.5c.166-.222.42-.4.752-.57.214-.108.414-.192.625-.281l.198-.084c.7.428 1.55.635 2.4.635.85 0 1.7-.207 2.4-.635.067.03.132.056.196.083.213.09.413.174.627.282.332.17.586.348.752.57l1.125 1.5a.5.5 0 0 0 .9-.3v-3.298a2.5 2.5 0 0 0-.548-1.562l-1.499-1.83ZM12 10.445v.055c0 .866-.284 1.585-.75 2.14.146.064.292.13.425.199.39.197.8.46 1.1.86L13 14v-1.798a1.5 1.5 0 0 0-.327-.935L12 10.445ZM4.75 12.64C4.284 12.085 4 11.366 4 10.5v-.054l-.673.82a1.5 1.5 0 0 0-.327.936V14l.225-.3c.3-.4.71-.664 1.1-.861.133-.068.279-.135.425-.199ZM8.009 1.073c.063.04.14.094.226.163.284.226.683.621 1.09 1.28C10.137 3.836 11 6.237 11 10.5c0 .858-.374 1.48-.943 1.893C9.517 12.786 8.781 13 8 13c-.781 0-1.517-.214-2.057-.607C5.373 11.979 5 11.358 5 10.5c0-4.182.86-6.586 1.677-7.928.409-.67.81-1.082 1.096-1.32.09-.076.17-.135.236-.18Z" />
|
||||
@ -26,7 +26,7 @@
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="status">
|
||||
<NavLink class="nav-link px-3" href="status">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-speedometer" viewBox="0 0 16 16">
|
||||
<path d="M8 2a.5.5 0 0 1 .5.5V4a.5.5 0 0 1-1 0V2.5A.5.5 0 0 1 8 2zM3.732 3.732a.5.5 0 0 1 .707 0l.915.914a.5.5 0 1 1-.708.708l-.914-.915a.5.5 0 0 1 0-.707zM2 8a.5.5 0 0 1 .5-.5h1.586a.5.5 0 0 1 0 1H2.5A.5.5 0 0 1 2 8zm9.5 0a.5.5 0 0 1 .5-.5h1.5a.5.5 0 0 1 0 1H12a.5.5 0 0 1-.5-.5zm.754-4.246a.389.389 0 0 0-.527-.02L7.547 7.31A.91.91 0 1 0 8.85 8.569l3.434-4.297a.389.389 0 0 0-.029-.518z" />
|
||||
<path fill-rule="evenodd" d="M6.664 15.889A8 8 0 1 1 9.336.11a8 8 0 0 1-2.672 15.78zm-4.665-4.283A11.945 11.945 0 0 1 8 10c2.186 0 4.236.585 6.001 1.606a7 7 0 1 0-12.002 0z" />
|
||||
@ -34,7 +34,7 @@
|
||||
</NavLink>
|
||||
</div>
|
||||
<div class="nav-item px-3">
|
||||
<NavLink class="nav-link" href="history">
|
||||
<NavLink class="nav-link px-3" href="history">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clock-history" viewBox="0 0 16 16">
|
||||
<path d="M8.515 1.019A7 7 0 0 0 8 1V0a8 8 0 0 1 .589.022l-.074.997zm2.004.45a7.003 7.003 0 0 0-.985-.299l.219-.976c.383.086.76.2 1.126.342l-.36.933zm1.37.71a7.01 7.01 0 0 0-.439-.27l.493-.87a8.025 8.025 0 0 1 .979.654l-.615.789a6.996 6.996 0 0 0-.418-.302zm1.834 1.79a6.99 6.99 0 0 0-.653-.796l.724-.69c.27.285.52.59.747.91l-.818.576zm.744 1.352a7.08 7.08 0 0 0-.214-.468l.893-.45a7.976 7.976 0 0 1 .45 1.088l-.95.313a7.023 7.023 0 0 0-.179-.483zm.53 2.507a6.991 6.991 0 0 0-.1-1.025l.985-.17c.067.386.106.778.116 1.17l-1 .025zm-.131 1.538c.033-.17.06-.339.081-.51l.993.123a7.957 7.957 0 0 1-.23 1.155l-.964-.267c.046-.165.086-.332.12-.501zm-.952 2.379c.184-.29.346-.594.486-.908l.914.405c-.16.36-.345.706-.555 1.038l-.845-.535zm-.964 1.205c.122-.122.239-.248.35-.378l.758.653a8.073 8.073 0 0 1-.401.432l-.707-.707z" />
|
||||
<path d="M8 1a7 7 0 1 0 4.95 11.95l.707.707A8.001 8.001 0 1 1 8 0v1z" />
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
7
ECM.JobRunner.Web/wwwroot/js/bootstrap.min.js
vendored
Normal file
7
ECM.JobRunner.Web/wwwroot/js/bootstrap.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
ECM.JobRunner.Web/wwwroot/js/bootstrap.min.js.map
Normal file
1
ECM.JobRunner.Web/wwwroot/js/bootstrap.min.js.map
Normal file
File diff suppressed because one or more lines are too long
@ -7,6 +7,7 @@
|
||||
Public Const JOB_CONFIG_ARGUMENTS = "__Arguments"
|
||||
Public Const JOB_CONFIG_DATABASE = "__Database"
|
||||
Public Const JOB_CONFIG_STATE = "__State"
|
||||
Public Const JOB_CONFIG_WINDREAM = "__Windream"
|
||||
End Class
|
||||
|
||||
Public Class Jobs
|
||||
|
||||
@ -57,6 +57,10 @@
|
||||
<Reference Include="DigitalData.Modules.Database">
|
||||
<HintPath>..\..\DDModules\Database\bin\Debug\DigitalData.Modules.Database.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DigitalData.Modules.Filesystem, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\DDModules\Filesystem\bin\Debug\DigitalData.Modules.Filesystem.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DigitalData.Modules.Language, Version=1.7.0.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\DDModules\Language\bin\Debug\DigitalData.Modules.Language.dll</HintPath>
|
||||
@ -123,6 +127,7 @@
|
||||
<Compile Include="Models\Jobs\HistoryItem.vb" />
|
||||
<Compile Include="Models\Jobs\StatusItem.vb" />
|
||||
<Compile Include="Models\Profiles\BaseProfile.vb" />
|
||||
<Compile Include="Models\Profiles\ImportFile.vb" />
|
||||
<Compile Include="Models\Profiles\ImportProfile.vb" />
|
||||
<Compile Include="Models\Profiles\ImportProfileStep.vb" />
|
||||
<Compile Include="Models\Windream\ObjectType.vb" />
|
||||
@ -168,6 +173,7 @@
|
||||
<Compile Include="WCF\JobRunner.vb" />
|
||||
<Compile Include="WCF\Methods\Base.vb" />
|
||||
<Compile Include="WCF\Methods\GetJobConfig.vb" />
|
||||
<Compile Include="WCF\Methods\RunJob.vb" />
|
||||
<Compile Include="WCF\Methods\UpdateJob.vb" />
|
||||
<Compile Include="WCF\Methods\UpdateProfile.vb" />
|
||||
<Compile Include="WCF\Methods\GetJobStatus.vb" />
|
||||
|
||||
@ -4,4 +4,19 @@
|
||||
Public Property Successful As Boolean
|
||||
Public Property ErrorMessage As String
|
||||
Public Property Message As String
|
||||
Public Property Steps As List(Of HistoryStep)
|
||||
|
||||
Public Class HistoryStep
|
||||
Public Property Created As Date = Now
|
||||
Public Property Message As String
|
||||
Public Property Level As StepLevel
|
||||
End Class
|
||||
|
||||
Public Enum StepLevel
|
||||
Debug
|
||||
Info
|
||||
Warning
|
||||
[Error]
|
||||
End Enum
|
||||
|
||||
End Class
|
||||
|
||||
19
ECM.JobRunner.Windows/Models/Profiles/ImportFile.vb
Normal file
19
ECM.JobRunner.Windows/Models/Profiles/ImportFile.vb
Normal file
@ -0,0 +1,19 @@
|
||||
Public Class ImportFile
|
||||
Public Property FilePath As String
|
||||
Public Property FilePathOriginal As String
|
||||
Public Property FilePathWindream As String
|
||||
Public Property FileInfo As IO.FileInfo
|
||||
|
||||
Public Property IndexValues As New List(Of IndexItem)
|
||||
|
||||
Public Class IndexItem
|
||||
Public Value As String
|
||||
Public IndexName As String
|
||||
End Class
|
||||
|
||||
Public Sub New(pFilePath As String)
|
||||
_FilePathOriginal = pFilePath
|
||||
_FilePath = pFilePath
|
||||
_FileInfo = New IO.FileInfo(pFilePath)
|
||||
End Sub
|
||||
End Class
|
||||
@ -12,23 +12,25 @@ Namespace Scheduler
|
||||
MyBase.New(pLogConfig)
|
||||
End Sub
|
||||
|
||||
Public Sub AddSuccess(pName As String, pMessage As String)
|
||||
Public Sub AddSuccess(pName As String, pMessage As String, pSteps As List(Of HistoryItem.HistoryStep))
|
||||
Entries.Add(New HistoryItem With {
|
||||
.CreatedAt = Now,
|
||||
.JobName = pName,
|
||||
.Successful = True,
|
||||
.ErrorMessage = Nothing,
|
||||
.Message = pMessage
|
||||
.Message = pMessage,
|
||||
.Steps = pSteps
|
||||
})
|
||||
End Sub
|
||||
|
||||
Public Sub AddError(pName As String, ErrorMessage As String)
|
||||
Public Sub AddError(pName As String, ErrorMessage As String, pSteps As List(Of HistoryItem.HistoryStep))
|
||||
Entries.Add(New HistoryItem With {
|
||||
.CreatedAt = Now,
|
||||
.JobName = pName,
|
||||
.Successful = False,
|
||||
.ErrorMessage = ErrorMessage,
|
||||
.Message = ""
|
||||
.Message = "",
|
||||
.Steps = pSteps
|
||||
})
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
@ -25,13 +25,13 @@ Namespace Scheduler
|
||||
If jobException Is Nothing Then
|
||||
If TypeOf context.Result Is JobResult Then
|
||||
Dim oResult As JobResult = context.Result
|
||||
History.AddSuccess(context.JobDetail.Key.Name, oResult.Description)
|
||||
History.AddSuccess(context.JobDetail.Key.Name, oResult.Description, oResult.Steps)
|
||||
Else
|
||||
|
||||
History.AddSuccess(context.JobDetail.Key.Name, "Job Successful!")
|
||||
History.AddSuccess(context.JobDetail.Key.Name, "Job Successful!", New List(Of HistoryItem.HistoryStep))
|
||||
End If
|
||||
Else
|
||||
History.AddError(context.JobDetail.Key.Name, jobException.Message)
|
||||
History.AddError(context.JobDetail.Key.Name, jobException.Message, New List(Of HistoryItem.HistoryStep))
|
||||
End If
|
||||
|
||||
Return MyBase.JobWasExecuted(context, jobException, cancellationToken)
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
Public Class JobResult
|
||||
Public Property Successful As Boolean
|
||||
Public Property Description As String
|
||||
Public Property Steps As List(Of HistoryItem.HistoryStep)
|
||||
End Class
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
Imports System.Collections.Specialized
|
||||
Imports DigitalData.Modules.Database
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports DigitalData.Modules.Windream
|
||||
Imports ECM.JobRunner.Common
|
||||
Imports Quartz
|
||||
Imports Quartz.Logging.OperationName
|
||||
|
||||
Namespace Scheduler
|
||||
Public Class JobScheduler
|
||||
@ -16,20 +18,32 @@ Namespace Scheduler
|
||||
Private ReadOnly Database As MSSQLServer
|
||||
Private ReadOnly Factory As Quartz.Impl.StdSchedulerFactory
|
||||
Private ReadOnly State As State
|
||||
Private ReadOnly Windream As Windream
|
||||
|
||||
Private Scheduler As IScheduler
|
||||
|
||||
Private Const JOB_TYPE_IMPORT As Integer = 1
|
||||
Private Const JOB_TYPE_INDEX As Integer = 2
|
||||
|
||||
Public Sub New(pLogConfig As LogConfig, pDatabase As MSSQLServer, pState As State)
|
||||
Public Sub New(pLogConfig As LogConfig, pDatabase As MSSQLServer, pState As State, pWindream As Windream)
|
||||
LogConfig = pLogConfig
|
||||
Logger = pLogConfig.GetLogger()
|
||||
Factory = New Impl.StdSchedulerFactory(Settings)
|
||||
Database = pDatabase
|
||||
Windream = pWindream
|
||||
State = pState
|
||||
End Sub
|
||||
|
||||
Private Function BuildJobData(pJobConfig As JobConfig) As JobDataMap
|
||||
Return New JobDataMap From {
|
||||
{Constants.Scheduler.JOB_CONFIG_LOGCONFIG, LogConfig},
|
||||
{Constants.Scheduler.JOB_CONFIG_ARGUMENTS, pJobConfig.Arguments},
|
||||
{Constants.Scheduler.JOB_CONFIG_DATABASE, Database},
|
||||
{Constants.Scheduler.JOB_CONFIG_STATE, State},
|
||||
{Constants.Scheduler.JOB_CONFIG_WINDREAM, Windream}
|
||||
}
|
||||
End Function
|
||||
|
||||
Public Async Function Start() As Task(Of Boolean)
|
||||
Try
|
||||
' Log all quartz events into our standard log files
|
||||
@ -69,26 +83,39 @@ Namespace Scheduler
|
||||
Return Await Scheduler.GetCurrentlyExecutingJobs()
|
||||
End Function
|
||||
|
||||
Public Async Function ScheduleJob(pJobId As Integer) As Task
|
||||
Dim oJob = State.JobDefinitions.Where(Function(j) j.Id = pJobId).SingleOrDefault()
|
||||
|
||||
If oJob IsNot Nothing Then
|
||||
Logger.Info("Scheduling Job [{0}] manually!", oJob.Name)
|
||||
Await PrepareScheduleJob(oJob)
|
||||
End If
|
||||
End Function
|
||||
|
||||
Private Async Function PrepareScheduleJob(pJob As JobDefinition) As Task
|
||||
Logger.Debug("Loading Job Definition [{0}]", pJob.Name)
|
||||
Logger.Debug("Job Type is [{0}]", pJob.Type.Name)
|
||||
|
||||
Select Case pJob.TypeId
|
||||
Case JOB_TYPE_IMPORT
|
||||
Dim oJobConfig = BuildJobConfig(Of Jobs.FileImportJob)(pJob)
|
||||
Await ScheduleJob(Of Jobs.FileImportJob)(oJobConfig)
|
||||
|
||||
Case JOB_TYPE_INDEX
|
||||
Dim oJobConfig = BuildJobConfig(Of Jobs.FileIndexJob)(pJob)
|
||||
Await ScheduleJob(Of Jobs.FileIndexJob)(oJobConfig)
|
||||
|
||||
Case Else
|
||||
Logger.Warn("Job for TypeId [{0}] is not implemented!", pJob.TypeId)
|
||||
End Select
|
||||
End Function
|
||||
|
||||
Private Async Sub ScheduleJobs()
|
||||
|
||||
Logger.Info("Loading [{0}] Job Definitions..", State.JobDefinitions.Count)
|
||||
|
||||
For Each oJob In State.JobDefinitions
|
||||
Logger.Debug("Loading Job Definition [{0}]", oJob.Name)
|
||||
Logger.Debug("Job Type is [{0}]", oJob.Type.Name)
|
||||
|
||||
Select Case oJob.TypeId
|
||||
Case JOB_TYPE_IMPORT
|
||||
Dim oJobConfig = BuildJobConfig(Of Jobs.FileImportJob)(oJob)
|
||||
Await ScheduleJob(Of Jobs.FileImportJob)(oJobConfig)
|
||||
|
||||
Case JOB_TYPE_INDEX
|
||||
Dim oJobConfig = BuildJobConfig(Of Jobs.FileIndexJob)(oJob)
|
||||
Await ScheduleJob(Of Jobs.FileIndexJob)(oJobConfig)
|
||||
|
||||
Case Else
|
||||
Logger.Warn("Job for TypeId [{0}] is not implemented!", oJob.TypeId)
|
||||
End Select
|
||||
Await PrepareScheduleJob(oJob)
|
||||
Next
|
||||
End Sub
|
||||
|
||||
@ -155,15 +182,6 @@ Namespace Scheduler
|
||||
End If
|
||||
End Function
|
||||
|
||||
Private Function BuildJobData(pJobConfig As JobConfig) As JobDataMap
|
||||
Return New JobDataMap From {
|
||||
{Constants.Scheduler.JOB_CONFIG_LOGCONFIG, LogConfig},
|
||||
{Constants.Scheduler.JOB_CONFIG_ARGUMENTS, pJobConfig.Arguments},
|
||||
{Constants.Scheduler.JOB_CONFIG_DATABASE, Database},
|
||||
{Constants.Scheduler.JOB_CONFIG_STATE, State}
|
||||
}
|
||||
End Function
|
||||
|
||||
Private Function BuildJob(Of T As IJob)(pJobConfig As JobConfig, pJobData As JobDataMap) As IJobDetail
|
||||
Dim oJobName = GetJobName(pJobConfig)
|
||||
Return JobBuilder.Create(Of T)().
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
Imports DigitalData.Modules.Database
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports DigitalData.Modules.Windream
|
||||
Imports ECM.JobRunner.Common
|
||||
Imports Quartz
|
||||
|
||||
@ -8,11 +9,14 @@ Namespace Scheduler.Jobs
|
||||
Friend LogConfig As LogConfig
|
||||
Friend Logger As Logger
|
||||
Friend Database As MSSQLServer
|
||||
Friend Windream As Windream
|
||||
Friend State As State
|
||||
|
||||
Friend Id As Integer
|
||||
Friend Name As String
|
||||
|
||||
Friend ResultItems As New List(Of HistoryItem.HistoryStep)
|
||||
|
||||
Private ctx As IJobExecutionContext
|
||||
|
||||
Public Function InitializeJob(context As IJobExecutionContext) As Dictionary(Of String, String)
|
||||
@ -23,6 +27,7 @@ Namespace Scheduler.Jobs
|
||||
LogConfig = oJobData.Item(Constants.Scheduler.JOB_CONFIG_LOGCONFIG)
|
||||
Database = oJobData.Item(Constants.Scheduler.JOB_CONFIG_DATABASE)
|
||||
State = oJobData.Item(Constants.Scheduler.JOB_CONFIG_STATE)
|
||||
Windream = oJobData.Item(Constants.Scheduler.JOB_CONFIG_WINDREAM)
|
||||
Logger = LogConfig.GetLogger()
|
||||
|
||||
Id = Integer.Parse(oArgs.Item("Id"))
|
||||
@ -36,9 +41,45 @@ Namespace Scheduler.Jobs
|
||||
State.JobStatus.Update(ctx, pCurrentValue, pTotalValue)
|
||||
End Sub
|
||||
|
||||
Public Sub CompleteJob()
|
||||
State.JobStatus.Complete(ctx)
|
||||
Public Sub LogStep(pLevel As HistoryItem.StepLevel, pMessage As String, ParamArray pArgs As String())
|
||||
ResultItems.Add(New HistoryItem.HistoryStep With {
|
||||
.Message = String.Format(pMessage, pArgs),
|
||||
.Level = pLevel
|
||||
})
|
||||
End Sub
|
||||
|
||||
Public Function CompleteJob() As Task(Of Boolean)
|
||||
ctx.Result = New JobResult With {
|
||||
.Successful = True,
|
||||
.Steps = ResultItems,
|
||||
.Description = "Job completed."
|
||||
}
|
||||
State.JobStatus.Complete(ctx)
|
||||
|
||||
Return Task.FromResult(True)
|
||||
End Function
|
||||
|
||||
Public Function CompleteJob(pCompletionMessage As String) As Task(Of Boolean)
|
||||
ctx.Result = New JobResult With {
|
||||
.Successful = True,
|
||||
.Steps = ResultItems,
|
||||
.Description = pCompletionMessage
|
||||
}
|
||||
State.JobStatus.Complete(ctx)
|
||||
|
||||
Return Task.FromResult(True)
|
||||
End Function
|
||||
|
||||
Public Function CompleteJob(pException As Exception) As Task(Of Boolean)
|
||||
ctx.Result = New JobResult With {
|
||||
.Successful = False,
|
||||
.Steps = ResultItems,
|
||||
.Description = pException.Message
|
||||
}
|
||||
State.JobStatus.Complete(ctx)
|
||||
|
||||
Return Task.FromResult(False)
|
||||
End Function
|
||||
End Class
|
||||
|
||||
End Namespace
|
||||
@ -18,7 +18,7 @@ Namespace Scheduler.Jobs
|
||||
|
||||
context.Result = oResult
|
||||
|
||||
CompleteJob()
|
||||
CompleteJob("Done!")
|
||||
Return Task.FromResult(True)
|
||||
End Function
|
||||
End Class
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
Imports ECM.JobRunner.Windows.Scheduler.Jobs
|
||||
Imports Quartz
|
||||
|
||||
|
||||
Imports System.Text.RegularExpressions
|
||||
Imports DigitalData.Modules.Filesystem
|
||||
|
||||
Namespace Scheduler.Jobs
|
||||
|
||||
@ -50,47 +50,271 @@ Namespace Scheduler.Jobs
|
||||
Inherits BaseJob
|
||||
Implements IJob
|
||||
|
||||
Private FileEx As File
|
||||
|
||||
Public Function Execute(context As IJobExecutionContext) As Task Implements IJob.Execute
|
||||
Dim oArgs = MyBase.InitializeJob(context)
|
||||
|
||||
Try
|
||||
Logger.Info("Running File Import [{0}]", Name)
|
||||
FileEx = New File(LogConfig)
|
||||
|
||||
Dim oProfile = State.ProfileDefintions.ImportProfiles.Where(Function(p) p.JobId = Id).SingleOrDefault()
|
||||
|
||||
Dim oSourceDirectory As String = oProfile.SourceFolder
|
||||
Dim oRecursive As Boolean = oProfile.IncludeSubfolders
|
||||
Dim oFiles = GetFiles(oSourceDirectory, oRecursive)
|
||||
Logger.Info("Running File Import [{0}]", Name)
|
||||
Logger.Info("Source directory: [{0}]", oProfile.SourceFolder)
|
||||
Logger.Info("Target directory: [{0}]", oProfile.TargetFolder)
|
||||
Logger.Info("Backup directory: [{0}]", oProfile.BackupFolder)
|
||||
|
||||
If oFiles.Count = 0 Then
|
||||
Logger.Info("No Files for Profile [{0}]", Name)
|
||||
Return Task.FromResult(True)
|
||||
Dim oObjectType = State.ObjectTypes.Where(Function(o) o.Name = oProfile.ObjectTypeName).SingleOrDefault()
|
||||
|
||||
If IO.Directory.Exists(oProfile.SourceFolder) = False Then
|
||||
LogStep(HistoryItem.StepLevel.Error, "Source directory [{0}] does not exist!", oProfile.SourceFolder)
|
||||
Return Task.FromResult(False)
|
||||
End If
|
||||
|
||||
Logger.Info("[0] files found in source directory [{1}]", oFiles.Count, oSourceDirectory)
|
||||
Dim oRecursive As Boolean = oProfile.IncludeSubfolders
|
||||
Dim oFileNames = GetFiles(oProfile.SourceFolder, oRecursive)
|
||||
Dim oRegexList As List(Of Regex) = GetRegexList(oProfile.FileExcludeRegex)
|
||||
|
||||
'Dim oMax = 100
|
||||
'For index = 1 To oMax
|
||||
' UpdateProgress(index, oMax)
|
||||
' Threading.Thread.Sleep(100)
|
||||
'Next
|
||||
Logger.Debug("[{0}] Regexes loaded", oRegexList.Count)
|
||||
|
||||
Dim oResult = New JobResult() With {
|
||||
.Description = $"File Import Job [{Name}] completed!"
|
||||
}
|
||||
If oFileNames.Count = 0 Then
|
||||
Logger.Info("No Files for Profile [{0}]", Name)
|
||||
Return CompleteJob("No files for profile")
|
||||
End If
|
||||
|
||||
context.Result = oResult
|
||||
Logger.Info("[{0}] files found in source directory [{1}]", oFileNames.Count, oProfile.SourceFolder)
|
||||
LogStep(HistoryItem.StepLevel.Info, "{0} files found in source directory {1}", oFileNames.Count, oProfile.SourceFolder)
|
||||
|
||||
Return Task.FromResult(True)
|
||||
' - [ ] Process Rules, build list of files and indexes
|
||||
' - [x] Process Regex to filter out files
|
||||
' - [x] Check time to filter out files
|
||||
' - [ ] (Check if files can be accessed)
|
||||
' - [ ] Check if backup is needed and backup files
|
||||
' - [ ] Import into windream
|
||||
' - [ ] Create original subfolder structure
|
||||
' - [ ] Create DateTime Subfolders
|
||||
' - [x] Check if file exists and version
|
||||
' - [x] Do import
|
||||
' - [ ] Check for filesize 0
|
||||
' - [ ] Write indexes (using data from getimportfile)
|
||||
' - [ ] Check if orig file should be deleted
|
||||
' - [ ] (delete subdirectories in source path)
|
||||
|
||||
Dim oFiles = oFileNames.
|
||||
Select(Function(f) New ImportFile(f)).
|
||||
ToList()
|
||||
Dim oFilteredFiles = oFiles
|
||||
|
||||
' Check time to filter out files
|
||||
Dim oDateFilteredFiles = oFilteredFiles.Where(Function(f) FileIsOlderThan(f, pMinutes:=1)).ToList()
|
||||
Dim oDateFilteredCount = oFilteredFiles.Except(oDateFilteredFiles).Count()
|
||||
Logger.Debug("[{0}] Files filtered out for being too new.", oDateFilteredCount)
|
||||
LogStep(HistoryItem.StepLevel.Debug, "{0} Files filtered out for being too new.", oDateFilteredCount)
|
||||
oFilteredFiles = oDateFilteredFiles
|
||||
|
||||
' Process Regex to filter out files
|
||||
Dim oRegexFilteredFiles = oFilteredFiles.Where(Function(f) Not FileMatchesRegex(f, oRegexList))
|
||||
Dim oRegexFilteredCount = oFilteredFiles.Except(oRegexFilteredFiles).Count()
|
||||
Logger.Debug("[{0}] Files filtered out for matching exclusion Regex.", oRegexFilteredCount)
|
||||
LogStep(HistoryItem.StepLevel.Debug, "{0} Files filtered out for matching exclusion Regex.", oRegexFilteredCount)
|
||||
oFilteredFiles = oDateFilteredFiles
|
||||
|
||||
Logger.Info("Importing files..")
|
||||
Dim oImportedFiles As New List(Of ImportFile)
|
||||
For Each oFile In oFilteredFiles
|
||||
|
||||
Dim oImportedPath = ImportFile(oFile, oProfile)
|
||||
If oImportedPath Is Nothing Then
|
||||
Logger.Warn("File [{0}] could not be imported!", oFile.FilePath)
|
||||
Continue For
|
||||
End If
|
||||
oFile.FilePathWindream = oImportedPath
|
||||
|
||||
oImportedFiles.Add(oFile)
|
||||
Next
|
||||
|
||||
Logger.Info("[{0}] files successfully Imported!", oImportedFiles.Count)
|
||||
LogStep(HistoryItem.StepLevel.Info, "{0} files successfully Imported!", oImportedFiles.Count)
|
||||
|
||||
Dim oIndexedFiles As New List(Of ImportFile)
|
||||
For Each oFile In oImportedFiles
|
||||
Logger.Info("Indexing file [{0}]", oFile.FilePathWindream)
|
||||
Dim oIndexResult = IndexFile(oFile, oProfile)
|
||||
If oIndexResult = True Then
|
||||
oIndexedFiles.Add(oFile)
|
||||
End If
|
||||
Logger.Info("Indexing of file [{0}] done!", oFile.FilePathWindream)
|
||||
Next
|
||||
|
||||
Logger.Info("[{0}] files successfully Indexed!", oIndexedFiles.Count)
|
||||
LogStep(HistoryItem.StepLevel.Info, "{0} files successfully Indexed!", oIndexedFiles.Count)
|
||||
|
||||
Return CompleteJob($"{oImportedFiles.Count} files successfully Processed!")
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex)
|
||||
|
||||
LogStep(HistoryItem.StepLevel.Error, "Unexpected Error: [{0}]", ex.Message)
|
||||
|
||||
Return Task.FromResult(False)
|
||||
Finally
|
||||
CompleteJob()
|
||||
Return CompleteJob(ex)
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Private Function FileIsOlderThan(pFile As ImportFile, pMinutes As Integer)
|
||||
Return pFile.FileInfo.CreationTime.AddMinutes(pMinutes) < Now
|
||||
End Function
|
||||
|
||||
Private Function FileMatchesRegex(pFile As ImportFile, pRegexList As List(Of Regex))
|
||||
Return pRegexList.Any(Function(r) r.IsMatch(pFile.FilePath))
|
||||
End Function
|
||||
|
||||
Private Function GetRegexList(pRegexString As String) As List(Of Regex)
|
||||
Return pRegexString.
|
||||
Split(vbNewLine).
|
||||
ToList().
|
||||
Where(Function(r) String.IsNullOrWhiteSpace(r) = False).
|
||||
Select(Function(s)
|
||||
Logger.Debug("Regex loaded: [{0}]", s)
|
||||
Return New Regex(s)
|
||||
End Function).ToList()
|
||||
|
||||
End Function
|
||||
|
||||
Private Function ImportFile(pFile As ImportFile, pProfile As ImportProfile) As String
|
||||
'Check if target folder exists
|
||||
If Windream.TestFolderExists(pProfile.TargetFolder) = False Then
|
||||
If Windream.NewFolder(pProfile.TargetFolder) = False Then
|
||||
Logger.Warn("Folder [{0}] could not be created!", pProfile.TargetFolder)
|
||||
Return Nothing
|
||||
End If
|
||||
End If
|
||||
|
||||
' Generate new filepath and stream file
|
||||
Dim oFileName = IO.Path.GetFileName(pFile.FilePath)
|
||||
Dim oNewFilePath As String = IO.Path.Combine(pProfile.TargetFolder, oFileName)
|
||||
Dim oVersionedFilePath = GetVersionedWindreamPath(oNewFilePath)
|
||||
|
||||
If Windream.NewFileStream(pFile.FilePathOriginal, oVersionedFilePath, pProfile.ObjectTypeName) = False Then
|
||||
Logger.Warn("File [{0}] could not be streamed to path [{1}]!", pFile.FilePathOriginal, oNewFilePath)
|
||||
Return Nothing
|
||||
End If
|
||||
|
||||
Return oVersionedFilePath
|
||||
End Function
|
||||
|
||||
Private Function GetVersionedWindreamPath(pWindreamFilePath As String) As String
|
||||
Dim oAbsolutePath = Windream.GetAbsolutePath(pWindreamFilePath)
|
||||
|
||||
' This versions the filename but does not rely on access though the filesystem.
|
||||
' Instead the check for file existence is made through the windream sdk.
|
||||
Dim oVersionedPath = FileEx.GetVersionedFilenameWithFilecheck(oAbsolutePath, Function(pPath As String) Windream.TestFileExists(pPath))
|
||||
Dim oVersionedAndNormalizedPath = Windream.GetNormalizedPath(oVersionedPath, False)
|
||||
|
||||
Return oVersionedAndNormalizedPath
|
||||
End Function
|
||||
|
||||
Private Function GetImportFile(pFilename As String, pProfile As ImportProfile) As ImportFile
|
||||
Dim oImportFile = New ImportFile(pFilename)
|
||||
|
||||
Return oImportFile
|
||||
End Function
|
||||
|
||||
Private Function ProcessSteps(pFile As ImportFile, pProfile As ImportProfile) As List(Of ImportFile.IndexItem)
|
||||
Dim oIndexItems = New List(Of ImportFile.IndexItem)
|
||||
|
||||
' Process Steps on Filename
|
||||
For Each oStep In pProfile.Steps
|
||||
Dim oValue As String
|
||||
|
||||
' Get the base value by checking scope
|
||||
Select Case oStep.Scope
|
||||
Case ImportProfileStep.StepScope.FILE
|
||||
oValue = pFile.FileInfo.Name
|
||||
Case ImportProfileStep.StepScope.FOLDER
|
||||
oValue = pFile.FileInfo.DirectoryName
|
||||
Case Else
|
||||
oValue = pFile.FilePath
|
||||
End Select
|
||||
|
||||
|
||||
' TODO: Error handling!
|
||||
Select Case oStep.Method
|
||||
Case ImportProfileStep.StepMethod.SUBSTRING
|
||||
Try
|
||||
Dim oIndex1 = Integer.Parse(oStep.Argument1)
|
||||
Dim oLength = Integer.Parse(oStep.Argument2)
|
||||
oValue = oValue.Substring(oIndex1, oLength)
|
||||
Catch ex As Exception
|
||||
LogStep(HistoryItem.StepLevel.Error, "Method SUBSTRING could not be applied to Index '{0}'. Error: '{1}'", oStep.IndexName, ex.Message)
|
||||
Logger.Error(ex)
|
||||
End Try
|
||||
|
||||
Case ImportProfileStep.StepMethod.SPLIT
|
||||
Try
|
||||
Dim oSeparator = oStep.Argument1.Substring(0, 1)
|
||||
Dim oIndex = Integer.Parse(oStep.Argument2)
|
||||
Dim oSplit = oValue.Split(oSeparator)
|
||||
oValue = oSplit(oIndex)
|
||||
Catch ex As Exception
|
||||
LogStep(HistoryItem.StepLevel.Error, "Method SPLIT could not be applied to Index '{0}'. Error: '{1}'", oStep.IndexName, ex.Message)
|
||||
Logger.Error(ex)
|
||||
End Try
|
||||
|
||||
Case ImportProfileStep.StepMethod.REGEX
|
||||
Try
|
||||
Dim oRegex = New Regex(oStep.Argument1)
|
||||
Dim oTrueValue = oStep.Argument2
|
||||
Dim oFalseValue = oStep.Argument3
|
||||
If oRegex.IsMatch(oValue) Then
|
||||
oValue = oTrueValue
|
||||
Else
|
||||
oValue = oFalseValue
|
||||
End If
|
||||
Catch ex As Exception
|
||||
LogStep(HistoryItem.StepLevel.Error, "Method REGEX could not be applied to Index '{0}'. Error: '{1}'", oStep.IndexName, ex.Message)
|
||||
Logger.Error(ex)
|
||||
End Try
|
||||
|
||||
Case ImportProfileStep.StepMethod.VALUE
|
||||
oValue = oStep.Argument1
|
||||
|
||||
Case ImportProfileStep.StepMethod.ALL
|
||||
'noop
|
||||
Case Else
|
||||
'noop
|
||||
End Select
|
||||
|
||||
oIndexItems.Add(New ImportFile.IndexItem With {
|
||||
.IndexName = oStep.IndexName,
|
||||
.Value = oValue
|
||||
})
|
||||
Next
|
||||
|
||||
Return oIndexItems
|
||||
End Function
|
||||
|
||||
Private Function IndexFile(pFile As ImportFile, pProfile As ImportProfile) As Boolean
|
||||
Logger.Debug("Writing [{0}] indexes for File [{1}]", pFile.IndexValues.Count, pFile.FilePathWindream)
|
||||
|
||||
Dim oIndexItems = ProcessSteps(pFile, pProfile)
|
||||
|
||||
Dim oResults = oIndexItems.
|
||||
Select(Function(v)
|
||||
Dim oIndexResult = False
|
||||
Logger.Info("Writing Index [{0}] with value [{1}]", v.IndexName, v.Value)
|
||||
|
||||
If Windream.TestIndexNameIsVectorIndex(v.IndexName) Then
|
||||
oIndexResult = Windream.SetFileIndex(pFile.FilePathWindream, v.IndexName, New List(Of String) From {v.Value}, pProfile.ObjectTypeName)
|
||||
Else
|
||||
oIndexResult = Windream.SetFileIndex(pFile.FilePathWindream, v.IndexName, v.Value, pProfile.ObjectTypeName)
|
||||
End If
|
||||
|
||||
Return oIndexResult
|
||||
End Function).
|
||||
ToList()
|
||||
|
||||
' Return True if all Indexes were set correctly
|
||||
Return oResults.All(Function(r) r = True)
|
||||
End Function
|
||||
|
||||
Private Function GetFiles(pDirectory As String, pRecursive As Boolean) As String()
|
||||
|
||||
@ -17,7 +17,7 @@ Namespace Scheduler.Jobs
|
||||
|
||||
context.Result = oResult
|
||||
|
||||
CompleteJob()
|
||||
CompleteJob("Done!")
|
||||
Return Task.FromResult(True)
|
||||
End Function
|
||||
End Class
|
||||
|
||||
@ -41,14 +41,14 @@ Public Class Service
|
||||
|
||||
' Initialize Windream
|
||||
Dim oWindream = Config.Windream
|
||||
Windream = New Windream(LogConfig, True, oWindream.DriveLetter, "/", True,
|
||||
Windream = New Windream(LogConfig, True, oWindream.DriveLetter, "\\windream\objects\", True,
|
||||
oWindream.Server, oWindream.Username, oWindream.Password, oWindream.Domain)
|
||||
|
||||
' initialize global state
|
||||
State = New State(LogConfig, Database, Windream)
|
||||
|
||||
' start the scheduler
|
||||
Scheduler = New Scheduler.JobScheduler(LogConfig, Database, State)
|
||||
Scheduler = New Scheduler.JobScheduler(LogConfig, Database, State, Windream)
|
||||
If Await Scheduler.Start() Then
|
||||
Logger.Info("Scheduler started!")
|
||||
Else
|
||||
|
||||
@ -4,6 +4,7 @@ Imports ECM.JobRunner.Windows.UpdateJob
|
||||
Imports ECM.JobRunner.Windows.UpdateProfile
|
||||
Imports ECM.JobRunner.Windows.GetJobStatus
|
||||
Imports ECM.JobRunner.Windows.GetJobConfig
|
||||
Imports ECM.JobRunner.Windows.RunJob
|
||||
|
||||
Namespace WCF
|
||||
<ServiceContract(Name:="IEDMIService", [Namespace]:="http://DigitalData.Services.EDMIService")>
|
||||
@ -15,6 +16,9 @@ Namespace WCF
|
||||
<OperationContract>
|
||||
Function GetJobStatus() As GetJobStatusResponse
|
||||
|
||||
'TODO: implement
|
||||
Function RunJob() As RunJobResponse
|
||||
|
||||
<OperationContract>
|
||||
Function UpdateJob(pData As UpdateJobRequest) As UpdateJobResponse
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@ Imports DigitalData.Modules.Database
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports DigitalData.Modules.Messaging.WCF
|
||||
Imports ECM.JobRunner.Windows.Scheduler
|
||||
Imports FxResources.System
|
||||
|
||||
Namespace WCF
|
||||
|
||||
@ -55,6 +56,11 @@ Namespace WCF
|
||||
Dim oMethod As New UpdateProfile.UpdateProfileMethod(LogConfig, Database, State, Scheduler)
|
||||
Return oMethod.Run(pData)
|
||||
End Function
|
||||
|
||||
Public Function RunJob() As RunJob.RunJobResponse Implements IJobRunner.RunJob
|
||||
'Dim oMethod As New RunJob.RunJobMethod(LogConfig, Database, State, Scheduler)
|
||||
'Return oMethod.Run(pData)
|
||||
End Function
|
||||
End Class
|
||||
|
||||
End Namespace
|
||||
|
||||
31
ECM.JobRunner.Windows/WCF/Methods/RunJob.vb
Normal file
31
ECM.JobRunner.Windows/WCF/Methods/RunJob.vb
Normal file
@ -0,0 +1,31 @@
|
||||
Imports DigitalData.Modules.Database
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports ECM.JobRunner.Windows.Scheduler
|
||||
Imports System.Runtime.Serialization
|
||||
|
||||
Public Class RunJob
|
||||
Public Class RunJobMethod
|
||||
Inherits Base.BaseMethod
|
||||
|
||||
Private ReadOnly Scheduler As JobScheduler
|
||||
|
||||
Public Sub New(pLogConfig As LogConfig, pDatabase As MSSQLServer, pState As State, pScheduler As JobScheduler)
|
||||
MyBase.New(pLogConfig, pDatabase, pState)
|
||||
Scheduler = pScheduler
|
||||
End Sub
|
||||
|
||||
Public Async Function Run(pData As RunJobRequest) As Task(Of RunJobResponse)
|
||||
Await Scheduler.ScheduleJob(pData.JobId)
|
||||
Return New RunJobResponse()
|
||||
End Function
|
||||
|
||||
End Class
|
||||
|
||||
Public Class RunJobRequest
|
||||
Public Property JobId As Integer
|
||||
End Class
|
||||
|
||||
Public Class RunJobResponse
|
||||
Inherits Base.BaseResponse
|
||||
End Class
|
||||
End Class
|
||||
Loading…
x
Reference in New Issue
Block a user