From 3a341f353d65be95568ba1bb34513d2152af6c91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Wed, 2 Nov 2022 11:42:44 +0100 Subject: [PATCH 01/41] Update Appveyor CI build --- .gitignore | 317 ++++++++++++++++++++++++++++++++++++++++++++++----- README.md | 30 +++-- appveyor.yml | 8 +- 3 files changed, 317 insertions(+), 38 deletions(-) diff --git a/.gitignore b/.gitignore index 948b1bc..2afa2e2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,11 +1,21 @@ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore # User-specific files +*.rsuser *.suo *.user +*.userosscache *.sln.docstates +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + # Build results [Dd]ebug/ [Dd]ebugPublic/ @@ -13,41 +23,65 @@ [Rr]eleases/ x64/ x86/ -build/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ bld/ [Bb]in/ [Oo]bj/ +[Ll]og/ +[Ll]ogs/ -# Roslyn cache directories -*.ide/ - -# Visual Studio cache directory +# Visual Studio 2015/2017 cache/options directory .vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ -# Rider directory -.idea/ +# Visual Studio 2017 auto generated files +Generated\ Files/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* -#NUNIT +# NUnit *.VisualState.xml TestResult.xml +nunit-*.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET +project.lock.json +project.fragment.lock.json +artifacts/ + +# Tye +.tye/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio *_i.c *_p.c -*_i.h +*_h.h *.ilk *.meta *.obj +*.iobj *.pch *.pdb +*.ipdb *.pgc *.pgd *.rsp @@ -57,6 +91,7 @@ dlldata.c *.tlh *.tmp *.tmp_proj +*_wpftmp.csproj *.log *.vspscc *.vssscc @@ -72,14 +107,21 @@ _Chutzpah* ipch/ *.aps *.ncb +*.opendb *.opensdf *.sdf *.cachefile +*.VC.db +*.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx +*.sap + +# Visual Studio Trace Files +*.e2e # TFS 2012 Local Workspace $tf/ @@ -92,18 +134,29 @@ _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user -# JustCode is a .NET coding addin-in -.JustCode - # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + # NCrunch _NCrunch_* .*crunch*.local.xml +nCrunchTemp_* # MightyMoose *.mm.* @@ -131,39 +184,71 @@ publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml -# TODO: Comment the next line if you want to checkin your web deploy settings +# Note: Comment the next line if you want to checkin your web deploy settings, # but database connection strings (with potential passwords) will be unencrypted *.pubxml *.publishproj +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + # NuGet Packages *.nupkg +# NuGet Symbol Packages +*.snupkg # The packages folder can be ignored because of Package Restore -**/packages/* +**/[Pp]ackages/* # except build/, which is used as an MSBuild target. -!**/packages/build/ -# If using the old MSBuild-Integrated Package Restore, uncomment this: -#!**/packages/repositories.config - -# Windows Azure Build Output +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output csx/ *.build.csdef -# Windows Store app package directory +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ # Others -sql/ -*.Cache ClientBin/ -[Ss]tyle[Cc]op.* ~$* *~ *.dbmdl *.dbproj.schemaview +*.jfm *.pfx *.publishsettings -node_modules/ +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ # RIA/Silverlight projects Generated_Code/ @@ -175,21 +260,195 @@ _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak # SQL Server files *.mdf *.ldf +*.ndf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl # Microsoft Fakes FakesAssemblies/ -# output of ilmerge & nuget package -tools/Jobbr.Server.* -*.ncrunchproject -docs/_build/ -source/.vs/ +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/master/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/master/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# JetBrains Rider +.idea/ +*.sln.iml + +## +## Visual Studio Code +## +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json diff --git a/README.md b/README.md index a219e53..692d3db 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,12 @@ -# Jobbr [![Build status](https://img.shields.io/appveyor/ci/jobbr/jobbr-server/develop.svg)](https://ci.appveyor.com/project/Jobbr/jobbr-server) +# Jobbr [![Build status](https://img.shields.io/appveyor/build/jobbr/jobbr-server/develop.svg?label=develop)](https://ci.appveyor.com/project/Jobbr/jobbr-server) + Jobbr is a .NET job server. It is designed to reduce artifical complexity when a job server is needed in a project. Jobbr tries to get out of your way as much as possible so that you can focus on business logic. Job implementations have no dependency to Jobbr which makes it easy to integrate Jobbr in any .NET project. +[![Master build status](https://img.shields.io/appveyor/ci/Jobbr/jobbr-server/master.svg?label=master)](https://ci.appveyor.com/project/Jobbr/jobbr-server) +[![NuGet-Stable](https://img.shields.io/nuget/v/Jobbr.Server.svg?label=NuGet%20stable)](https://www.nuget.org/packages/Jobbr.Server) +[![Develop build status](https://img.shields.io/appveyor/ci/Jobbr/jobbr-server/develop.svg?label=develop)](https://ci.appveyor.com/project/Jobbr/jobbr-server) +[![NuGet Pre-Release](https://img.shields.io/nuget/vpre/Jobbr.Server.svg?label=NuGet%20pre)](https://www.nuget.org/packages/Jobbr.Server) + ## Main Features * Isolation of Jobs on process-level @@ -15,9 +21,11 @@ Jobbr is a .NET job server. It is designed to reduce artifical complexity when a * Progress tracking via stdout (`Console.WriteLine()`) ## QuickStart -The best way to get started is to check out the [demo repo](https://github.com/jobbrIO/jobbr-demo) to see a running example of Jobbr. + +The best way to get started is to check out the [demo repo](https://github.com/jobbrIO/demo) to see a running example of Jobbr. ## Implementing a job + Good news! All your C#-Code is compatible with jobbr as long as the CLR-type can be instantiated and has at least a public `Run()`- Method. ```c# @@ -38,6 +46,7 @@ public class SampleJob ``` ## Configuring job with triggers + To define jobs use the `AddJobs` extension method: ```c# jobbrBuilder.AddJobs(repo => @@ -53,6 +62,7 @@ jobbrBuilder.AddJobs(repo => If you need to add triggers at runtime head over to the [REST API component](https://github.com/jobbrIO/jobbr-webapi) which also includes a typed client. The REST API is optional and has to be plugged in if needed. ## Persistence + There are two different storages: - `Storage`: stores jobs, triggers and jobruns @@ -61,17 +71,21 @@ There are two different storages: By default Jobbr runs in memory, thus all data is lost when Jobbr is restarted. To keep the data configure one of the storage providers: ### Storage + - [MsSql Storage Provider](https://github.com/jobbrIO/jobbr-server-mssql) to store the data in MS SQL Server - [RavenDb Storage Provider](https://github.com/jobbrIO/jobbr-server-ravendb) to store the data in [RavenDB](http://ravendb.net) ### ArtefactStorage + - [Filesystem Storage Provider](https://github.com/jobbrIO/jobbr-artefactstorage-filesystem) to store the data in a folder - [RavenFS Storage Provider](https://github.com/jobbrIO/jobbr-artefactstorage-ravenfs) to store the data in [RavenDB](http://ravendb.net) ## Logging + Jobbr uses the LibLog library to detect your Logging-Framework of the Hosting Process. When using Jobbr, you don't introduce a new dependency to an existing Logging-Framework. See https://github.com/damianh/LibLog for details. # License + This software is licenced under GPLv3. See [LICENSE](LICENSE), please see the related licences of 3rd party libraries below. ## Acknowledgements @@ -85,10 +99,12 @@ Jobbr Server is based on following great open source projects: * [TinyMessenger](https://github.com/grumpydev/TinyMessenger/blob/master/licence.txt) [(Ms-PL)](https://github.com/grumpydev/TinyMessenger/blob/master/licence.txt) ## Credits + This application was built by the following awesome developers: -* Michael Schnyder -* Oliver Zürcher -* Peter Gfader -* Mark Odermatt +* [Michael Schnyder](https://github.com/michaelschnyder) +* [Oliver Zürcher](https://github.com/olibanjoli) +* [Peter Gfader](https://twitter.com/peitor) +* [Mark Odermatt](https://github.com/mo85) * [Steven Giesel](https://github.com/linkdotnet) -* David Fiebig +* [David Fiebig](https://github.com/david-fiebig) +* [Lukas Dürrenberger](https://github.com/eXpl0it3r) diff --git a/appveyor.yml b/appveyor.yml index d576ca7..0eca95f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -image: Visual Studio 2017 +image: Visual Studio 2019 branches: only: @@ -7,13 +7,17 @@ branches: - /release/.*/ - /hotfix/.*/ - /feature/.*/ + - /bugfix/.*/ skip_commits: files: - docs/* +environment: + IGNORE_NORMALISATION_GIT_HEAD_MOVE: 1 + install: - git submodule update --init --recursive - - choco install gitversion.portable --version 4.0.0 + - choco install gitversion.portable --version 5.10.3 -y assembly_info: patch: false From 771a42e6d56d691271186db4ebf1a94f7da5d423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Wed, 2 Nov 2022 11:47:30 +0100 Subject: [PATCH 02/41] Update Newtonsoft Json to 13.0.1 --- source/Jobbr.Server/Jobbr.Server.csproj | 5 ++--- source/Jobbr.Server/packages.config | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index b9a763e..408f25b 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -61,9 +61,8 @@ ..\packages\NCrontab.3.3.1\lib\net35\NCrontab.dll - - ..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll - True + + ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll ..\packages\Ninject.3.3.4\lib\net45\Ninject.dll diff --git a/source/Jobbr.Server/packages.config b/source/Jobbr.Server/packages.config index e29eae6..702d5e7 100644 --- a/source/Jobbr.Server/packages.config +++ b/source/Jobbr.Server/packages.config @@ -13,7 +13,7 @@ - + From a8c2c571848d46921ecf0e3bfa5e602da856f277 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Fri, 4 Nov 2022 20:36:19 +0100 Subject: [PATCH 03/41] Convert to SDK project format - Update nuspec - Use PackageReference - Update devsupport tooling --- source/Jobbr.Server.nuspec | 13 +- source/Jobbr.Server/Jobbr.Server.csproj | 201 ++++-------------- .../Jobbr.Server/Properties/AssemblyInfo.cs | 40 ---- source/Jobbr.Server/packages.config | 24 --- source/Jobbr.Tests/Jobbr.Tests.csproj | 171 +++------------ source/Jobbr.Tests/PackagingTests.cs | 3 +- source/Jobbr.Tests/Properties/AssemblyInfo.cs | 37 ---- source/Jobbr.Tests/app.config | 12 ++ source/Jobbr.Tests/packages.config | 14 -- source/icon.png | Bin 0 -> 5329 bytes source/submodules/devsupport | 2 +- 11 files changed, 88 insertions(+), 429 deletions(-) delete mode 100644 source/Jobbr.Server/Properties/AssemblyInfo.cs delete mode 100644 source/Jobbr.Server/packages.config delete mode 100644 source/Jobbr.Tests/Properties/AssemblyInfo.cs delete mode 100644 source/Jobbr.Tests/packages.config create mode 100644 source/icon.png diff --git a/source/Jobbr.Server.nuspec b/source/Jobbr.Server.nuspec index 111f18d..c564605 100644 --- a/source/Jobbr.Server.nuspec +++ b/source/Jobbr.Server.nuspec @@ -5,12 +5,12 @@ $version$ Jobbr Jobbr - http://github.com/jobbrIO/jobbr-server - https://raw.githubusercontent.com/jobbrIO/jobbr-server/develop/LICENSE + https://github.com/jobbrIO/jobbr-server + GPL-3.0-only true Jobbr is a non-invasive .NET JobServer - https://raw.githubusercontent.com/jobbrIO/artwork/master/build/icons/icon_detailed_256_dark.png - Copyright 2018 + Copyright 2022 + images\icon.png @@ -20,7 +20,8 @@ - - + + + diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index 408f25b..b7b2149 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -1,162 +1,24 @@ - - - - + - Debug - AnyCPU {A45F729D-8629-4C7A-96B8-29EAA8D52919} - Library - Properties - Jobbr.Server - Jobbr.Server - v4.6.2 - 512 - - - + net462 + Jobber.Server + Zuehlke Technology Group + Jobbr.Server + Copyright © Zuehlke Technology Group 2015 + 1.0.0-pre + ..\JobbrRuleSet.ruleset + bin\$(Configuration)\ - true full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - ..\JobbrRuleSet.ruleset false pdbonly - true - bin\Release\ - TRACE - prompt - 4 - ..\JobbrRuleSet.ruleset - - ..\packages\AutoMapper.7.0.1\lib\net45\AutoMapper.dll - - - ..\packages\Costura.Fody.3.3.3\lib\net40\Costura.dll - - - ..\packages\Jobbr.ComponentModel.ArtefactStorage.1.0.1\lib\net462\Jobbr.ComponentModel.ArtefactStorage.dll - - - ..\packages\Jobbr.ComponentModel.Execution.1.0.1\lib\net462\Jobbr.ComponentModel.Execution.dll - - - ..\packages\Jobbr.ComponentModel.JobStorage.1.4.0\lib\net462\Jobbr.ComponentModel.JobStorage.dll - - - ..\packages\Jobbr.ComponentModel.Management.1.6.0\lib\net462\Jobbr.ComponentModel.Management.dll - - - ..\packages\Jobbr.ComponentModel.Registration.1.0.1\lib\net462\Jobbr.ComponentModel.Registration.dll - - - ..\packages\NCrontab.3.3.1\lib\net35\NCrontab.dll - - - ..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll - - - ..\packages\Ninject.3.3.4\lib\net45\Ninject.dll - - - - - - ..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Designer - - - - - - - - - - - - - @@ -166,20 +28,33 @@ - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - + + + + + + all + + + + + + + + all + + + + + + + + all + + + + + + + \ No newline at end of file diff --git a/source/Jobbr.Server/Properties/AssemblyInfo.cs b/source/Jobbr.Server/Properties/AssemblyInfo.cs deleted file mode 100644 index a7bfe2c..0000000 --- a/source/Jobbr.Server/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,40 +0,0 @@ -using System; -using System.Reflection; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Jobber.Server")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Zuehlke Technology Group")] -[assembly: AssemblyProduct("Jobbr.Server")] -[assembly: AssemblyCopyright("Copyright © Zuehlke Technology Group 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -[assembly: CLSCompliant(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("b0b9dc2d-cdf9-4e89-83ca-1319cf585c6a")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] - -[assembly: AssemblyInformationalVersion("1.0.0-pre")] diff --git a/source/Jobbr.Server/packages.config b/source/Jobbr.Server/packages.config deleted file mode 100644 index 702d5e7..0000000 --- a/source/Jobbr.Server/packages.config +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/source/Jobbr.Tests/Jobbr.Tests.csproj b/source/Jobbr.Tests/Jobbr.Tests.csproj index 84d8222..d78707b 100644 --- a/source/Jobbr.Tests/Jobbr.Tests.csproj +++ b/source/Jobbr.Tests/Jobbr.Tests.csproj @@ -1,169 +1,56 @@ - - + - Debug - AnyCPU {304D07A5-D6D1-4F48-819E-5D28ED8755AC} - Library - Properties - Jobbr.Tests - Jobbr.Tests - v4.6.2 - 512 + net462 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 10.0 $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages False UnitTest - + Jobbr.Tests + Zuehlke Technology Group + Jobbr.Tests + Copyright © Zuehlke Technology Group 2015 + 1.0.0.0-pre + bin\$(Configuration)\ - true full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 ..\JobbrRuleSet.ruleset pdbonly - true - bin\Release\ - TRACE - prompt - 4 + - - ..\packages\AutoMapper.7.0.1\lib\net45\AutoMapper.dll - - - ..\packages\Castle.Core.5.1.0\lib\net462\Castle.Core.dll - - - ..\packages\Jobbr.ComponentModel.ArtefactStorage.1.0.1\lib\net462\Jobbr.ComponentModel.ArtefactStorage.dll - - - ..\packages\Jobbr.ComponentModel.Execution.1.0.1\lib\net462\Jobbr.ComponentModel.Execution.dll - - - ..\packages\Jobbr.ComponentModel.JobStorage.1.4.0\lib\net462\Jobbr.ComponentModel.JobStorage.dll - - - ..\packages\Jobbr.ComponentModel.Management.1.6.0\lib\net462\Jobbr.ComponentModel.Management.dll - - - ..\packages\Jobbr.ComponentModel.Registration.1.0.1\lib\net462\Jobbr.ComponentModel.Registration.dll - - - - ..\packages\Moq.4.18.2\lib\net462\Moq.dll - - - - - ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll - - - - ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll - - - ..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll - - - - - - - - - - - - False - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - + + - - {a45f729d-8629-4c7a-96b8-29eaa8d52919} - Jobbr.Server - - - {D7C78DBD-D440-4D0C-B9A9-AD8B7473364A} - Jobbr.DevSupport.ReferencedVersionAsserter - + + CustomDictionary.xml - - - - - False - - - False - - - False - - - False - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/Jobbr.Tests/PackagingTests.cs b/source/Jobbr.Tests/PackagingTests.cs index df05971..c603783 100644 --- a/source/Jobbr.Tests/PackagingTests.cs +++ b/source/Jobbr.Tests/PackagingTests.cs @@ -7,10 +7,9 @@ namespace Jobbr.Tests public class PackagingTests { [TestMethod] - [Ignore] public void Feature_NuSpec_IsCompliant() { - var asserter = new Asserter(Asserter.ResolvePackagesConfig("Jobbr.Server"), Asserter.ResolveRootFile("Jobbr.Server.nuspec")); + var asserter = new Asserter(Asserter.ResolveProjectFile("Jobbr.Server", "Jobbr.Server.csproj"), Asserter.ResolveRootFile("Jobbr.Server.nuspec")); asserter.Add(new PackageExistsInBothRule("Jobbr.ComponentModel.ArtefactStorage")); asserter.Add(new PackageExistsInBothRule("Jobbr.ComponentModel.Execution")); diff --git a/source/Jobbr.Tests/Properties/AssemblyInfo.cs b/source/Jobbr.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index 981ae25..0000000 --- a/source/Jobbr.Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Jobbr.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Zuehlke Technology Group")] -[assembly: AssemblyProduct("Jobbr.Tests")] -[assembly: AssemblyCopyright("Copyright © Zuehlke Technology Group 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("fd489320-c98b-4c17-a2dd-5666b591871e")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] -[assembly: AssemblyInformationalVersion("1.0.0.0-pre")] diff --git a/source/Jobbr.Tests/app.config b/source/Jobbr.Tests/app.config index 3a97385..b00fb16 100644 --- a/source/Jobbr.Tests/app.config +++ b/source/Jobbr.Tests/app.config @@ -18,6 +18,18 @@ + + + + + + + + + + + + diff --git a/source/Jobbr.Tests/packages.config b/source/Jobbr.Tests/packages.config deleted file mode 100644 index 6610cc2..0000000 --- a/source/Jobbr.Tests/packages.config +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/source/icon.png b/source/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1bf379f0e5911135a2c6b9292f2a2c4deadb6e1a GIT binary patch literal 5329 zcmYj#1yB@F*Y*O-F1@5kE*%1r(y_3_vP+ljiUP7$n!L3OEAR)S4 zoU6=DZk=NT9TSaPmkX+MUr>t+isIwZzn%YYaQv^$$^0J!$;19%QK-)UA^)2NMR9Zf z2ll@JZjS#(>Tt3C$JOEa|E$~S-?hd+O>kZ=9e!@z^LOw+D-D7?I=|}R!hAZXjqtPO zdO<$@-(Tz2iq)lrQ9Bjt!U6^o_fS*W8sE#+4{G2WBjr+}CSt-yvZAPy26${>u(B-L zTmu>JfT+T1F666MWF@L9U_8vUU5vGVR;lmJR=+Du5fwlgs30S35$SGP@1r&A!!?(S z)DOSZtPGZZ?JF*S6`!9J6XxabX6vr5WT7Z+4wpt*p|riwh)hqd6c?>e85*B+)VC)q zCR+1`-{lO{XTNyn`Pjt42x%iLX$F%*Ss;*(hT68e+QCl{H91N6&`^7e=i2f}tTn>v ziL0)rm4Z0RSPhxyqtza-*^{KvnW*t&{B22koEGe{t`bsH7FiOg*_WcRQL28tP`f)- zIoDIvTay{!>hl!s^ian8c zZhc_zjv+gEu$xfU_=+H=N|J8#r-aI3LfOHek3unz*mOF8o4K~%?;}Y#DX83WZ z^rgwQFou_Ab&fr6Z1BBqqDjPky`Ah|?V=(bmc?$s!xi{QJGC}8Axa`t3gnrP!}ogO zMa&;e7-qUoJwU5OOxwpx7+tElJ|(su?i1h3NfWMOE=R#Fj-Fa$aaP#oH88ppWG7Ad z7>6TWbs=tM;IW|~ba-inS8pnUQ#+^Oo(*DQ_LB!=n4i?~F1!M=vv>PuDpj+QJ8it{#wBg}bLI-=0c9IoUe+4S7XW*rU2km4= zMHXUf8@RSVq@>3p+0^O3@h$Ohf)U+FZ_J&hsvgtBoHp5OpkS3=>MPZS_iN)F#7E(r zJmM_4)D`lBUB=>Jeh2Y03+oA9-&3aJI?9)KCa1)rR~US~$+9FUS8M-82aglUfT7~G zqWjZ)KTdMn{w;=Exafc5U>wZRTw4Cc$s@#fd3n7;lfMqO9euZ*c;+?cJijG*8Sdpf zwz#8DXGl-%F6A-T2hpTUjMaR@x7C?dGdW@j>mfE+P(=fQOJo8V1M%{hmcxHFH)TmO zB{PM&JMH#<$Nv`9rX}4cf+d&lp+PKPdPKwt&0Hb(7dz2T*N0Jo{0MXOR*%kCGM?w* zfdTw9)!Xbki(K{BYHIoUo;%a^gjGswf1y@%JiiU}*fh*ZsqVDA151q4PK_L@TGx(( z%*jau7_-_BR4MZ?hpzl91We*8Qxd0E4r1~qepP$ViK-pJRSJoVvJgC@}`FNFiQBX^Hvf z4d&9T`OO7!N%#kZ3`wo~Aa-~kx^hB965@M}D?RamA@O{&fYori1aiLSC) zrzb%FXrcDih`Kl33z~=-J!99#WJZBAE4tL`FmLzDZ67WV6C%d8E*&MmrEpz@G@!-1 zGBxIMLLb+LX;D=26HU@Zm;#nVX!Fi+|6n=i6X4M6XkC(n-=#Gd{agSIM!{&*5S;BB zGd#Ia0GpJ4%&@da=P8X-oRz$9PRSHU=%*(bS=-%Fz>4H>%kk)xLl`i?__OX+b_a7l zYv$DL>b8~PG$o)%4_s5aztQhF=vh6{DUSwf5G4E+OzZ+%^d34woG24@NMuxTMF7{d z{8Hwk5sx@jO#!0AyA4zY6{BtJRf!Vt3vYzMoo*;*gRjLeVsAM*u&{@j z?+*q7$29;XWV(7~TexjSX~Q3Fjb;}9Y6Fpy5e+Hcc$*STil&I%IJeL{J&P(lNiLAW zHcP_~9HPM!VE!zF8Coo`gkYO3y(b^wtMMKTkx^14sywl|)^g@l^#If(-V4f*9YpCs zc8ToBHGFHIXff|cCtWNeIaOT%KC4urqOEml&vOQhR)3(Uk6`L_Qq<)?v|Ug6hA9hf0wXt!O%dh-W4&kFF)yS6dB+jc8RdzYx3 zN8zOnXOO;G2Hqxi#|+x|A_x{uaY|s~O)d9od7Gppc4^jn(wj2=#|khj_xOk85Z6)1 z{uYl!Iix^T?QA71aHlN&nFq<|Pbd5Pc5VYih}IdSF$vim+|78*iFF!C=#-$H56s5j zllz9}W`S0Cvg}@FVHIaYv83_-nC7Pk=8ly8@!_6}%wc~4mZ@o|BJ%tcu~h6)U{qES zT?v9rDt&<>d_V#5@b5rS{-JR-DD5wRc5|DrWsatvZ7}s=Ee=ip1QD$05~Lgm^i8pE zU0!6cyRrxF62+vwL9klLOl_$!V-rgBNt7iZ{~(W?%}dMe^}5K{6Ixk2OM42Gv8hPU zSyMt-=(W!sH5Y|ZzNIe_8c&mOSv00)mTWdrac^Vatv*;PfE%y_TrVCgk|r`(hnX?j zO9x4QGxusK@oHt@PRPNavU%^tXX8m`!B|H9p;#4b%dh%l+UQ^oQ_@dKSsHW^ zJ^e5ck!I1(3(0%CM!|q>1Z&q|DVtLO0uzW04K_nqoPF-< zvaonF#*~jHeM*fS&2pS1DGBC$6CnIx&VK9@D3cz{;Sjt$p&;;e7uw2l2escM*)LqS z28fWimj_w9@-6;lK_^_5TRpdoj@$)Ar1p_E-c|TU%@@6Z%W~RILc4a7ek;q|VNdm% zFTZwega}f?Chb)$f72OSd!Ejf;x>Av!&&U_&nf~Lk4qi^k4uyRoM%aGfsgf=Nj?G; zEhD?yaWYR3X$Fs|RYk~(L>L54gSz9`CPb?BDx3T&=(X6Y@$wkwLGqV84X^3l>F9iC zx1JTM9P2f#HgmRp@V~y|ogc`y&3cS0(GF3>m25i_e@un~&L^3!%)I9@n_50}M>!(e zbScTu?vvtR*z?WtG|@BJKbd#A!vuyP96#P2_sEKz7$|G|j&7T~3x<^-JJs8wsApraAiSMjWL8M0w zGKXyRy=hRaGV&Gc-9`jq`<{qDC{kdk3z%cH0?6Pausow(`68frL12|D9KTkR3e8sf z9!n<~f3yiI*o8Hd&GwjTM`UzJi}ODv(Fg&2kdQAOnkH;Ua<%X6-((OuNKe-5ymE2( zr(L(J)gI%I;8MYs{E?978}ejW(!pB#g=Z?Nr9fe$jyIlqreI$=n5bg^=th?`6Z7aK zNZ!d-+(gWI^9J87Aw>4={~h38#3w({pupew!sDjn2q>3ecbgK>cy-dN&u{@zz(-72 znuC+M9~CCJZ-T{K8SXP+U1dTR;bN`pU5p{FW#^yNWsivrstNN03!Md zPev##Ppd;kCSfNr5tjfXkn`45A)i0fHiNUp=knS#c`i;BEYq%pRTeKQh@EImW|(*P zqV_iVRbTp~NBZ-ft-H264(+}qCN!iM1Xca9^+_L8@f!(vRq2P4o25-&>hKUirNW?i zj5pW>*TL=^*L{Cr zBeCjqm&44X)6mdb?zh)`z~pY9Mg)fnw&J`q@2R4;#e0mVijeMB=qszX;Ovg76B4y# zR@gnbE4h2Iq7d$#esJElGtcsb(SCEAi4 zeb{XFGd|J6McA(5$VgPD^}I;26nM1xPnl$h96R&LNYGmQC9?GG;E_<^1eO17v>NCE zTY^TDz@lC#$YixC6$3qgbjGb7`vToP%-1znioWI1PPRSzqqN>U2RUp%H`v4Y>5}da zxB&U7tRUCzFX9H}x?2qpe&6#i;$piyz6f^OLd9NSu7PGpZua!`lKE z99d#|0YUE1`8gTY?oXx{7oSgurVG4oiGPkL_JK3np{WgCg-P2GBkZ)$1R^iVG~OLz zn$YHkbxKczXxmn~=OyJ|j3Z8-#9EKCQQ+ifo1}%yhy4cjj=r*?N4){LcI$&=v%-Eq zs*hQ!|E^+H4We7^p-8E0Kel$>ihlzkq4EBtJUqQ$TF`?weR@Q&f6+(Q;CpeKB_P*j zUz^znVt%10bS)LJ{xFJtNnQr;X6Q=heb|=#45{HN@wM$#rFOy1u)?t;vR&}F?+HnB zqzg~^8~*g*=ypZ_%FMM>)r7ieZbse0UE1kV-tY{6HaW_`_g9~Loe_Zu345Ko-FU+@ z_u`KG^!xBHMVdwwA=+Pc~jqPbvvSDE{IqaZpQ~=zy5xF5=5be2~4I5L>y1QSUWMEPY;*B9L)Tb7MI03U)55xr35$) zF0>)1C1V!!rw3=4uK%bgRAiOIHajNL+kIQJ4h1w9;O*<^!qijK?ToF~mXDX`1xr&q zdr_*~&{Wg9d1ZzgvqC?^Ix0vb^FJqg*b%594B z8RN~NKc*+Cw#TJ-H+*PaNr&*enC~}V>DS7b`A!5@=bcbG-iL=}Wf9f}Y@G~@S9VFR zgv)O}V5XE6JJ_KwzGR(8uQva60e-unAl}!YN~zD}2Q4byzS#k)I;oA~5qTbmOuvRj zxi;+^`;eo3G&b?%eR}zjedUr%-GxMIySyfkSG; zE_Xomk%sKuBq1r9#TkPfd?jyorkBe`8O}tL8(K6Y&?f1`th+cZ#bZr{@KEpAgW{t&9c2I_r zwb@A6XNx>FJs}pWv;YK6a!y=WrnHz*tLH4=(^u>Bb(H9A80j@^7C2f`*bfq zyHx^x6K%)K1mmvXIr}P*;0yp*)$1`imZp~rIYNCBD>qlirSV_9u&q7Ahm=^45Lwm+ z*(fC;Cq@!tM={;nq#7RkJ1a#)`|N#w+;;Qchl}}D_+OUSqQk~_A&Ht+lai8nbt&)K zTs3A!VD#C>gH;jlmP;i`En5#w8Msju$jHo1^H#))CgbW$YNaiA76h(x zl@#nvtCFJc=$GY2xG!4a+QM{HHDF30cbqu7v!;^KN!riioJ8J<%~x!>{iOnEYv`%h Is9E9u2jVrrLjV8( literal 0 HcmV?d00001 diff --git a/source/submodules/devsupport b/source/submodules/devsupport index 5184c86..643d004 160000 --- a/source/submodules/devsupport +++ b/source/submodules/devsupport @@ -1 +1 @@ -Subproject commit 5184c868934d78f14a6999ea5f5562dace1fd05e +Subproject commit 643d004936c5df825592233971320a702dae6daf From 7521c859658f6dd03ff2599c778087b71a0354ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Fri, 11 Nov 2022 17:09:47 +0100 Subject: [PATCH 04/41] Align dependency versions --- source/Jobbr.Server/Jobbr.Server.csproj | 4 ++-- source/Jobbr.Tests/Jobbr.Tests.csproj | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index b7b2149..90a6a4c 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -47,8 +47,8 @@ - - + + all diff --git a/source/Jobbr.Tests/Jobbr.Tests.csproj b/source/Jobbr.Tests/Jobbr.Tests.csproj index d78707b..5da05d1 100644 --- a/source/Jobbr.Tests/Jobbr.Tests.csproj +++ b/source/Jobbr.Tests/Jobbr.Tests.csproj @@ -23,9 +23,9 @@ - - - + + + From cb1761c20b44a2619b13314c4100d83eb0334fd9 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Tue, 15 Nov 2022 14:42:54 +0100 Subject: [PATCH 05/41] Upgrade target frameworks and package references to NET6 --- source/Jobbr.Server.sln | 13 ++++++++----- source/Jobbr.Server/Jobbr.Server.csproj | 21 ++++++++++----------- source/Jobbr.Tests/Jobbr.Tests.csproj | 20 ++++++++++---------- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/source/Jobbr.Server.sln b/source/Jobbr.Server.sln index 5440047..7a22aab 100644 --- a/source/Jobbr.Server.sln +++ b/source/Jobbr.Server.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26430.14 +# Visual Studio Version 17 +VisualStudioVersion = 17.4.33103.184 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionFiles", "SolutionFiles", "{3B0F0067-E652-4915-86BA-0B6595ABF789}" ProjectSection(SolutionItems) = preProject @@ -10,9 +10,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionFiles", "SolutionFi ..\README.md = ..\README.md EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jobbr.Server", "Jobbr.Server\Jobbr.Server.csproj", "{A45F729D-8629-4C7A-96B8-29EAA8D52919}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jobbr.Server", "Jobbr.Server\Jobbr.Server.csproj", "{A45F729D-8629-4C7A-96B8-29EAA8D52919}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jobbr.Tests", "Jobbr.Tests\Jobbr.Tests.csproj", "{304D07A5-D6D1-4F48-819E-5D28ED8755AC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jobbr.Tests", "Jobbr.Tests\Jobbr.Tests.csproj", "{304D07A5-D6D1-4F48-819E-5D28ED8755AC}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{13B2F939-2E3C-4145-A00B-6B6D42680598}" ProjectSection(SolutionItems) = preProject @@ -24,7 +24,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{13B2F939 EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "submodules", "submodules", "{256FF5EC-6208-4EEA-8FB1-1F9E131F9644}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jobbr.DevSupport.ReferencedVersionAsserter", "submodules\devsupport\src\Jobbr.DevSupport.ReferencedVersionAsserter\Jobbr.DevSupport.ReferencedVersionAsserter.csproj", "{D7C78DBD-D440-4D0C-B9A9-AD8B7473364A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jobbr.DevSupport.ReferencedVersionAsserter", "submodules\devsupport\src\Jobbr.DevSupport.ReferencedVersionAsserter\Jobbr.DevSupport.ReferencedVersionAsserter.csproj", "{D7C78DBD-D440-4D0C-B9A9-AD8B7473364A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -51,4 +51,7 @@ Global GlobalSection(NestedProjects) = preSolution {D7C78DBD-D440-4D0C-B9A9-AD8B7473364A} = {256FF5EC-6208-4EEA-8FB1-1F9E131F9644} EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {566C76B3-8585-43FA-B324-A040A569B548} + EndGlobalSection EndGlobal diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index 90a6a4c..3891650 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -1,7 +1,7 @@  {A45F729D-8629-4C7A-96B8-29EAA8D52919} - net462 + net6.0 Jobber.Server Zuehlke Technology Group Jobbr.Server @@ -30,16 +30,7 @@ - - - all - - - - - - all @@ -54,7 +45,15 @@ - + + all + + + + + + + \ No newline at end of file diff --git a/source/Jobbr.Tests/Jobbr.Tests.csproj b/source/Jobbr.Tests/Jobbr.Tests.csproj index 5da05d1..9d2bab7 100644 --- a/source/Jobbr.Tests/Jobbr.Tests.csproj +++ b/source/Jobbr.Tests/Jobbr.Tests.csproj @@ -1,7 +1,7 @@  {304D07A5-D6D1-4F48-819E-5D28ED8755AC} - net462 + net6.0 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages @@ -26,10 +26,18 @@ + + + all + + + + + + - @@ -42,15 +50,7 @@ - - - - - - - - \ No newline at end of file From fa9856b9c55fd5275651aa50a46fdc46ab53f1c0 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Tue, 15 Nov 2022 14:51:50 +0100 Subject: [PATCH 06/41] Remove Fody --- .../Builder/AutoMapperConfigurationFactory.cs | 1 - source/Jobbr.Server/FodyWeavers.xml | 4 - source/Jobbr.Server/FodyWeavers.xsd | 111 ------------------ source/Jobbr.Server/Jobbr.Server.csproj | 4 - 4 files changed, 120 deletions(-) delete mode 100644 source/Jobbr.Server/FodyWeavers.xml delete mode 100644 source/Jobbr.Server/FodyWeavers.xsd diff --git a/source/Jobbr.Server/Builder/AutoMapperConfigurationFactory.cs b/source/Jobbr.Server/Builder/AutoMapperConfigurationFactory.cs index e94e2e3..9a44962 100644 --- a/source/Jobbr.Server/Builder/AutoMapperConfigurationFactory.cs +++ b/source/Jobbr.Server/Builder/AutoMapperConfigurationFactory.cs @@ -10,7 +10,6 @@ public class AutoMapperConfigurationFactory { private static readonly ILog Logger = LogProvider.For(); - [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "We want to express the dynamic aspect of it")] public MapperConfiguration GetNew() { var foundAutoMapperProfiles = new List(); diff --git a/source/Jobbr.Server/FodyWeavers.xml b/source/Jobbr.Server/FodyWeavers.xml deleted file mode 100644 index a5dcf04..0000000 --- a/source/Jobbr.Server/FodyWeavers.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/source/Jobbr.Server/FodyWeavers.xsd b/source/Jobbr.Server/FodyWeavers.xsd deleted file mode 100644 index 44a5374..0000000 --- a/source/Jobbr.Server/FodyWeavers.xsd +++ /dev/null @@ -1,111 +0,0 @@ - - - - - - - - - - - - A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks - - - - - A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. - - - - - A list of unmanaged 32 bit assembly names to include, delimited with line breaks. - - - - - A list of unmanaged 64 bit assembly names to include, delimited with line breaks. - - - - - The order of preloaded assemblies, delimited with line breaks. - - - - - - This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. - - - - - Controls if .pdbs for reference assemblies are also embedded. - - - - - Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. - - - - - As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. - - - - - Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. - - - - - Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. - - - - - A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | - - - - - A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. - - - - - A list of unmanaged 32 bit assembly names to include, delimited with |. - - - - - A list of unmanaged 64 bit assembly names to include, delimited with |. - - - - - The order of preloaded assemblies, delimited with |. - - - - - - - - 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. - - - - - A comma-separated list of error codes that can be safely ignored in assembly verification. - - - - - 'false' to turn off automatic generation of the XML Schema file. - - - - - \ No newline at end of file diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index 3891650..57b9c1c 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -25,9 +25,6 @@ CustomDictionary.xml - - - @@ -49,7 +46,6 @@ all - From aeb5fb8e40f02f41a4bb7fc3d9d44b322562123b Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Tue, 15 Nov 2022 15:07:12 +0100 Subject: [PATCH 07/41] Remove obsolete code analyzers --- source/Jobbr.Server/Jobbr.Server.csproj | 6 ------ 1 file changed, 6 deletions(-) diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index 57b9c1c..b16ca18 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -27,21 +27,15 @@ - all - - all - - - all From c103552a77df5a4a34476d8e32e75e88a320f0cc Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Wed, 16 Nov 2022 12:17:41 +0100 Subject: [PATCH 08/41] Remove LibLog and replace with Microsoft logging abstractions --- .../App_Packages/LibLog.3.1/LibLog.cs | 1942 ----------------- .../Builder/AutoMapperConfigurationFactory.cs | 26 +- .../Jobbr.Server/Builder/DefaultContainer.cs | 39 +- source/Jobbr.Server/Builder/JobbrBuilder.cs | 58 +- .../Execution/JobRunInformationService.cs | 46 +- .../Execution/JobRunProgressReceiver.cs | 48 +- source/Jobbr.Server/ConfigurationManager.cs | 88 +- source/Jobbr.Server/Core/JobRunService.cs | 107 +- source/Jobbr.Server/Core/TriggerService.cs | 99 +- .../JobRegistry/JobbrBuilderExtension.cs | 11 +- .../JobRegistry/RegistryBuilder.cs | 155 +- source/Jobbr.Server/Jobbr.Server.csproj | 4 +- source/Jobbr.Server/JobbrServer.cs | 184 +- .../Scheduling/DefaultScheduler.cs | 281 ++- .../Planer/RecurringJobRunPlaner.cs | 45 +- .../Jobbr.Server/Storage/JobbrRepository.cs | 107 +- .../JobRunService/ProgressChannelTests.cs | 6 +- .../Components/Scheduler/TestBase.cs | 6 +- .../Integration/JobbrServerTestBase.cs | 2 +- .../Startup/BadEnvironmentTests.cs | 6 +- .../Startup/ConfigurationValidationTests.cs | 8 +- .../Startup/SetupValidationTests.cs | 12 +- .../Jobbr.Tests/Registration/BuilderTests.cs | 24 +- source/JobbrRuleSet.ruleset | 11 +- 24 files changed, 771 insertions(+), 2544 deletions(-) delete mode 100644 source/Jobbr.Server/App_Packages/LibLog.3.1/LibLog.cs diff --git a/source/Jobbr.Server/App_Packages/LibLog.3.1/LibLog.cs b/source/Jobbr.Server/App_Packages/LibLog.3.1/LibLog.cs deleted file mode 100644 index 2e7a136..0000000 --- a/source/Jobbr.Server/App_Packages/LibLog.3.1/LibLog.cs +++ /dev/null @@ -1,1942 +0,0 @@ -// -//=============================================================================== -// LibLog -// -// https://github.com/damianh/LibLog -//=============================================================================== -// Copyright © 2011-2015 Damian Hickey. All rights reserved. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -//=============================================================================== - -// ReSharper disable PossibleNullReferenceException - -// Define LIBLOG_PORTABLE conditional compilation symbol for PCL compatibility - -#pragma warning disable 1591 - -namespace Jobbr.Server.Logging -{ - using System.Collections.Generic; - using Jobbr.Server.Logging.LogProviders; - using System; - using System.Diagnostics; - - /// - /// Simple interface that represent a logger. - /// - public interface ILog - { - /// - /// Log a message the specified log level. - /// - /// The log level. - /// The message function. - /// An optional exception. - /// Optional format parameters for the message generated by the messagefunc. - /// true if the message was logged. Otherwise false. - /// - /// Note to implementers: the message func should not be called if the loglevel is not enabled - /// so as not to incur performance penalties. - /// - /// To check IsEnabled call Log with only LogLevel and check the return value, no event will be written. - /// - bool Log(LogLevel logLevel, Func messageFunc, Exception exception = null, params object[] formatParameters ); - } - - /// - /// The log level. - /// - public enum LogLevel - { - Trace, - Debug, - Info, - Warn, - Error, - Fatal - } - - public static class LogExtensions - { - public static bool IsDebugEnabled(this ILog logger) - { - GuardAgainstNullLogger(logger); - return logger.Log(LogLevel.Debug, null); - } - - public static bool IsErrorEnabled(this ILog logger) - { - GuardAgainstNullLogger(logger); - return logger.Log(LogLevel.Error, null); - } - - public static bool IsFatalEnabled(this ILog logger) - { - GuardAgainstNullLogger(logger); - return logger.Log(LogLevel.Fatal, null); - } - - public static bool IsInfoEnabled(this ILog logger) - { - GuardAgainstNullLogger(logger); - return logger.Log(LogLevel.Info, null); - } - - public static bool IsTraceEnabled(this ILog logger) - { - GuardAgainstNullLogger(logger); - return logger.Log(LogLevel.Trace, null); - } - - public static bool IsWarnEnabled(this ILog logger) - { - GuardAgainstNullLogger(logger); - return logger.Log(LogLevel.Warn, null); - } - - public static void Debug(this ILog logger, Func messageFunc) - { - GuardAgainstNullLogger(logger); - logger.Log(LogLevel.Debug, messageFunc); - } - - public static void Debug(this ILog logger, string message) - { - if (logger.IsDebugEnabled()) - { - logger.Log(LogLevel.Debug, message.AsFunc()); - } - } - - public static void DebugFormat(this ILog logger, string message, params object[] args) - { - if (logger.IsDebugEnabled()) - { - logger.LogFormat(LogLevel.Debug, message, args); - } - } - - public static void DebugException(this ILog logger, string message, Exception exception) - { - if (logger.IsDebugEnabled()) - { - logger.Log(LogLevel.Debug, message.AsFunc(), exception); - } - } - - - public static void DebugException(this ILog logger, string message, Exception exception, params object[] formatParams) - { - if (logger.IsDebugEnabled()) - { - logger.Log(LogLevel.Debug, message.AsFunc(), exception, formatParams); - } - } - - public static void Error(this ILog logger, Func messageFunc) - { - logger.Log(LogLevel.Error, messageFunc); - } - - public static void Error(this ILog logger, string message) - { - if (logger.IsErrorEnabled()) - { - logger.Log(LogLevel.Error, message.AsFunc()); - } - } - - public static void ErrorFormat(this ILog logger, string message, params object[] args) - { - if (logger.IsErrorEnabled()) - { - logger.LogFormat(LogLevel.Error, message, args); - } - } - - public static void ErrorException(this ILog logger, string message, Exception exception, params object[] formatParams) - { - if (logger.IsErrorEnabled()) - { - logger.Log(LogLevel.Error, message.AsFunc(), exception, formatParams); - } - } - - public static void Fatal(this ILog logger, Func messageFunc) - { - logger.Log(LogLevel.Fatal, messageFunc); - } - - public static void Fatal(this ILog logger, string message) - { - if (logger.IsFatalEnabled()) - { - logger.Log(LogLevel.Fatal, message.AsFunc()); - } - } - - public static void FatalFormat(this ILog logger, string message, params object[] args) - { - if (logger.IsFatalEnabled()) - { - logger.LogFormat(LogLevel.Fatal, message, args); - } - } - - public static void FatalException(this ILog logger, string message, Exception exception, params object[] formatParams) - { - if (logger.IsFatalEnabled()) - { - logger.Log(LogLevel.Fatal, message.AsFunc(), exception, formatParams); - } - } - - public static void Info(this ILog logger, Func messageFunc) - { - GuardAgainstNullLogger(logger); - logger.Log(LogLevel.Info, messageFunc); - } - - public static void Info(this ILog logger, string message) - { - if (logger.IsInfoEnabled()) - { - logger.Log(LogLevel.Info, message.AsFunc()); - } - } - - public static void InfoFormat(this ILog logger, string message, params object[] args) - { - if (logger.IsInfoEnabled()) - { - logger.LogFormat(LogLevel.Info, message, args); - } - } - - public static void InfoException(this ILog logger, string message, Exception exception, params object[] formatParams) - { - if (logger.IsInfoEnabled()) - { - logger.Log(LogLevel.Info, message.AsFunc(), exception, formatParams); - } - } - - public static void Trace(this ILog logger, Func messageFunc) - { - GuardAgainstNullLogger(logger); - logger.Log(LogLevel.Trace, messageFunc); - } - - public static void Trace(this ILog logger, string message) - { - if (logger.IsTraceEnabled()) - { - logger.Log(LogLevel.Trace, message.AsFunc()); - } - } - - public static void TraceFormat(this ILog logger, string message, params object[] args) - { - if (logger.IsTraceEnabled()) - { - logger.LogFormat(LogLevel.Trace, message, args); - } - } - - public static void TraceException(this ILog logger, string message, Exception exception, params object[] formatParams) - { - if (logger.IsTraceEnabled()) - { - logger.Log(LogLevel.Trace, message.AsFunc(), exception, formatParams); - } - } - - public static void Warn(this ILog logger, Func messageFunc) - { - GuardAgainstNullLogger(logger); - logger.Log(LogLevel.Warn, messageFunc); - } - - public static void Warn(this ILog logger, string message) - { - if (logger.IsWarnEnabled()) - { - logger.Log(LogLevel.Warn, message.AsFunc()); - } - } - - public static void WarnFormat(this ILog logger, string message, params object[] args) - { - if (logger.IsWarnEnabled()) - { - logger.LogFormat(LogLevel.Warn, message, args); - } - } - - public static void WarnException(this ILog logger, string message, Exception exception, params object[] formatParams) - { - if (logger.IsWarnEnabled()) - { - logger.Log(LogLevel.Warn, message.AsFunc(), exception, formatParams); - } - } - - private static void GuardAgainstNullLogger(ILog logger) - { - if (logger == null) - { - throw new ArgumentNullException("logger"); - } - } - - private static void LogFormat(this ILog logger, LogLevel logLevel, string message, params object[] args) - { - logger.Log(logLevel, message.AsFunc(), null, args); - } - - // Avoid the closure allocation, see https://gist.github.com/AArnott/d285feef75c18f6ecd2b - private static Func AsFunc(this T value) where T : class - { - return value.Return; - } - - private static T Return(this T value) - { - return value; - } - } - - /// - /// Represents a way to get a - /// - public interface ILogProvider - { - /// - /// Gets the specified named logger. - /// - /// Name of the logger. - /// The logger reference. - ILog GetLogger(string name); - - /// - /// Opens a nested diagnostics context. Not supported in EntLib logging. - /// - /// The message to add to the diagnostics context. - /// A disposable that when disposed removes the message from the context. - IDisposable OpenNestedContext(string message); - - /// - /// Opens a mapped diagnostics context. Not supported in EntLib logging. - /// - /// A key. - /// A value. - /// A disposable that when disposed removes the map from the context. - IDisposable OpenMappedContext(string key, string value); - } - - /// - /// Provides a mechanism to create instances of objects. - /// - public static class LogProvider - { - private static ILogProvider _currentLogProvider; - private const string NullLogProvider = "Current Log Provider is not set. Call SetCurrentLogProvider " + - "with a non-null value first."; - - /// - /// Gets a logger for the specified type. - /// - /// The type whose name will be used for the logger. - /// An instance of - public static ILog For() - { - return GetLogger(typeof(T)); - } - -#if !LIBLOG_PORTABLE - /// - /// Gets a logger for the current class. - /// - /// An instance of - public static ILog GetCurrentClassLogger() - { - var stackFrame = new StackFrame(1, false); - return GetLogger(stackFrame.GetMethod().DeclaringType); - } -#endif - - /// - /// Gets a logger for the specified type. - /// - /// The type whose name will be used for the logger. - /// An instance of - public static ILog GetLogger(Type type) - { - return GetLogger(type.FullName); - } - - /// - /// Gets a logger with the specified name. - /// - /// The name. - /// An instance of - public static ILog GetLogger(string name) - { - ILogProvider logProvider = _currentLogProvider ?? ResolveLogProvider(); - return logProvider == null ? new NoOpLogger() : (ILog)new LoggerExecutionWrapper(logProvider.GetLogger(name)); - } - - /// - /// Sets the current log provider. - /// - /// The log provider. - public static void SetCurrentLogProvider(ILogProvider logProvider) - { - _currentLogProvider = logProvider; - } - - public static IDisposable OpenNestedConext(string message) - { - if(_currentLogProvider == null) - { - throw new InvalidOperationException(NullLogProvider); - } - return _currentLogProvider.OpenNestedContext(message); - } - - public static IDisposable OpenMappedContext(string key, string value) - { - if (_currentLogProvider == null) - { - throw new InvalidOperationException(NullLogProvider); - } - return _currentLogProvider.OpenMappedContext(key, value); - } - - public delegate bool IsLoggerAvailable(); - - public delegate ILogProvider CreateLogProvider(); - - public static readonly List> LogProviderResolvers = - new List> - { - new Tuple(SerilogLogProvider.IsLoggerAvailable, () => new SerilogLogProvider()), - new Tuple(NLogLogProvider.IsLoggerAvailable, () => new NLogLogProvider()), - new Tuple(Log4NetLogProvider.IsLoggerAvailable, () => new Log4NetLogProvider()), - new Tuple(EntLibLogProvider.IsLoggerAvailable, () => new EntLibLogProvider()), - new Tuple(LoupeLogProvider.IsLoggerAvailable, () => new LoupeLogProvider()), - new Tuple(ColouredConsoleLogProvider.IsLoggerAvailable, () => new ColouredConsoleLogProvider()), - }; - - private static ILogProvider ResolveLogProvider() - { - try - { - foreach (var providerResolver in LogProviderResolvers) - { - if (providerResolver.Item1()) - { - return providerResolver.Item2(); - } - } - } - catch (Exception ex) - { -#if LIBLOG_PORTABLE - Debug.WriteLine( -#else - Console.WriteLine( -#endif - "Exception occured resolving a log provider. Logging for this assembly {0} is disabled. {1}", - typeof(LogProvider).GetAssemblyPortable().FullName, - ex); - } - return null; - } - - internal class NoOpLogger : ILog - { - public bool Log(LogLevel logLevel, Func messageFunc, Exception exception, params object[] formatParameters) - { - return false; - } - } - } - - internal class LoggerExecutionWrapper : ILog - { - private readonly ILog _logger; - internal const string FailedToGenerateLogMessage = "Failed to generate log message"; - - internal LoggerExecutionWrapper(ILog logger) - { - _logger = logger; - } - - public ILog WrappedLogger - { - get { return _logger; } - } - - public bool Log(LogLevel logLevel, Func messageFunc, Exception exception = null, params object[] formatParameters) - { - if (messageFunc == null) - { - return _logger.Log(logLevel, null); - } - - Func wrappedMessageFunc = () => - { - try - { - return messageFunc(); - } - catch (Exception ex) - { - Log(LogLevel.Error, () => FailedToGenerateLogMessage, ex); - } - return null; - }; - return _logger.Log(logLevel, wrappedMessageFunc, exception, formatParameters); - } - } -} - -namespace Jobbr.Server.Logging.LogProviders -{ - using System; - using System.Collections.Generic; - using System.Globalization; - using System.Linq.Expressions; - using System.Reflection; - using System.Text; - using System.Text.RegularExpressions; - - internal abstract class LogProviderBase : ILogProvider - { - protected delegate IDisposable OpenNdc(string message); - protected delegate IDisposable OpenMdc(string key, string value); - - private readonly Lazy _lazyOpenNdcMethod; - private readonly Lazy _lazyOpenMdcMethod; - private static readonly IDisposable NoopDisposableInstance = new DisposableAction(); - - protected LogProviderBase() - { - _lazyOpenNdcMethod - = new Lazy(GetOpenNdcMethod); - _lazyOpenMdcMethod - = new Lazy(GetOpenMdcMethod); - } - - public abstract ILog GetLogger(string name); - - public IDisposable OpenNestedContext(string message) - { - return _lazyOpenNdcMethod.Value(message); - } - - public IDisposable OpenMappedContext(string key, string value) - { - return _lazyOpenMdcMethod.Value(key, value); - } - - protected virtual OpenNdc GetOpenNdcMethod() - { - return _ => NoopDisposableInstance; - } - - protected virtual OpenMdc GetOpenMdcMethod() - { - return (_, __) => NoopDisposableInstance; - } - } - - internal class NLogLogProvider : LogProviderBase - { - private readonly Func _getLoggerByNameDelegate; - private static bool _providerIsAvailableOverride = true; - - public NLogLogProvider() - { - if (!IsLoggerAvailable()) - { - throw new InvalidOperationException("NLog.LogManager not found"); - } - _getLoggerByNameDelegate = GetGetLoggerMethodCall(); - } - - public static bool ProviderIsAvailableOverride - { - get { return _providerIsAvailableOverride; } - set { _providerIsAvailableOverride = value; } - } - - public override ILog GetLogger(string name) - { - return new NLogLogger(_getLoggerByNameDelegate(name)); - } - - public static bool IsLoggerAvailable() - { - return ProviderIsAvailableOverride && GetLogManagerType() != null; - } - - protected override OpenNdc GetOpenNdcMethod() - { - Type ndcContextType = Type.GetType("NLog.NestedDiagnosticsContext, NLog"); - MethodInfo pushMethod = ndcContextType.GetMethodPortable("Push", new[] { typeof(string) }); - ParameterExpression messageParam = Expression.Parameter(typeof(string), "message"); - MethodCallExpression pushMethodCall = Expression.Call(null, pushMethod, messageParam); - return Expression.Lambda(pushMethodCall, messageParam).Compile(); - } - - protected override OpenMdc GetOpenMdcMethod() - { - Type mdcContextType = Type.GetType("NLog.MappedDiagnosticsContext, NLog"); - - MethodInfo setMethod = mdcContextType.GetMethodPortable("Set", new[] { typeof(string), typeof(string) }); - MethodInfo removeMethod = mdcContextType.GetMethodPortable("Remove", new[] { typeof(string) }); - ParameterExpression keyParam = Expression.Parameter(typeof(string), "key"); - ParameterExpression valueParam = Expression.Parameter(typeof(string), "value"); - - MethodCallExpression setMethodCall = Expression.Call(null, setMethod, keyParam, valueParam); - MethodCallExpression removeMethodCall = Expression.Call(null, removeMethod, keyParam); - - Action set = Expression - .Lambda>(setMethodCall, keyParam, valueParam) - .Compile(); - Action remove = Expression - .Lambda>(removeMethodCall, keyParam) - .Compile(); - - return (key, value) => - { - set(key, value); - return new DisposableAction(() => remove(key)); - }; - } - - private static Type GetLogManagerType() - { - return Type.GetType("NLog.LogManager, NLog"); - } - - private static Func GetGetLoggerMethodCall() - { - Type logManagerType = GetLogManagerType(); - MethodInfo method = logManagerType.GetMethodPortable("GetLogger", new[] { typeof(string) }); - ParameterExpression nameParam = Expression.Parameter(typeof(string), "name"); - MethodCallExpression methodCall = Expression.Call(null, method, nameParam); - return Expression.Lambda>(methodCall, nameParam).Compile(); - } - - public class NLogLogger : ILog - { - private readonly dynamic _logger; - - internal NLogLogger(dynamic logger) - { - _logger = logger; - } - - public bool Log(LogLevel logLevel, Func messageFunc, Exception exception, params object[] formatParameters) - { - if (messageFunc == null) - { - return IsLogLevelEnable(logLevel); - } - messageFunc = LogMessageFormatter.SimulateStructuredLogging(messageFunc, formatParameters); - - if(exception != null) - { - return LogException(logLevel, messageFunc, exception); - } - switch (logLevel) - { - case LogLevel.Debug: - if (_logger.IsDebugEnabled) - { - _logger.Debug(messageFunc()); - return true; - } - break; - case LogLevel.Info: - if (_logger.IsInfoEnabled) - { - _logger.Info(messageFunc()); - return true; - } - break; - case LogLevel.Warn: - if (_logger.IsWarnEnabled) - { - _logger.Warn(messageFunc()); - return true; - } - break; - case LogLevel.Error: - if (_logger.IsErrorEnabled) - { - _logger.Error(messageFunc()); - return true; - } - break; - case LogLevel.Fatal: - if (_logger.IsFatalEnabled) - { - _logger.Fatal(messageFunc()); - return true; - } - break; - default: - if (_logger.IsTraceEnabled) - { - _logger.Trace(messageFunc()); - return true; - } - break; - } - return false; - } - - private bool LogException(LogLevel logLevel, Func messageFunc, Exception exception) - { - switch (logLevel) - { - case LogLevel.Debug: - if (_logger.IsDebugEnabled) - { - _logger.DebugException(messageFunc(), exception); - return true; - } - break; - case LogLevel.Info: - if (_logger.IsInfoEnabled) - { - _logger.InfoException(messageFunc(), exception); - return true; - } - break; - case LogLevel.Warn: - if (_logger.IsWarnEnabled) - { - _logger.WarnException(messageFunc(), exception); - return true; - } - break; - case LogLevel.Error: - if (_logger.IsErrorEnabled) - { - _logger.ErrorException(messageFunc(), exception); - return true; - } - break; - case LogLevel.Fatal: - if (_logger.IsFatalEnabled) - { - _logger.FatalException(messageFunc(), exception); - return true; - } - break; - default: - if (_logger.IsTraceEnabled) - { - _logger.TraceException(messageFunc(), exception); - return true; - } - break; - } - return false; - } - - private bool IsLogLevelEnable(LogLevel logLevel) - { - switch (logLevel) - { - case LogLevel.Debug: - return _logger.IsDebugEnabled; - case LogLevel.Info: - return _logger.IsInfoEnabled; - case LogLevel.Warn: - return _logger.IsWarnEnabled; - case LogLevel.Error: - return _logger.IsErrorEnabled; - case LogLevel.Fatal: - return _logger.IsFatalEnabled; - default: - return _logger.IsTraceEnabled; - } - } - } - } - - internal class Log4NetLogProvider : LogProviderBase - { - private readonly Func _getLoggerByNameDelegate; - private static bool _providerIsAvailableOverride = true; - - public Log4NetLogProvider() - { - if (!IsLoggerAvailable()) - { - throw new InvalidOperationException("log4net.LogManager not found"); - } - _getLoggerByNameDelegate = GetGetLoggerMethodCall(); - } - - public static bool ProviderIsAvailableOverride - { - get { return _providerIsAvailableOverride; } - set { _providerIsAvailableOverride = value; } - } - - public override ILog GetLogger(string name) - { - return new Log4NetLogger(_getLoggerByNameDelegate(name)); - } - - internal static bool IsLoggerAvailable() - { - return ProviderIsAvailableOverride && GetLogManagerType() != null; - } - - protected override OpenNdc GetOpenNdcMethod() - { - Type ndcContextType = Type.GetType("log4net.NDC, log4net"); - MethodInfo pushMethod = ndcContextType.GetMethodPortable("Push", new[] { typeof(string) }); - ParameterExpression messageParam = Expression.Parameter(typeof(string), "message"); - MethodCallExpression pushMethodCall = Expression.Call(null, pushMethod, messageParam); - return Expression.Lambda(pushMethodCall, messageParam).Compile(); - } - - protected override OpenMdc GetOpenMdcMethod() - { - Type mdcContextType = Type.GetType("log4net.MDC, log4net"); - - MethodInfo setMethod = mdcContextType.GetMethodPortable("Set", new[] { typeof(string), typeof(string) }); - MethodInfo removeMethod = mdcContextType.GetMethodPortable("Remove", new[] { typeof(string) }); - ParameterExpression keyParam = Expression.Parameter(typeof(string), "key"); - ParameterExpression valueParam = Expression.Parameter(typeof(string), "value"); - - MethodCallExpression setMethodCall = Expression.Call(null, setMethod, keyParam, valueParam); - MethodCallExpression removeMethodCall = Expression.Call(null, removeMethod, keyParam); - - Action set = Expression - .Lambda>(setMethodCall, keyParam, valueParam) - .Compile(); - Action remove = Expression - .Lambda>(removeMethodCall, keyParam) - .Compile(); - - return (key, value) => - { - set(key, value); - return new DisposableAction(() => remove(key)); - }; - } - - private static Type GetLogManagerType() - { - return Type.GetType("log4net.LogManager, log4net"); - } - - private static Func GetGetLoggerMethodCall() - { - Type logManagerType = GetLogManagerType(); - MethodInfo method = logManagerType.GetMethodPortable("GetLogger", new[] { typeof(string) }); - ParameterExpression nameParam = Expression.Parameter(typeof(string), "name"); - MethodCallExpression methodCall = Expression.Call(null, method, nameParam); - return Expression.Lambda>(methodCall, nameParam).Compile(); - } - - public class Log4NetLogger : ILog - { - private readonly dynamic _logger; - - internal Log4NetLogger(dynamic logger) - { - _logger = logger; - } - - public bool Log(LogLevel logLevel, Func messageFunc, Exception exception, params object[] formatParameters) - { - if (messageFunc == null) - { - return IsLogLevelEnable(logLevel); - } - - messageFunc = LogMessageFormatter.SimulateStructuredLogging(messageFunc, formatParameters); - - if (exception != null) - { - return LogException(logLevel, messageFunc, exception); - } - switch (logLevel) - { - case LogLevel.Info: - if (_logger.IsInfoEnabled) - { - _logger.Info(messageFunc()); - return true; - } - break; - case LogLevel.Warn: - if (_logger.IsWarnEnabled) - { - _logger.Warn(messageFunc()); - return true; - } - break; - case LogLevel.Error: - if (_logger.IsErrorEnabled) - { - _logger.Error(messageFunc()); - return true; - } - break; - case LogLevel.Fatal: - if (_logger.IsFatalEnabled) - { - _logger.Fatal(messageFunc()); - return true; - } - break; - default: - if (_logger.IsDebugEnabled) - { - _logger.Debug(messageFunc()); // Log4Net doesn't have a 'Trace' level, so all Trace messages are written as 'Debug' - return true; - } - break; - } - return false; - } - - private bool LogException(LogLevel logLevel, Func messageFunc, Exception exception) - { - switch (logLevel) - { - case LogLevel.Info: - if (_logger.IsDebugEnabled) - { - _logger.Info(messageFunc(), exception); - return true; - } - break; - case LogLevel.Warn: - if (_logger.IsWarnEnabled) - { - _logger.Warn(messageFunc(), exception); - return true; - } - break; - case LogLevel.Error: - if (_logger.IsErrorEnabled) - { - _logger.Error(messageFunc(), exception); - return true; - } - break; - case LogLevel.Fatal: - if (_logger.IsFatalEnabled) - { - _logger.Fatal(messageFunc(), exception); - return true; - } - break; - default: - if (_logger.IsDebugEnabled) - { - _logger.Debug(messageFunc(), exception); - return true; - } - break; - } - return false; - } - - private bool IsLogLevelEnable(LogLevel logLevel) - { - switch (logLevel) - { - case LogLevel.Debug: - return _logger.IsDebugEnabled; - case LogLevel.Info: - return _logger.IsInfoEnabled; - case LogLevel.Warn: - return _logger.IsWarnEnabled; - case LogLevel.Error: - return _logger.IsErrorEnabled; - case LogLevel.Fatal: - return _logger.IsFatalEnabled; - default: - return _logger.IsDebugEnabled; - } - } - } - } - - internal class EntLibLogProvider : LogProviderBase - { - private const string TypeTemplate = "Microsoft.Practices.EnterpriseLibrary.Logging.{0}, Microsoft.Practices.EnterpriseLibrary.Logging"; - private static bool _providerIsAvailableOverride = true; - private static readonly Type LogEntryType; - private static readonly Type LoggerType; - private static readonly Type TraceEventTypeType; - private static readonly Action WriteLogEntry; - private static readonly Func ShouldLogEntry; - - static EntLibLogProvider() - { - LogEntryType = Type.GetType(string.Format(TypeTemplate, "LogEntry")); - LoggerType = Type.GetType(string.Format(TypeTemplate, "Logger")); - TraceEventTypeType = TraceEventTypeValues.Type; - if (LogEntryType == null - || TraceEventTypeType == null - || LoggerType == null) - { - return; - } - WriteLogEntry = GetWriteLogEntry(); - ShouldLogEntry = GetShouldLogEntry(); - } - - public EntLibLogProvider() - { - if (!IsLoggerAvailable()) - { - throw new InvalidOperationException("Microsoft.Practices.EnterpriseLibrary.Logging.Logger not found"); - } - } - - public static bool ProviderIsAvailableOverride - { - get { return _providerIsAvailableOverride; } - set { _providerIsAvailableOverride = value; } - } - - public override ILog GetLogger(string name) - { - return new EntLibLogger(name, WriteLogEntry, ShouldLogEntry); - } - - internal static bool IsLoggerAvailable() - { - return ProviderIsAvailableOverride - && TraceEventTypeType != null - && LogEntryType != null; - } - - private static Action GetWriteLogEntry() - { - // new LogEntry(...) - var logNameParameter = Expression.Parameter(typeof(string), "logName"); - var messageParameter = Expression.Parameter(typeof(string), "message"); - var severityParameter = Expression.Parameter(typeof(int), "severity"); - - MemberInitExpression memberInit = GetWriteLogExpression( - messageParameter, - Expression.Convert(severityParameter, TraceEventTypeType), - logNameParameter); - - //Logger.Write(new LogEntry(....)); - MethodInfo writeLogEntryMethod = LoggerType.GetMethodPortable("Write", new[] { LogEntryType }); - var writeLogEntryExpression = Expression.Call(writeLogEntryMethod, memberInit); - - return Expression.Lambda>( - writeLogEntryExpression, - logNameParameter, - messageParameter, - severityParameter).Compile(); - } - - private static Func GetShouldLogEntry() - { - // new LogEntry(...) - var logNameParameter = Expression.Parameter(typeof(string), "logName"); - var severityParameter = Expression.Parameter(typeof(int), "severity"); - - MemberInitExpression memberInit = GetWriteLogExpression( - Expression.Constant("***dummy***"), - Expression.Convert(severityParameter, TraceEventTypeType), - logNameParameter); - - //Logger.Write(new LogEntry(....)); - MethodInfo writeLogEntryMethod = LoggerType.GetMethodPortable("ShouldLog", new[] { LogEntryType }); - var writeLogEntryExpression = Expression.Call(writeLogEntryMethod, memberInit); - - return Expression.Lambda>( - writeLogEntryExpression, - logNameParameter, - severityParameter).Compile(); - } - - private static MemberInitExpression GetWriteLogExpression(Expression message, - Expression severityParameter, ParameterExpression logNameParameter) - { - var entryType = LogEntryType; - MemberInitExpression memberInit = Expression.MemberInit(Expression.New(entryType), new [] - { - Expression.Bind(entryType.GetPropertyPortable("Message"), message), - Expression.Bind(entryType.GetPropertyPortable("Severity"), severityParameter), - Expression.Bind(entryType.GetPropertyPortable("TimeStamp"), - Expression.Property(null, typeof (DateTime).GetPropertyPortable("UtcNow"))), - Expression.Bind(entryType.GetPropertyPortable("Categories"), - Expression.ListInit( - Expression.New(typeof (List)), - typeof (List).GetMethodPortable("Add", new[] {typeof (string)}), - logNameParameter)) - }); - return memberInit; - } - - public class EntLibLogger : ILog - { - private readonly string _loggerName; - private readonly Action _writeLog; - private readonly Func _shouldLog; - - internal EntLibLogger(string loggerName, Action writeLog, Func shouldLog) - { - _loggerName = loggerName; - _writeLog = writeLog; - _shouldLog = shouldLog; - } - - public bool Log(LogLevel logLevel, Func messageFunc, Exception exception, params object[] formatParameters) - { - var severity = MapSeverity(logLevel); - if (messageFunc == null) - { - return _shouldLog(_loggerName, severity); - } - - - messageFunc = LogMessageFormatter.SimulateStructuredLogging(messageFunc, formatParameters); - if (exception != null) - { - return LogException(logLevel, messageFunc, exception); - } - _writeLog(_loggerName, messageFunc(), severity); - return true; - } - - public bool LogException(LogLevel logLevel, Func messageFunc, Exception exception) - { - var severity = MapSeverity(logLevel); - var message = messageFunc() + Environment.NewLine + exception; - _writeLog(_loggerName, message, severity); - return true; - } - - private static int MapSeverity(LogLevel logLevel) - { - switch (logLevel) - { - case LogLevel.Fatal: - return TraceEventTypeValues.Critical; - case LogLevel.Error: - return TraceEventTypeValues.Error; - case LogLevel.Warn: - return TraceEventTypeValues.Warning; - case LogLevel.Info: - return TraceEventTypeValues.Information; - default: - return TraceEventTypeValues.Verbose; - } - } - } - } - - internal class SerilogLogProvider : LogProviderBase - { - private readonly Func _getLoggerByNameDelegate; - private static bool _providerIsAvailableOverride = true; - - public SerilogLogProvider() - { - if (!IsLoggerAvailable()) - { - throw new InvalidOperationException("Serilog.Log not found"); - } - _getLoggerByNameDelegate = GetForContextMethodCall(); - } - - public static bool ProviderIsAvailableOverride - { - get { return _providerIsAvailableOverride; } - set { _providerIsAvailableOverride = value; } - } - - public override ILog GetLogger(string name) - { - return new SerilogLogger(_getLoggerByNameDelegate(name)); - } - - internal static bool IsLoggerAvailable() - { - return ProviderIsAvailableOverride && GetLogManagerType() != null; - } - - protected override OpenNdc GetOpenNdcMethod() - { - return message => GetPushProperty()("NDC", message); - } - - protected override OpenMdc GetOpenMdcMethod() - { - return (key, value) => GetPushProperty()(key, value); - } - - private static Func GetPushProperty() - { - Type ndcContextType = Type.GetType("Serilog.Context.LogContext, Serilog.FullNetFx"); - MethodInfo pushPropertyMethod = ndcContextType.GetMethodPortable( - "PushProperty", - new[] - { - typeof(string), - typeof(object), - typeof(bool) - }); - ParameterExpression nameParam = Expression.Parameter(typeof(string), "name"); - ParameterExpression valueParam = Expression.Parameter(typeof(object), "value"); - ParameterExpression destructureObjectParam = Expression.Parameter(typeof(bool), "destructureObjects"); - MethodCallExpression pushPropertyMethodCall = Expression - .Call(null, pushPropertyMethod, nameParam, valueParam, destructureObjectParam); - var pushProperty = Expression - .Lambda>( - pushPropertyMethodCall, - nameParam, - valueParam, - destructureObjectParam) - .Compile(); - - return (key, value) => pushProperty(key, value, false); - } - - private static Type GetLogManagerType() - { - return Type.GetType("Serilog.Log, Serilog"); - } - - private static Func GetForContextMethodCall() - { - Type logManagerType = GetLogManagerType(); - MethodInfo method = logManagerType.GetMethodPortable("ForContext", new[] { typeof(string), typeof(object), typeof(bool) }); - ParameterExpression propertyNameParam = Expression.Parameter(typeof(string), "propertyName"); - ParameterExpression valueParam = Expression.Parameter(typeof(object), "value"); - ParameterExpression destructureObjectsParam = Expression.Parameter(typeof(bool), "destructureObjects"); - MethodCallExpression methodCall = Expression.Call(null, method, new Expression[] - { - propertyNameParam, - valueParam, - destructureObjectsParam - }); - var func = Expression.Lambda>( - methodCall, - propertyNameParam, - valueParam, - destructureObjectsParam) - .Compile(); - return name => func("Name", name, false); - } - - public class SerilogLogger : ILog - { - private readonly object _logger; - private static readonly object DebugLevel; - private static readonly object ErrorLevel; - private static readonly object FatalLevel; - private static readonly object InformationLevel; - private static readonly object VerboseLevel; - private static readonly object WarningLevel; - private static readonly Func IsEnabled; - private static readonly Action Write; - private static readonly Action WriteException; - - static SerilogLogger() - { - var logEventTypeType = Type.GetType("Serilog.Events.LogEventLevel, Serilog"); - DebugLevel = Enum.Parse(logEventTypeType, "Debug", false); - ErrorLevel = Enum.Parse(logEventTypeType, "Error", false); - FatalLevel = Enum.Parse(logEventTypeType, "Fatal", false); - InformationLevel = Enum.Parse(logEventTypeType, "Information", false); - VerboseLevel = Enum.Parse(logEventTypeType, "Verbose", false); - WarningLevel = Enum.Parse(logEventTypeType, "Warning", false); - - // Func isEnabled = (logger, level) => { return ((SeriLog.ILogger)logger).IsEnabled(level); } - var loggerType = Type.GetType("Serilog.ILogger, Serilog"); - var logEventLevelType = Type.GetType("Serilog.Events.LogEventLevel, Serilog"); - MethodInfo isEnabledMethodInfo = loggerType.GetMethodPortable("IsEnabled", logEventLevelType); - ParameterExpression instanceParam = Expression.Parameter(typeof(object)); - UnaryExpression instanceCast = Expression.Convert(instanceParam, loggerType); - ParameterExpression levelParam = Expression.Parameter(typeof(object)); - UnaryExpression levelCast = Expression.Convert(levelParam, logEventTypeType); - MethodCallExpression isEnabledMethodCall = Expression.Call(instanceCast, isEnabledMethodInfo, levelCast); - IsEnabled = Expression.Lambda>(isEnabledMethodCall, instanceParam, levelParam).Compile(); - - // Action Write = - // (logger, level, message, params) => { ((SeriLog.ILoggerILogger)logger).Write(level, message, params); } - MethodInfo writeMethodInfo = loggerType.GetMethodPortable("Write", new[] { logEventTypeType, typeof(string), typeof(object[]) }); - ParameterExpression messageParam = Expression.Parameter(typeof(string)); - ParameterExpression propertyValuesParam = Expression.Parameter(typeof(object[])); - MethodCallExpression writeMethodExp = Expression.Call(instanceCast, writeMethodInfo, levelCast, messageParam, propertyValuesParam); - var expression = Expression.Lambda>( - writeMethodExp, - instanceParam, - levelParam, - messageParam, - propertyValuesParam); - Write = expression.Compile(); - - // Action WriteException = - // (logger, level, exception, message) => { ((ILogger)logger).Write(level, exception, message, new object[]); } - MethodInfo writeExceptionMethodInfo = loggerType.GetMethodPortable("Write", new[] - { - logEventTypeType, - typeof(Exception), - typeof(string), - typeof(object[]) - }); - ParameterExpression exceptionParam = Expression.Parameter(typeof(Exception)); - writeMethodExp = Expression.Call( - instanceCast, - writeExceptionMethodInfo, - levelCast, - exceptionParam, - messageParam, - propertyValuesParam); - WriteException = Expression.Lambda>( - writeMethodExp, - instanceParam, - levelParam, - exceptionParam, - messageParam, - propertyValuesParam).Compile(); - } - - internal SerilogLogger(object logger) - { - _logger = logger; - } - - public bool Log(LogLevel logLevel, Func messageFunc, Exception exception, params object[] formatParameters) - { - if (messageFunc == null) - { - return IsEnabled(_logger, logLevel); - } - if (exception != null) - { - return LogException(logLevel, messageFunc, exception, formatParameters); - } - - switch (logLevel) - { - case LogLevel.Debug: - if (IsEnabled(_logger, DebugLevel)) - { - Write(_logger, DebugLevel, messageFunc(), formatParameters); - return true; - } - break; - case LogLevel.Info: - if (IsEnabled(_logger, InformationLevel)) - { - Write(_logger, InformationLevel, messageFunc(), formatParameters); - return true; - } - break; - case LogLevel.Warn: - if (IsEnabled(_logger, WarningLevel)) - { - Write(_logger, WarningLevel, messageFunc(), formatParameters); - return true; - } - break; - case LogLevel.Error: - if (IsEnabled(_logger, ErrorLevel)) - { - Write(_logger, ErrorLevel, messageFunc(), formatParameters); - return true; - } - break; - case LogLevel.Fatal: - if (IsEnabled(_logger, FatalLevel)) - { - Write(_logger, FatalLevel, messageFunc(), formatParameters); - return true; - } - break; - default: - if (IsEnabled(_logger, VerboseLevel)) - { - Write(_logger, VerboseLevel, messageFunc(), formatParameters); - return true; - } - break; - } - return false; - } - - private bool LogException(LogLevel logLevel, Func messageFunc, Exception exception, object[] formatParams) - { - switch (logLevel) - { - case LogLevel.Debug: - if (IsEnabled(_logger, DebugLevel)) - { - WriteException(_logger, DebugLevel, exception, messageFunc(), formatParams); - return true; - } - break; - case LogLevel.Info: - if (IsEnabled(_logger, InformationLevel)) - { - WriteException(_logger, InformationLevel, exception, messageFunc(), formatParams); - return true; - } - break; - case LogLevel.Warn: - if (IsEnabled(_logger, WarningLevel)) - { - WriteException(_logger, WarningLevel, exception, messageFunc(), formatParams); - return true; - } - break; - case LogLevel.Error: - if (IsEnabled(_logger, ErrorLevel)) - { - WriteException(_logger, ErrorLevel, exception, messageFunc(), formatParams); - return true; - } - break; - case LogLevel.Fatal: - if (IsEnabled(_logger, FatalLevel)) - { - WriteException(_logger, FatalLevel, exception, messageFunc(), formatParams); - return true; - } - break; - default: - if (IsEnabled(_logger, VerboseLevel)) - { - WriteException(_logger, VerboseLevel, exception, messageFunc(), formatParams); - return true; - } - break; - } - return false; - } - } - } - - internal class LoupeLogProvider : LogProviderBase - { - /// - /// The form of the Loupe Log.Write method we're using - /// - internal delegate void WriteDelegate( - int severity, - string logSystem, - int skipFrames, - Exception exception, - bool attributeToException, - int writeMode, - string detailsXml, - string category, - string caption, - string description, - params object[] args - ); - - private static bool _providerIsAvailableOverride = true; - private readonly WriteDelegate _logWriteDelegate; - - public LoupeLogProvider() - { - if (!IsLoggerAvailable()) - { - throw new InvalidOperationException("Gibraltar.Agent.Log (Loupe) not found"); - } - - _logWriteDelegate = GetLogWriteDelegate(); - } - - /// - /// Gets or sets a value indicating whether [provider is available override]. Used in tests. - /// - /// - /// true if [provider is available override]; otherwise, false. - /// - public static bool ProviderIsAvailableOverride - { - get { return _providerIsAvailableOverride; } - set { _providerIsAvailableOverride = value; } - } - - public override ILog GetLogger(string name) - { - return new LoupeLogger(name, _logWriteDelegate); - } - - public static bool IsLoggerAvailable() - { - return ProviderIsAvailableOverride && GetLogManagerType() != null; - } - - private static Type GetLogManagerType() - { - return Type.GetType("Gibraltar.Agent.Log, Gibraltar.Agent"); - } - - private static WriteDelegate GetLogWriteDelegate() - { - Type logManagerType = GetLogManagerType(); - Type logMessageSeverityType = Type.GetType("Gibraltar.Agent.LogMessageSeverity, Gibraltar.Agent"); - Type logWriteModeType = Type.GetType("Gibraltar.Agent.LogWriteMode, Gibraltar.Agent"); - - MethodInfo method = logManagerType.GetMethodPortable( - "Write", - new[] - { - logMessageSeverityType, typeof(string), typeof(int), typeof(Exception), typeof(bool), - logWriteModeType, typeof(string), typeof(string), typeof(string), typeof(string), typeof(object[]) - }); - - var callDelegate = (WriteDelegate)method.CreateDelegate(typeof(WriteDelegate)); - return callDelegate; - } - - public class LoupeLogger : ILog - { - private const string LogSystem = "LibLog"; - - private readonly string _category; - private readonly WriteDelegate _logWriteDelegate; - private readonly int _skipLevel; - - internal LoupeLogger(string category, WriteDelegate logWriteDelegate) - { - _category = category; - _logWriteDelegate = logWriteDelegate; - _skipLevel = 1; - } - - public bool Log(LogLevel logLevel, Func messageFunc, Exception exception, params object[] formatParameters) - { - if (messageFunc == null) - { - //nothing to log.. - return true; - } - - messageFunc = LogMessageFormatter.SimulateStructuredLogging(messageFunc, formatParameters); - - _logWriteDelegate(ToLogMessageSeverity(logLevel), LogSystem, _skipLevel, exception, true, 0, null, - _category, null, messageFunc.Invoke()); - - return true; - } - - private int ToLogMessageSeverity(LogLevel logLevel) - { - switch (logLevel) - { - case LogLevel.Trace: - return TraceEventTypeValues.Verbose; - case LogLevel.Debug: - return TraceEventTypeValues.Verbose; - case LogLevel.Info: - return TraceEventTypeValues.Information; - case LogLevel.Warn: - return TraceEventTypeValues.Warning; - case LogLevel.Error: - return TraceEventTypeValues.Error; - case LogLevel.Fatal: - return TraceEventTypeValues.Critical; - default: - throw new ArgumentOutOfRangeException("logLevel"); - } - } - } - } - - internal static class TraceEventTypeValues - { - internal static readonly Type Type; - internal static readonly int Verbose; - internal static readonly int Information; - internal static readonly int Warning; - internal static readonly int Error; - internal static readonly int Critical; - - static TraceEventTypeValues() - { - var assembly = typeof(Uri).GetAssemblyPortable(); // This is to get to the System.dll assembly in a PCL compatible way. - if (assembly == null) - { - return; - } - Type = assembly.GetType("System.Diagnostics.TraceEventType"); - if (Type == null) return; - Verbose = (int)Enum.Parse(Type, "Verbose", false); - Information = (int)Enum.Parse(Type, "Information", false); - Warning = (int)Enum.Parse(Type, "Warning", false); - Error = (int)Enum.Parse(Type, "Error", false); - Critical = (int)Enum.Parse(Type, "Critical", false); - } - } - - internal class ColouredConsoleLogProvider : LogProviderBase - { - private static readonly Type ConsoleType; - private static readonly Type ConsoleColorType; - private static readonly Action ConsoleWriteLine; - private static readonly Func GetConsoleForeground; - private static readonly Action SetConsoleForeground; - private static bool _providerIsAvailableOverride = true; - private static readonly IDictionary Colors; - - static ColouredConsoleLogProvider() - { - ConsoleType = Type.GetType("System.Console"); - ConsoleColorType = ConsoleColorValues.Type; - - if (!IsLoggerAvailable()) - { - throw new InvalidOperationException("System.Console or System.ConsoleColor type not found"); - } - - MessageFormatter = DefaultMessageFormatter; - Colors = new Dictionary - { - {LogLevel.Fatal, ConsoleColorValues.Red}, - {LogLevel.Error, ConsoleColorValues.Yellow}, - {LogLevel.Warn, ConsoleColorValues.Magenta}, - {LogLevel.Info, ConsoleColorValues.White}, - {LogLevel.Debug, ConsoleColorValues.Gray}, - {LogLevel.Trace, ConsoleColorValues.DarkGray}, - }; - ConsoleWriteLine = GetConsoleWrite(); - GetConsoleForeground = GetGetConsoleForeground(); - SetConsoleForeground = GetSetConsoleForeground(); - } - - internal static bool IsLoggerAvailable() - { - return ProviderIsAvailableOverride && ConsoleType != null && ConsoleColorType != null; - } - - public override ILog GetLogger(string name) - { - return new ColouredConsoleLogger(name, ConsoleWriteLine, GetConsoleForeground, SetConsoleForeground); - } - - /// - /// A delegate returning a formatted log message - /// - /// The name of the Logger - /// The Log Level - /// The Log Message - /// The Exception, if there is one - /// A formatted Log Message string. - internal delegate string MessageFormatterDelegate( - string loggerName, - LogLevel level, - object message, - Exception e); - - internal static MessageFormatterDelegate MessageFormatter { get; set; } - - public static bool ProviderIsAvailableOverride - { - get { return _providerIsAvailableOverride; } - set { _providerIsAvailableOverride = value; } - } - - protected static string DefaultMessageFormatter(string loggerName, LogLevel level, object message, Exception e) - { - var stringBuilder = new StringBuilder(); - stringBuilder.Append(DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss", CultureInfo.InvariantCulture)); - stringBuilder.Append(" "); - - // Append a readable representation of the log level - stringBuilder.Append(("[" + level.ToString().ToUpper() + "]").PadRight(8)); - stringBuilder.Append("(" + loggerName + ") "); - - // Append the message - stringBuilder.Append(message); - - // Append stack trace if there is an exception - if (e != null) - { - stringBuilder.Append(Environment.NewLine).Append(e.GetType()); - stringBuilder.Append(Environment.NewLine).Append(e.Message); - stringBuilder.Append(Environment.NewLine).Append(e.StackTrace); - } - - return stringBuilder.ToString(); - } - - private static Action GetConsoleWrite() - { - var messageParameter = Expression.Parameter(typeof(string), "message"); - - MethodInfo writeMethod = ConsoleType.GetMethodPortable("WriteLine", new[] { typeof(string) }); - var writeExpression = Expression.Call(writeMethod, messageParameter); - - return Expression.Lambda>( - writeExpression, messageParameter).Compile(); - } - - private static Func GetGetConsoleForeground() - { - MethodInfo getForeground = ConsoleType.GetPropertyPortable("ForegroundColor").GetGetMethod(); - var getForegroundExpression = Expression.Convert(Expression.Call(getForeground), typeof(int)); - - return Expression.Lambda>(getForegroundExpression).Compile(); - } - - private static Action GetSetConsoleForeground() - { - var colorParameter = Expression.Parameter(typeof(int), "color"); - - MethodInfo setForeground = ConsoleType.GetPropertyPortable("ForegroundColor").GetSetMethod(); - var setForegroundExpression = Expression.Call(setForeground, - Expression.Convert(colorParameter, ConsoleColorType)); - - return Expression.Lambda>( - setForegroundExpression, colorParameter).Compile(); - } - - public class ColouredConsoleLogger : ILog - { - private readonly string _name; - private readonly Action _write; - private readonly Func _getForeground; - private readonly Action _setForeground; - - public ColouredConsoleLogger(string name, Action write, - Func getForeground, Action setForeground) - { - _name = name; - _write = write; - _getForeground = getForeground; - _setForeground = setForeground; - } - - public bool Log(LogLevel logLevel, Func messageFunc, Exception exception, - params object[] formatParameters) - { - if (messageFunc == null) - { - return true; - } - - messageFunc = LogMessageFormatter.SimulateStructuredLogging(messageFunc, formatParameters); - - Write(logLevel, messageFunc(), exception); - return true; - } - - protected void Write(LogLevel logLevel, string message, Exception e = null) - { - var formattedMessage = MessageFormatter(this._name, logLevel, message, e); - int color; - - if (Colors.TryGetValue(logLevel, out color)) - { - var originalColor = _getForeground(); - try - { - _setForeground(color); - _write(formattedMessage); - } - finally - { - _setForeground(originalColor); - } - } - else - { - _write(formattedMessage); - } - } - } - - private static class ConsoleColorValues - { - internal static readonly Type Type; - internal static readonly int Red; - internal static readonly int Yellow; - internal static readonly int Magenta; - internal static readonly int White; - internal static readonly int Gray; - internal static readonly int DarkGray; - - static ConsoleColorValues() - { - Type = Type.GetType("System.ConsoleColor"); - if (Type == null) return; - Red = (int)Enum.Parse(Type, "Red", false); - Yellow = (int)Enum.Parse(Type, "Yellow", false); - Magenta = (int)Enum.Parse(Type, "Magenta", false); - White = (int)Enum.Parse(Type, "White", false); - Gray = (int)Enum.Parse(Type, "Gray", false); - DarkGray = (int)Enum.Parse(Type, "DarkGray", false); - } - } - } - - internal static class LogMessageFormatter - { - private static readonly Regex Pattern = new Regex(@"\{\w{1,}\}"); - - /// - /// Some logging frameworks support structured logging, such as serilog. This will allow you to add names to structured data in a format string: - /// For example: Log("Log message to {user}", user). This only works with serilog, but as the user of LibLog, you don't know if serilog is actually - /// used. So, this class simulates that. it will replace any text in {curlybraces} with an index number. - /// - /// "Log {message} to {user}" would turn into => "Log {0} to {1}". Then the format parameters are handled using regular .net string.Format. - /// - /// The message builder. - /// The format parameters. - /// - public static Func SimulateStructuredLogging(Func messageBuilder, object[] formatParameters) - { - if(formatParameters == null) - { - return messageBuilder; - } - - return () => - { - string targetMessage = messageBuilder(); - int argumentIndex = 0; - foreach (Match match in Pattern.Matches(targetMessage)) - { - int notUsed; - if (!int.TryParse(match.Value.Substring(1, match.Value.Length -2), out notUsed)) - { - targetMessage = ReplaceFirst(targetMessage, match.Value, - "{" + argumentIndex++ + "}"); - } - } - try - { - return String.Format(CultureInfo.InvariantCulture, targetMessage, formatParameters); - } - catch (FormatException ex) - { - throw new FormatException("The input string '" + targetMessage + "' could not be formatted using string.Format", ex); - } - }; - } - - private static string ReplaceFirst(string text, string search, string replace) - { - int pos = text.IndexOf(search, StringComparison.Ordinal); - if (pos < 0) - { - return text; - } - return text.Substring(0, pos) + replace + text.Substring(pos + search.Length); - } - } - - internal static class TypeExtensions - { - internal static MethodInfo GetMethodPortable(this Type type, string name) - { -#if LIBLOG_PORTABLE - return type.GetRuntimeMethod(name, new Type[]{}); -#else - return type.GetMethod(name); -#endif - } - - internal static MethodInfo GetMethodPortable(this Type type, string name, params Type[] types) - { -#if LIBLOG_PORTABLE - return type.GetRuntimeMethod(name, types); -#else - return type.GetMethod(name, types); -#endif - } - - internal static PropertyInfo GetPropertyPortable(this Type type, string name) - { -#if LIBLOG_PORTABLE - return type.GetRuntimeProperty(name); -#else - return type.GetProperty(name); -#endif - } - -#if LIBLOG_PORTABLE - internal static MethodInfo GetGetMethod(this PropertyInfo propertyInfo) - { - return propertyInfo.GetMethod; - } - - internal static MethodInfo GetSetMethod(this PropertyInfo propertyInfo) - { - return propertyInfo.SetMethod; - } -#endif - -#if !LIBLOG_PORTABLE - internal static object CreateDelegate(this MethodInfo methodInfo, Type delegateType) - { - return Delegate.CreateDelegate(delegateType, methodInfo); - } -#endif - - internal static Assembly GetAssemblyPortable(this Type type) - { -#if LIBLOG_PORTABLE - return type.GetTypeInfo().Assembly; -#else - return type.Assembly; -#endif - } - } - - internal class DisposableAction : IDisposable - { - private readonly Action _onDispose; - - public DisposableAction(Action onDispose = null) - { - _onDispose = onDispose; - } - - public void Dispose() - { - if(_onDispose != null) - { - _onDispose(); - } - } - } -} diff --git a/source/Jobbr.Server/Builder/AutoMapperConfigurationFactory.cs b/source/Jobbr.Server/Builder/AutoMapperConfigurationFactory.cs index 9a44962..496a2d1 100644 --- a/source/Jobbr.Server/Builder/AutoMapperConfigurationFactory.cs +++ b/source/Jobbr.Server/Builder/AutoMapperConfigurationFactory.cs @@ -2,26 +2,42 @@ using System.Collections.Generic; using System.Linq; using AutoMapper; -using Jobbr.Server.Logging; +using Microsoft.Extensions.Logging; namespace Jobbr.Server.Builder { + /// + /// Uses reflection to fetch AutoMapper configurations and initializes them. + /// public class AutoMapperConfigurationFactory { - private static readonly ILog Logger = LogProvider.For(); + private readonly ILogger _logger; + /// + /// Initializes a new instance of the class. + /// + /// The logger. + public AutoMapperConfigurationFactory(ILogger logger) + { + _logger = logger; + } + + /// + /// Creates a new for AutoMapper. + /// + /// containing all types that are in the 'Jobbr.Server' namespace. public MapperConfiguration GetNew() { var foundAutoMapperProfiles = new List(); - var profileTypes = this.GetType().Assembly.GetTypes().Where(t => t.Namespace != null && t.Namespace.StartsWith("Jobbr.Server") && typeof(Profile).IsAssignableFrom(t) && !t.IsAbstract); + var profileTypes = GetType().Assembly.GetTypes().Where(t => t.Namespace != null && t.Namespace.StartsWith("Jobbr.Server") && typeof(Profile).IsAssignableFrom(t) && !t.IsAbstract); var profileTypesList = profileTypes.ToList(); - Logger.Debug($"Found {profileTypesList.Count} types that need to be registered in internal AutoMapper."); + _logger.LogDebug("Found {count} types that need to be registered in internal AutoMapper.", profileTypesList.Count); foreach (var profileType in profileTypesList) { - Logger.Debug($"Activating type '{profileType.Name}' from namespace '{profileType.Namespace}' in assembly '{profileType.Assembly}'"); + _logger.LogDebug("Activating type '{name}' from namespace '{namespace}' in assembly '{assembly}'", profileType.Name, profileType.Namespace, profileType.Assembly); // Don't try/catch here, better fail early (in the creation of Jobbr server) var profile = (Profile)Activator.CreateInstance(profileType); diff --git a/source/Jobbr.Server/Builder/DefaultContainer.cs b/source/Jobbr.Server/Builder/DefaultContainer.cs index 3f9da5e..52b8bdb 100644 --- a/source/Jobbr.Server/Builder/DefaultContainer.cs +++ b/source/Jobbr.Server/Builder/DefaultContainer.cs @@ -6,6 +6,7 @@ using Jobbr.Server.ComponentServices.Management; using Jobbr.Server.ComponentServices.Registration; using Jobbr.Server.Storage; +using Microsoft.Extensions.Logging; using Ninject; using TinyMessenger; @@ -16,44 +17,46 @@ namespace Jobbr.Server.Builder /// internal class DefaultContainer : StandardKernel { - private readonly AutoMapperConfigurationFactory autoMapperConfigurationFactory = new AutoMapperConfigurationFactory(); + private readonly AutoMapperConfigurationFactory _autoMapperConfigurationFactory; - public DefaultContainer() + /// + /// Initializes a new instance of the class. + /// + public DefaultContainer(ILoggerFactory loggerFactory) { - this.AddCoreServices(); - - this.AddAutoMapper(); - - this.AddComponentModelImplementations(); + _autoMapperConfigurationFactory = new AutoMapperConfigurationFactory(loggerFactory.CreateLogger()); + AddCoreServices(); + AddAutoMapper(); + AddComponentModelImplementations(); } private void AddCoreServices() { - this.Bind().To().InSingletonScope(); - this.Bind().To().InSingletonScope(); + Bind().To().InSingletonScope(); + Bind().To().InSingletonScope(); } private void AddAutoMapper() { - var config = this.autoMapperConfigurationFactory.GetNew(); + var config = _autoMapperConfigurationFactory.GetNew(); - this.Bind().ToConstant(config); - this.Bind().ToProvider(); + Bind().ToConstant(config); + Bind().ToProvider(); } private void AddComponentModelImplementations() { // Registration - this.Bind().ToConstant(new JobbrServiceProvider(this)); + Bind().ToConstant(new JobbrServiceProvider(this)); // Management related services - this.Bind().To().InSingletonScope(); - this.Bind().To().InSingletonScope(); - this.Bind().To().InSingletonScope(); + Bind().To().InSingletonScope(); + Bind().To().InSingletonScope(); + Bind().To().InSingletonScope(); // Execution related services - this.Bind().To().InSingletonScope(); - this.Bind().To().InSingletonScope(); + Bind().To().InSingletonScope(); + Bind().To().InSingletonScope(); } } } \ No newline at end of file diff --git a/source/Jobbr.Server/Builder/JobbrBuilder.cs b/source/Jobbr.Server/Builder/JobbrBuilder.cs index 3222ace..dbc8157 100644 --- a/source/Jobbr.Server/Builder/JobbrBuilder.cs +++ b/source/Jobbr.Server/Builder/JobbrBuilder.cs @@ -5,59 +5,71 @@ using Jobbr.ComponentModel.JobStorage; using Jobbr.ComponentModel.Management; using Jobbr.ComponentModel.Registration; -using Jobbr.Server.Logging; using Jobbr.Server.Scheduling; using Jobbr.Server.Storage; +using Microsoft.Extensions.Logging; using Ninject; namespace Jobbr.Server.Builder { - [SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "Cannot disopose container, its used for the jobbr-server instance")] - [SuppressMessage("Design", "CA2213:Disposable fields should be disposed", Justification = "Cannot disopose container, its used for the jobbr-server instance")] + /// + /// Builder class for the entire Jobbr server. + /// + [SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "Cannot dispose container, it is used for the jobbr-server instance.")] public class JobbrBuilder : IJobbrBuilder { - private static readonly ILog Logger = LogProvider.For(); - private readonly StandardKernel container; + private readonly ILogger _logger; + private readonly StandardKernel _container; - public JobbrBuilder() + /// + /// Initializes a new instance of the class. + /// + /// Factory for creating typed loggers. + public JobbrBuilder(ILoggerFactory loggerFactory) { - this.container = new DefaultContainer(); + _logger = loggerFactory.CreateLogger(); + _container = new DefaultContainer(loggerFactory); } + /// + /// Creates a . + /// + /// Maximum amount of concurrent jobs. + /// A new . public JobbrServer Create(int maxConcurrentJobs = 4) { // Register default implementations if user did not specify any separate - if (this.container.TryGet() == null) + if (_container.TryGet() == null) { - Logger.Error("There was no JobStorageProvider registered. Will continue building with an InMemory version, which does not support production scenarios."); + _logger.LogError("There was no JobStorageProvider registered. Will continue building with an in-memory version, which does not support production scenarios."); var inMemoryJobStorageProvider = new InMemoryJobStorageProvider(); - this.container.Bind().ToConstant(inMemoryJobStorageProvider); + _container.Bind().ToConstant(inMemoryJobStorageProvider); } // Register default implementations if user did not specify any separate - if (this.container.TryGet() == null) + if (_container.TryGet() == null) { - Logger.Warn("There was no ArtefactsStorageProvider registered. Adding a default InMemoryArtefactStorage, which stores artefacts in memory. Please register a proper ArtefactStorage for production use."); + _logger.LogWarning("There was no ArtefactsStorageProvider registered. Adding a default InMemoryArtefactStorage, which stores artefacts in memory. Please register a proper ArtefactStorage for production use."); var fileSystemArtefactsStorageProvider = new InMemoryArtefactsStorage(); - this.container.Bind().ToConstant(fileSystemArtefactsStorageProvider); + _container.Bind().ToConstant(fileSystemArtefactsStorageProvider); } // Register default implementations if user did not specify any separate - if (this.container.TryGet() == null) + if (_container.TryGet() == null) { - Logger.Error("There was no JobExecutor registered. Adding a Non-Operational JobExecutor"); - this.container.Bind().To(); + _logger.LogError("There was no JobExecutor registered. Adding a Non-Operational JobExecutor"); + _container.Bind().To(); } // Register default implementations if user did not specify any separate - if (this.container.TryGet() == null) + if (_container.TryGet() == null) { // Don't warn because the internal Scheduler is usually in use this.AddDefaultScheduler(); } - var serverManagementService = this.container.TryGet(); + var serverManagementService = _container.TryGet(); if (serverManagementService != null) { @@ -65,25 +77,25 @@ public JobbrServer Create(int maxConcurrentJobs = 4) } else { - Logger.Error("No Server Management Service found."); + _logger.LogError("No Server Management Service found."); } - return this.container.Get(); + return _container.Get(); } public void Register(Type type) { - this.container.Bind().To(type).InSingletonScope(); + _container.Bind().To(type).InSingletonScope(); } public void Add(object instance) { if (instance is IFeatureConfiguration featureConfiguration) { - this.container.Bind().ToConstant(featureConfiguration); + _container.Bind().ToConstant(featureConfiguration); } - this.container.Bind().ToConstant((T)instance); + _container.Bind().ToConstant((T)instance); } } } \ No newline at end of file diff --git a/source/Jobbr.Server/ComponentServices/Execution/JobRunInformationService.cs b/source/Jobbr.Server/ComponentServices/Execution/JobRunInformationService.cs index 484c1bf..fbcb60d 100644 --- a/source/Jobbr.Server/ComponentServices/Execution/JobRunInformationService.cs +++ b/source/Jobbr.Server/ComponentServices/Execution/JobRunInformationService.cs @@ -1,43 +1,57 @@ using AutoMapper; using Jobbr.ComponentModel.Execution; using Jobbr.ComponentModel.Execution.Model; -using Jobbr.Server.Logging; using Jobbr.Server.Storage; +using Microsoft.Extensions.Logging; namespace Jobbr.Server.ComponentServices.Execution { + /// + /// Service for retrieving information on job runs. + /// internal class JobRunInformationService : IJobRunInformationService { - private static readonly ILog Logger = LogProvider.For(); - - private readonly IJobbrRepository jobbrRepository; - private readonly IMapper mapper; - - public JobRunInformationService(IJobbrRepository jobbrRepository, IMapper mapper) + private readonly ILogger _logger; + private readonly IJobbrRepository _jobbrRepository; + private readonly IMapper _mapper; + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// Repository that contains the jobs. + /// The mapper. + public JobRunInformationService(ILogger logger, IJobbrRepository jobbrRepository, IMapper mapper) { - this.jobbrRepository = jobbrRepository; - this.mapper = mapper; + _logger = logger; + _jobbrRepository = jobbrRepository; + _mapper = mapper; } + /// + /// Gets a job by using the run ID. + /// + /// The run ID. + /// A . public JobRunInfo GetByJobRunId(long jobRunId) { - Logger.Debug($"Retrieving information regarding jobrun with id '{jobRunId}'"); + _logger.LogDebug("Retrieving information regarding job run with ID '{jobRunId}'", jobRunId); - var jobRun = this.jobbrRepository.GetJobRunById(jobRunId); + var jobRun = _jobbrRepository.GetJobRunById(jobRunId); if (jobRun == null) { return null; } - var trigger = this.jobbrRepository.GetTriggerById(jobRun.Job.Id, jobRun.Trigger.Id); - var job = this.jobbrRepository.GetJob(jobRun.Job.Id); + var trigger = _jobbrRepository.GetTriggerById(jobRun.Job.Id, jobRun.Trigger.Id); + var job = _jobbrRepository.GetJob(jobRun.Job.Id); var info = new JobRunInfo(); - this.mapper.Map(job, info); - this.mapper.Map(trigger, info); - this.mapper.Map(jobRun, info); + _mapper.Map(job, info); + _mapper.Map(trigger, info); + _mapper.Map(jobRun, info); return info; } diff --git a/source/Jobbr.Server/ComponentServices/Execution/JobRunProgressReceiver.cs b/source/Jobbr.Server/ComponentServices/Execution/JobRunProgressReceiver.cs index ab608c5..ea4a51c 100644 --- a/source/Jobbr.Server/ComponentServices/Execution/JobRunProgressReceiver.cs +++ b/source/Jobbr.Server/ComponentServices/Execution/JobRunProgressReceiver.cs @@ -6,37 +6,67 @@ namespace Jobbr.Server.ComponentServices.Execution { + /// + /// Receives events regarding job runs and sends them to service classes. + /// internal class JobRunProgressReceiver : IJobRunProgressChannel { - private readonly JobRunService jobRunService; - private readonly IMapper mapper; + private readonly JobRunService _jobRunService; + private readonly IMapper _mapper; + /// + /// Initializes a new instance of the class. + /// + /// Job run service. + /// The mapper. public JobRunProgressReceiver(JobRunService jobRunService, IMapper mapper) { - this.jobRunService = jobRunService; - this.mapper = mapper; + _jobRunService = jobRunService; + _mapper = mapper; } + /// + /// Publishes a status update for the job run. + /// + /// The ID of the job run. + /// The state for the update. public void PublishStatusUpdate(long jobRunId, JobRunStates state) { - var coreState = this.mapper.Map(state); + var coreState = _mapper.Map(state); - this.jobRunService.UpdateState(jobRunId, coreState); + _jobRunService.UpdateState(jobRunId, coreState); } + /// + /// Publishes a progress update for the job run. + /// + /// The ID for the job run. + /// The progress that is being published. public void PublishProgressUpdate(long jobRunId, double progress) { - this.jobRunService.UpdateProgress(jobRunId, progress); + _jobRunService.UpdateProgress(jobRunId, progress); } + /// + /// Publishes a process ID for the job run. + /// + /// The ID of the job run. + /// The process ID. + /// The host. public void PublishPid(long jobRunId, int pid, string host) { - this.jobRunService.UpdatePid(jobRunId, host, pid); + _jobRunService.UpdatePid(jobRunId, pid); } + /// + /// Publishes an artifact for the job run. + /// + /// The ID for the job run. + /// Artifact filename. + /// Result . public void PublishArtefact(long id, string fileName, Stream result) { - this.jobRunService.AddArtefact(id, fileName, result); + _jobRunService.AddArtefact(id, fileName, result); } } } \ No newline at end of file diff --git a/source/Jobbr.Server/ConfigurationManager.cs b/source/Jobbr.Server/ConfigurationManager.cs index 1e40b6c..d72d6c9 100644 --- a/source/Jobbr.Server/ConfigurationManager.cs +++ b/source/Jobbr.Server/ConfigurationManager.cs @@ -1,85 +1,103 @@ using System; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using System.Reflection; using Jobbr.ComponentModel.Registration; using Jobbr.Server.ComponentServices.Registration; -using Jobbr.Server.Logging; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; namespace Jobbr.Server { + /// + /// Manages configuration for the Jobbr server. + /// public class ConfigurationManager { - private static readonly ILog Logger = LogProvider.For(); - - private readonly List configurationValidators; - private readonly JobbrServiceProvider jobbrServiceProvider; - private readonly List featureConfigurations; - - public ConfigurationManager(List configurationValidators, JobbrServiceProvider jobbrServiceProvider, List featureConfigurations) + private readonly ILogger _logger; + private readonly Collection _configurationValidators; + private readonly JobbrServiceProvider _jobbrServiceProvider; + private readonly Collection _featureConfigurations; + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// Collection of validators for the configurations. + /// Jobbr dependency resolver. + /// Configurations for the Jobbr server. + public ConfigurationManager(ILogger logger, Collection configurationValidators, JobbrServiceProvider jobbrServiceProvider, Collection featureConfigurations) { - this.configurationValidators = configurationValidators; - this.jobbrServiceProvider = jobbrServiceProvider; - this.featureConfigurations = featureConfigurations; + _logger = logger; + _configurationValidators = configurationValidators; + _jobbrServiceProvider = jobbrServiceProvider; + _featureConfigurations = featureConfigurations; } + /// + /// Logs the current configurations. + /// public void LogConfiguration() { - if (this.featureConfigurations == null || !this.featureConfigurations.Any()) + if (_featureConfigurations == null || !_featureConfigurations.Any()) { - Logger.Debug("Skipping printing configurations because there are feature configurations available."); + _logger.LogDebug("Skipping printing configurations because there are feature configurations available."); return; } - foreach (var config in this.featureConfigurations) + foreach (var config in _featureConfigurations) { - var jsonSettings = new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = new IgnoreDelegatesFromSerializationContractResolver() }; + var jsonSettings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = new IgnoreDelegatesFromSerializationContractResolver() }; var serialized = JsonConvert.SerializeObject(config, jsonSettings); - serialized = serialized.Replace("{", "["); - serialized = serialized.Replace("}", "]"); - serialized = serialized.Replace(",\"", ", "); - serialized = serialized.Replace("\":", ": "); - serialized = serialized.Replace("[\"", "["); + serialized = serialized.Replace("{", "[", StringComparison.CurrentCulture); + serialized = serialized.Replace("}", "]", StringComparison.CurrentCulture); + serialized = serialized.Replace(",\"", ", ", StringComparison.CurrentCulture); + serialized = serialized.Replace("\":", ": ", StringComparison.CurrentCulture); + serialized = serialized.Replace("[\"", "[", StringComparison.CurrentCulture); try { - Logger.Info($"{config.GetType().Name} = " + serialized); + _logger.LogInformation("{typeName} = {serialized}", config.GetType().Name, serialized); } - catch + catch (NullReferenceException) { - Logger.Info($"{config.GetType().Name} = " + "NOT DISPLAYABLE!"); + _logger.LogInformation("{typeName} = NOT DISPLAYABLE!", config.GetType().Name); } } } + /// + /// Validates configurations. + /// + /// At least one of the configuration validations failed. public void ValidateConfigurationAndThrowOnErrors() { - if (this.configurationValidators == null || !this.configurationValidators.Any()) + if (_configurationValidators == null || !_configurationValidators.Any()) { - Logger.Debug("Skipping validating configuration because there are no validators available."); + _logger.LogDebug("Skipping validating configuration because there are no validators available."); return; } - Logger.Debug("Validating the configuration..."); + _logger.LogDebug("Validating the configuration..."); var results = new Dictionary(); - foreach (var validator in this.configurationValidators) + foreach (var validator in _configurationValidators) { var forType = validator.ConfigurationType; - var config = this.jobbrServiceProvider.GetService(forType); + var config = _jobbrServiceProvider.GetService(forType); if (config == null) { - Logger.Warn($"Unable to use Validator '{validator.GetType().FullName}' because there are no compatible configurations (of Type '{forType.FullName}') registered."); + _logger.LogWarning("Unable to use validator '{validatorName}' because there are no compatible configurations (of Type '{configurationTypeName}') registered.", validator.GetType().FullName, forType.FullName); continue; } - Logger.Debug($"Validating configuration of Type '{config.GetType()}'"); + _logger.LogDebug("Validating configuration of type '{configType}'", config.GetType()); try { @@ -87,25 +105,25 @@ public void ValidateConfigurationAndThrowOnErrors() if (result) { - Logger.Info($"Configuration '{config.GetType().Name}' has been validated successfully"); + _logger.LogInformation("Configuration '{configName}' has been validated successfully", config.GetType().Name); } else { - Logger.Warn($"Validation for Configuration '{config.GetType().Name}' failed."); + _logger.LogWarning("Validation for Configuration '{configTypeName}' failed.", config.GetType().Name); } results.Add(forType, result); } catch (Exception e) { - Logger.ErrorException($"Validator '{validator.GetType().FullName}' has failed while validation!", e); + _logger.LogError(e, "Validator '{validatorName}' has failed while validation!", validator.GetType().FullName); results.Add(forType, false); } } if (!results.Values.All(r => r)) { - throw new Exception("Configuration failed for one or more configurations"); + throw new ArgumentNullException("Configuration failed for one or more configurations"); } } @@ -113,7 +131,7 @@ private class IgnoreDelegatesFromSerializationContractResolver : DefaultContract { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { - JsonProperty property = base.CreateProperty(member, memberSerialization); + var property = base.CreateProperty(member, memberSerialization); if (typeof(MulticastDelegate).IsAssignableFrom(property.PropertyType.BaseType)) { diff --git a/source/Jobbr.Server/Core/JobRunService.cs b/source/Jobbr.Server/Core/JobRunService.cs index 489299e..f9e3246 100644 --- a/source/Jobbr.Server/Core/JobRunService.cs +++ b/source/Jobbr.Server/Core/JobRunService.cs @@ -5,67 +5,88 @@ using Jobbr.ComponentModel.ArtefactStorage; using Jobbr.Server.Core.Messaging; using Jobbr.Server.Core.Models; -using Jobbr.Server.Logging; using Jobbr.Server.Storage; +using Microsoft.Extensions.Logging; using TinyMessenger; namespace Jobbr.Server.Core { + /// + /// Service for managing the job states, artifacts and IDs. + /// public class JobRunService { - private static readonly ILog Logger = LogProvider.For(); - - private readonly ITinyMessengerHub messengerHub; - private readonly IJobbrRepository repository; - private readonly IArtefactsStorageProvider artefactsStorageProvider; - private readonly IMapper mapper; - - public JobRunService(ITinyMessengerHub messengerHub, IJobbrRepository repository, IArtefactsStorageProvider artefactsStorageProvider, IMapper mapper) + private readonly ILogger _logger; + private readonly ITinyMessengerHub _messengerHub; + private readonly IJobbrRepository _jobbrRepository; + private readonly IArtefactsStorageProvider _artefactsStorageProvider; + private readonly IMapper _mapper; + + /// + /// Initializes a new instance of the class. + /// + public JobRunService(ILogger logger, ITinyMessengerHub messengerHub, IJobbrRepository jobbrRepository, IArtefactsStorageProvider artefactsStorageProvider, IMapper mapper) { - this.messengerHub = messengerHub; - this.repository = repository; - this.artefactsStorageProvider = artefactsStorageProvider; - this.mapper = mapper; + _logger = logger; + _messengerHub = messengerHub; + _jobbrRepository = jobbrRepository; + _artefactsStorageProvider = artefactsStorageProvider; + _mapper = mapper; } + /// + /// Update the progress of a job. + /// + /// ID for the job run. + /// How far the job has progressed. public void UpdateProgress(long jobRunId, double progress) { - this.repository.UpdateJobRunProgress(jobRunId, progress); + _jobbrRepository.UpdateJobRunProgress(jobRunId, progress); } + /// + /// Update the state of a job. + /// + /// The ID of the job run. + /// The new state for the job. public void UpdateState(long jobRunId, JobRunStates state) { - Logger.InfoFormat("[{0}] The JobRun with id: {0} has switched to the '{1}'-State", jobRunId, state); + _logger.LogInformation("[{jobRunId}] The JobRun with id: {jobRunId} has switched to the '{state}'-State", jobRunId, jobRunId, state); - var jobRun = this.repository.GetJobRunById(jobRunId); - jobRun.State = this.mapper.Map(state); + var jobRun = _jobbrRepository.GetJobRunById(jobRunId); + jobRun.State = _mapper.Map(state); if (state == JobRunStates.Started) { jobRun.ActualStartDateTimeUtc = DateTime.UtcNow; } - if (state == JobRunStates.Completed || state == JobRunStates.Failed) + if (state is JobRunStates.Completed or JobRunStates.Failed) { jobRun.ActualEndDateTimeUtc = DateTime.UtcNow; } - this.repository.Update(jobRun); + _jobbrRepository.Update(jobRun); if (state == JobRunStates.Completed || state == JobRunStates.Failed) { - this.messengerHub.Publish(new JobRunCompletedMessage(this) { Id = jobRunId, IsSuccessful = state == JobRunStates.Completed }); + _messengerHub.Publish(new JobRunCompletedMessage(this) { Id = jobRunId, IsSuccessful = state == JobRunStates.Completed }); } } + /// + /// Gets job artifacts. + /// + /// ID of the job. + /// A list of s. List is empty if none are found or an error is thrown in the process. public List GetArtefactsByJobRunId(long jobRunId) { try { - var artefacts = this.artefactsStorageProvider.GetArtefacts(jobRunId.ToString()); - return this.mapper.Map>(artefacts); + var artefacts = _artefactsStorageProvider.GetArtefacts(jobRunId.ToString()); + return _mapper.Map>(artefacts); } - catch + catch (Exception) { // ignored } @@ -73,39 +94,61 @@ public List GetArtefactsByJobRunId(long jobRunId) return new List(); } + /// + /// Gets a of artifacts for the job. + /// + /// ID of the job. + /// Target file to stream to. + /// An artifact pointed towards the file. Null if none are found or error is thrown in the process. public Stream GetArtefactAsStream(long jobRunId, string filename) { try { - return this.artefactsStorageProvider.Load(jobRunId.ToString(), filename); + return _artefactsStorageProvider.Load(jobRunId.ToString(), filename); } - catch + catch (Exception) { + // ignored } return null; } + /// + /// Adds an artifact to a job. + /// + /// ID of the job. + /// Filename of the file containing an artifact. + /// Result . public void AddArtefact(long jobRunId, string fileName, Stream result) { - this.artefactsStorageProvider.Save(jobRunId.ToString(), fileName, result); + _artefactsStorageProvider.Save(jobRunId.ToString(), fileName, result); } - public void UpdatePid(long jobRunId, string host, int pid) + /// + /// Updates the process ID of the job. + /// + /// ID of the job. + /// New process ID. + public void UpdatePid(long jobRunId, int processId) { - var jobRun = this.repository.GetJobRunById(jobRunId); - jobRun.Pid = pid; + var jobRun = _jobbrRepository.GetJobRunById(jobRunId); + jobRun.Pid = processId; - this.repository.Update(jobRun); + _jobbrRepository.Update(jobRun); } + /// + /// Deletes a job. + /// + /// ID of the job. public void Delete(long jobRunId) { - var jobRun = this.repository.GetJobRunById(jobRunId); + var jobRun = _jobbrRepository.GetJobRunById(jobRunId); jobRun.Deleted = true; - this.repository.Update(jobRun); + _jobbrRepository.Update(jobRun); } } } \ No newline at end of file diff --git a/source/Jobbr.Server/Core/TriggerService.cs b/source/Jobbr.Server/Core/TriggerService.cs index 87c9bfd..b53784d 100644 --- a/source/Jobbr.Server/Core/TriggerService.cs +++ b/source/Jobbr.Server/Core/TriggerService.cs @@ -3,163 +3,174 @@ using Jobbr.ComponentModel.JobStorage.Model; using Jobbr.Server.Core.Messaging; using Jobbr.Server.Core.Models; -using Jobbr.Server.Logging; using Jobbr.Server.Storage; +using Microsoft.Extensions.Logging; using TinyMessenger; namespace Jobbr.Server.Core { + /// + /// Service for managing triggers. + /// internal class TriggerService { - private static readonly ILog Logger = LogProvider.For(); - - private readonly IJobbrRepository jobbrRepository; - private readonly ITinyMessengerHub messengerHub; - private readonly IMapper mapper; - - public TriggerService(IJobbrRepository jobbrRepository, ITinyMessengerHub messengerHub, IMapper mapper) + private readonly ILogger _logger; + private readonly IJobbrRepository _jobbrRepository; + private readonly ITinyMessengerHub _messengerHub; + private readonly IMapper _mapper; + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + /// Repository for accessing job data, + /// SubPub messenger hub. + /// The mapper. + public TriggerService(ILogger logger, IJobbrRepository jobbrRepository, ITinyMessengerHub messengerHub, IMapper mapper) { - this.jobbrRepository = jobbrRepository; - this.messengerHub = messengerHub; - this.mapper = mapper; + _logger = logger; + _jobbrRepository = jobbrRepository; + _messengerHub = messengerHub; + _mapper = mapper; } internal void Add(long jobId, RecurringTriggerModel trigger) { - var triggerEntity = this.mapper.Map(trigger); + var triggerEntity = _mapper.Map(trigger); - this.jobbrRepository.SaveAddTrigger(jobId, triggerEntity); + _jobbrRepository.SaveAddTrigger(jobId, triggerEntity); trigger.Id = triggerEntity.Id; trigger.JobId = triggerEntity.JobId; - this.messengerHub.PublishAsync(new TriggerAddedMessage(this, new TriggerKey { JobId = triggerEntity.JobId, TriggerId = triggerEntity.Id })); + _messengerHub.PublishAsync(new TriggerAddedMessage(this, new TriggerKey { JobId = triggerEntity.JobId, TriggerId = triggerEntity.Id })); } internal void Add(long jobId, ScheduledTriggerModel trigger) { - var triggerEntity = this.mapper.Map(trigger); + var triggerEntity = _mapper.Map(trigger); - this.jobbrRepository.SaveAddTrigger(jobId, triggerEntity); + _jobbrRepository.SaveAddTrigger(jobId, triggerEntity); trigger.Id = triggerEntity.Id; trigger.JobId = triggerEntity.JobId; - this.messengerHub.PublishAsync(new TriggerAddedMessage(this, new TriggerKey { JobId = triggerEntity.JobId, TriggerId = triggerEntity.Id })); + _messengerHub.PublishAsync(new TriggerAddedMessage(this, new TriggerKey { JobId = triggerEntity.JobId, TriggerId = triggerEntity.Id })); } internal void Add(long jobId, InstantTriggerModel trigger) { - var triggerEntity = this.mapper.Map(trigger); + var triggerEntity = _mapper.Map(trigger); - this.jobbrRepository.SaveAddTrigger(jobId, triggerEntity); + _jobbrRepository.SaveAddTrigger(jobId, triggerEntity); trigger.Id = triggerEntity.Id; trigger.JobId = triggerEntity.JobId; - this.messengerHub.PublishAsync(new TriggerAddedMessage(this, new TriggerKey { JobId = triggerEntity.JobId, TriggerId = triggerEntity.Id })); + _messengerHub.PublishAsync(new TriggerAddedMessage(this, new TriggerKey { JobId = triggerEntity.JobId, TriggerId = triggerEntity.Id })); } internal void Disable(long jobId, long triggerId) { - this.jobbrRepository.DisableTrigger(jobId, triggerId); - this.messengerHub.PublishAsync(new TriggerStateChangedMessage(this, new TriggerKey { JobId = jobId, TriggerId = triggerId })); + _jobbrRepository.DisableTrigger(jobId, triggerId); + _messengerHub.PublishAsync(new TriggerStateChangedMessage(this, new TriggerKey { JobId = jobId, TriggerId = triggerId })); } internal void Delete(long jobId, long triggerId) { - this.jobbrRepository.DeleteTrigger(jobId, triggerId); - this.messengerHub.PublishAsync(new TriggerStateChangedMessage(this, new TriggerKey { JobId = jobId, TriggerId = triggerId })); + _jobbrRepository.DeleteTrigger(jobId, triggerId); + _messengerHub.PublishAsync(new TriggerStateChangedMessage(this, new TriggerKey { JobId = jobId, TriggerId = triggerId })); } internal void Enable(long jobId, long triggerId) { - this.jobbrRepository.EnableTrigger(jobId, triggerId); + _jobbrRepository.EnableTrigger(jobId, triggerId); - this.messengerHub.PublishAsync(new TriggerStateChangedMessage(this, new TriggerKey { JobId = jobId, TriggerId = triggerId })); + _messengerHub.PublishAsync(new TriggerStateChangedMessage(this, new TriggerKey { JobId = jobId, TriggerId = triggerId })); } + // TODO: combine update methods, too much copy-paste here internal void Update(long jobId, long triggerId, string definition) { - var trigger = this.jobbrRepository.GetTriggerById(jobId, triggerId); + var trigger = _jobbrRepository.GetTriggerById(jobId, triggerId); var recurringTrigger = trigger as RecurringTrigger; if (recurringTrigger == null) { - Logger.Warn($"Unable to update RecurringTrigger with id '{triggerId}': Trigger not found!"); + _logger.LogWarning("Unable to update RecurringTrigger with id '{triggerId}': Trigger not found!", triggerId); return; } recurringTrigger.Definition = definition; - this.jobbrRepository.SaveUpdateTrigger(jobId, trigger, out var hadChanges); + _jobbrRepository.SaveUpdateTrigger(jobId, trigger, out var hadChanges); if (hadChanges) { - this.messengerHub.PublishAsync(new TriggerUpdatedMessage(this, new TriggerKey { JobId = jobId, TriggerId = triggerId })); + _messengerHub.PublishAsync(new TriggerUpdatedMessage(this, new TriggerKey { JobId = jobId, TriggerId = triggerId })); } } internal void Update(RecurringTriggerModel trigger) { - var triggerEntity = this.mapper.Map(trigger); + var triggerEntity = _mapper.Map(trigger); // ReSharper disable once UsePatternMatching - var fromDb = this.jobbrRepository.GetTriggerById(trigger.JobId, trigger.Id) as RecurringTrigger; + var fromDb = _jobbrRepository.GetTriggerById(trigger.JobId, trigger.Id) as RecurringTrigger; if (fromDb == null) { - Logger.Warn($"Unable to update RecurringTrigger with id '{trigger.Id}' (JobId '{trigger.JobId}'): Trigger not found!"); + _logger.LogWarning("Unable to update RecurringTrigger with id '{triggerId}' (JobId '{jobId}'): Trigger not found!", trigger.Id, trigger.JobId); return; } - this.jobbrRepository.SaveUpdateTrigger(trigger.JobId, triggerEntity, out var hadChanges); + _jobbrRepository.SaveUpdateTrigger(trigger.JobId, triggerEntity, out var hadChanges); if (hadChanges) { - this.messengerHub.PublishAsync(new TriggerUpdatedMessage(this, new TriggerKey { JobId = trigger.JobId, TriggerId = trigger.Id })); + _messengerHub.PublishAsync(new TriggerUpdatedMessage(this, new TriggerKey { JobId = trigger.JobId, TriggerId = trigger.Id })); } } internal void Update(ScheduledTriggerModel trigger) { - var triggerEntity = this.mapper.Map(trigger); + var triggerEntity = _mapper.Map(trigger); // ReSharper disable once UsePatternMatching - var fromDb = this.jobbrRepository.GetTriggerById(trigger.JobId, trigger.Id) as ScheduledTrigger; + var fromDb = _jobbrRepository.GetTriggerById(trigger.JobId, trigger.Id) as ScheduledTrigger; if (fromDb == null) { - Logger.Warn($"Unable to update ScheduledTrigger with id '{trigger.Id}' (JobId '{trigger.JobId}'): Trigger not found!"); + _logger.LogWarning("Unable to update ScheduledTrigger with id '{triggerId}' (JobId '{jobId}'): Trigger not found!", trigger.Id, trigger.JobId); return; } - this.jobbrRepository.SaveUpdateTrigger(trigger.JobId, triggerEntity, out var hadChanges); + _jobbrRepository.SaveUpdateTrigger(trigger.JobId, triggerEntity, out var hadChanges); if (hadChanges) { - this.messengerHub.PublishAsync(new TriggerUpdatedMessage(this, new TriggerKey { JobId = trigger.JobId, TriggerId = trigger.Id })); + _messengerHub.PublishAsync(new TriggerUpdatedMessage(this, new TriggerKey { JobId = trigger.JobId, TriggerId = trigger.Id })); } } internal void Update(long jobId, long triggerId, DateTime startDateTimeUtc) { - var trigger = this.jobbrRepository.GetTriggerById(jobId, triggerId); + var trigger = _jobbrRepository.GetTriggerById(jobId, triggerId); // ReSharper disable once UsePatternMatching var recurringTrigger = trigger as ScheduledTrigger; if (recurringTrigger == null) { - Logger.Warn($"Unable to update ScheduledTrigger with id '{triggerId}': Trigger not found!"); + _logger.LogWarning("Unable to update ScheduledTrigger with id '{triggerId}': Trigger not found!", trigger.Id); return; } recurringTrigger.StartDateTimeUtc = startDateTimeUtc; - this.jobbrRepository.SaveUpdateTrigger(jobId, trigger, out var hadChanges); + _jobbrRepository.SaveUpdateTrigger(jobId, trigger, out var hadChanges); if (hadChanges) { - this.messengerHub.PublishAsync(new TriggerUpdatedMessage(this, new TriggerKey { JobId = jobId, TriggerId = triggerId })); + _messengerHub.PublishAsync(new TriggerUpdatedMessage(this, new TriggerKey { JobId = jobId, TriggerId = triggerId })); } } } diff --git a/source/Jobbr.Server/JobRegistry/JobbrBuilderExtension.cs b/source/Jobbr.Server/JobRegistry/JobbrBuilderExtension.cs index 43b5f1e..db9554e 100644 --- a/source/Jobbr.Server/JobRegistry/JobbrBuilderExtension.cs +++ b/source/Jobbr.Server/JobRegistry/JobbrBuilderExtension.cs @@ -3,11 +3,20 @@ namespace Jobbr.Server.JobRegistry { + /// + /// Extensions for . + /// public static class JobbrBuilderExtension { + /// + /// Extract jobs from given and add to a . + /// + /// where the jobs are added. + /// Typed that contains the jobs. + /// The original with the added jobs. public static IJobbrBuilder AddJobs(this IJobbrBuilder builder, Action repository) { - var repoBuilder = new RegistryBuilder(); + var repoBuilder = new RegistryBuilder(null); repository(repoBuilder); diff --git a/source/Jobbr.Server/JobRegistry/RegistryBuilder.cs b/source/Jobbr.Server/JobRegistry/RegistryBuilder.cs index 6a3d730..ae3e6e4 100644 --- a/source/Jobbr.Server/JobRegistry/RegistryBuilder.cs +++ b/source/Jobbr.Server/JobRegistry/RegistryBuilder.cs @@ -3,32 +3,42 @@ using System.Linq; using Jobbr.ComponentModel.JobStorage; using Jobbr.ComponentModel.JobStorage.Model; -using Jobbr.Server.Logging; +using Microsoft.Extensions.Logging; namespace Jobbr.Server.JobRegistry { + /// + /// Builds a registry that contains jobs, job descriptions and their triggers. + /// public class RegistryBuilder { - private static readonly ILog Logger = LogProvider.For(); - - private readonly List definitions = new List(); - - private bool isSingleSourceOfTruth; + private readonly ILogger _logger; + private readonly List _definitions = new (); + private bool _isSingleSourceOfTruth; internal bool HasConfiguration { get; private set; } - internal List Definitions => this.definitions; + internal List Definitions => _definitions; + + /// + /// Initializes a new instance of the class. + /// + /// The logger. + public RegistryBuilder(ILogger logger) + { + _logger = logger; + } public RegistryBuilder RemoveAll() { - this.HasConfiguration = true; + HasConfiguration = true; return this; } public RegistryBuilder AsSingleSourceOfTruth() { - this.isSingleSourceOfTruth = true; + _isSingleSourceOfTruth = true; return this; } @@ -36,15 +46,15 @@ public JobDefinition Define(Type jobType, int maxConcurrentJobRuns = 0) { if (jobType == null) { - throw new ArgumentException($"Job Type can't be null."); + throw new ArgumentException("Job Type can't be null."); } - return this.Define(jobType.Name, jobType.FullName, maxConcurrentJobRuns); + return Define(jobType.Name, jobType.FullName, maxConcurrentJobRuns); } public JobDefinition Define(string uniqueName, string typeName, int maxConcurrentJobRuns = 0) { - var existing = this.definitions.FirstOrDefault(d => string.Equals(d.UniqueName, uniqueName, StringComparison.OrdinalIgnoreCase)); + var existing = _definitions.FirstOrDefault(d => string.Equals(d.UniqueName, uniqueName, StringComparison.OrdinalIgnoreCase)); if (existing != null) { @@ -53,9 +63,9 @@ public JobDefinition Define(string uniqueName, string typeName, int maxConcurren } var definition = new JobDefinition() { UniqueName = uniqueName, ClrType = typeName, MaxConcurrentJobRuns = maxConcurrentJobRuns }; - this.definitions.Add(definition); + _definitions.Add(definition); - this.HasConfiguration = true; + HasConfiguration = true; return definition; } @@ -64,29 +74,31 @@ internal int Apply(IJobStorageProvider storage) { var numberOfChanges = 0; - if (!this.HasConfiguration) + if (!HasConfiguration) { return numberOfChanges; } // Deactivate non existent - if (this.isSingleSourceOfTruth) + if (_isSingleSourceOfTruth) { - numberOfChanges += this.SoftDeleteOldJobsAndTriggers(storage); + numberOfChanges += SoftDeleteOldJobsAndTriggers(storage); } - foreach (var jobDefinition in this.Definitions) + foreach (var jobDefinition in Definitions) { var existingJob = storage.GetJobByUniqueName(jobDefinition.UniqueName); if (existingJob == null) { // Add new Job - Logger.InfoFormat("Adding job '{0}' of type '{1}'", jobDefinition.UniqueName, jobDefinition.ClrType); + _logger.LogInformation("Adding job '{name}' of type '{clrType}'", jobDefinition.UniqueName, jobDefinition.ClrType); var job = new Job { - UniqueName = jobDefinition.UniqueName, Type = jobDefinition.ClrType, - Parameters = jobDefinition.Parameter, MaxConcurrentJobRuns = jobDefinition.MaxConcurrentJobRuns + UniqueName = jobDefinition.UniqueName, + Type = jobDefinition.ClrType, + Parameters = jobDefinition.Parameter, + MaxConcurrentJobRuns = jobDefinition.MaxConcurrentJobRuns, }; storage.AddJob(job); @@ -100,9 +112,9 @@ internal int Apply(IJobStorageProvider storage) { existingJob.Deleted = false; existingJob.MaxConcurrentJobRuns = jobDefinition.MaxConcurrentJobRuns; - + // Update existing Jobs and triggers - Logger.InfoFormat("Updating type for Job '{0}' (Id: '{1}') from '{2}' to '{2}'", existingJob.UniqueName, existingJob.Id, existingJob.Type, jobDefinition.ClrType); + _logger.LogInformation("Updating type for Job '{name}' (Id: '{id}') from '{type}' to '{clrType}'", existingJob.UniqueName, existingJob.Id, existingJob.Type, jobDefinition.ClrType); existingJob.Type = jobDefinition.ClrType; existingJob.Parameters = jobDefinition.Parameter; @@ -118,7 +130,7 @@ internal int Apply(IJobStorageProvider storage) if (jobDefinition.Triggers.Any()) { - Logger.InfoFormat("Job '{0}' has {1} triggers explicitly specified by definition. Going to apply the TriggerDefinition to the actual storage provider.", existingJob.UniqueName, jobDefinition.Triggers.Count); + _logger.LogInformation("Job '{name}' has {triggerCount} triggers explicitly specified by definition. Going to apply the TriggerDefinition to the actual storage provider.", existingJob.UniqueName, jobDefinition.Triggers.Count); } // Update or add new ones @@ -130,7 +142,7 @@ internal int Apply(IJobStorageProvider storage) { // Add one AddTrigger(storage, trigger, jobDefinition, existingJob.Id); - Logger.InfoFormat("Added trigger (type: '{0}' to job '{1}' (JobId: '{2}')'", trigger.GetType().Name, jobDefinition.UniqueName, trigger.Id); + _logger.LogInformation("Added trigger (type: '{typeName}' to job '{jobName}' (JobId: '{id}')'", trigger.GetType().Name, jobDefinition.UniqueName, trigger.Id); numberOfChanges++; } @@ -143,7 +155,7 @@ internal int Apply(IJobStorageProvider storage) // Deactivate not specified triggers foreach (var trigger in toDeactivateTriggers) { - Logger.InfoFormat("Deactivating trigger (type: '{0}' to job '{1}' (JobId: '{2}')'", trigger.GetType().Name, jobDefinition.UniqueName, trigger.Id); + _logger.LogInformation("Deactivating trigger (type: '{typeName}' to job '{name}' (JobId: '{id}')'", trigger.GetType().Name, jobDefinition.UniqueName, trigger.Id); storage.DisableTrigger(existingJob.Id, trigger.Id); numberOfChanges++; } @@ -154,13 +166,44 @@ internal int Apply(IJobStorageProvider storage) return numberOfChanges; } - private static void AddTrigger(IJobStorageProvider storage, JobTriggerBase trigger, JobDefinition jobDef, long jobId) + private static IList GetUndefinedJobs(ICollection allDefinedJobs, IEnumerable allJobsInStorage) + { + return allJobsInStorage.Where(job => !allDefinedJobs.Contains(job.UniqueName)).ToList(); + } + + private static int OmitJobRunsFromJob(IJobStorageProvider storage, Job undefinedJob) + { + var numberOfChanges = 0; + foreach (var jobRun in storage.GetJobRunsByJobId((int)undefinedJob.Id, pageSize: int.MaxValue).Items) + { + jobRun.Deleted = true; + jobRun.State = JobRunStates.Omitted; + storage.Update(jobRun); + numberOfChanges++; + } + + return numberOfChanges; + } + + private int SoftDeleteTriggers(IJobStorageProvider storage, IEnumerable triggersOfJob) + { + var numberOfChanges = 0; + foreach (var trigger in triggersOfJob) + { + DeleteAndDeactivateTrigger(storage, trigger); + numberOfChanges++; + } + + return numberOfChanges; + } + + private void AddTrigger(IJobStorageProvider storage, JobTriggerBase trigger, JobDefinition jobDef, long jobId) { trigger.IsActive = true; trigger.JobId = jobId; trigger.Parameters = trigger.Parameters; - Logger.InfoFormat("Adding trigger (type: '{0}' to job '{1}' (JobId: '{2}')", trigger.GetType().Name, jobDef.UniqueName, jobId); + _logger.LogInformation("Adding trigger (type: '{typeName}' to job '{jobName}' (JobId: '{id}')", trigger.GetType().Name, jobDef.UniqueName, jobId); switch (trigger) { @@ -173,12 +216,7 @@ private static void AddTrigger(IJobStorageProvider storage, JobTriggerBase trigg } } - private static IList GetUndefinedJobs(ICollection allDefinedJobs, IEnumerable allJobsInStorage) - { - return allJobsInStorage.Where(job => !allDefinedJobs.Contains(job.UniqueName)).ToList(); - } - - private static IList GetTriggersOfJobs(IEnumerable jobIds, IJobStorageProvider storage) + private IEnumerable GetTriggersOfJobs(IEnumerable jobIds, IJobStorageProvider storage) { var triggers = new List(); foreach (var jobId in jobIds) @@ -186,17 +224,17 @@ private static IList GetTriggersOfJobs(IEnumerable jobIds, triggers.AddRange(storage.GetTriggersByJobId(jobId, pageSize: int.MaxValue).Items); } - Logger.InfoFormat($"{triggers.Count} are in the storage but not defined."); + _logger.LogInformation("{triggerCount} are in the storage but not defined.", triggers.Count); return triggers; } - private static int SoftDeleteJobs(IJobStorageProvider storage, IList undefinedJobs) + private int SoftDeleteJobs(IJobStorageProvider storage, IList undefinedJobs) { var numberOfChanges = 0; foreach (var undefinedJob in undefinedJobs) { undefinedJob.Deleted = true; - Logger.InfoFormat($"Deleting job ({undefinedJob.UniqueName}) with the id: {undefinedJob.Id}"); + _logger.LogInformation("Deleting job ({name}) with the id: {id}", undefinedJob.UniqueName, undefinedJob.Id); storage.Update(undefinedJob); numberOfChanges = OmitJobRunsFromJob(storage, undefinedJob); numberOfChanges++; @@ -205,35 +243,9 @@ private static int SoftDeleteJobs(IJobStorageProvider storage, IList undefi return numberOfChanges; } - private static int OmitJobRunsFromJob(IJobStorageProvider storage, Job undefinedJob) + private void DeleteAndDeactivateTrigger(IJobStorageProvider storage, JobTriggerBase trigger) { - var numberOfChanges = 0; - foreach (var jobRun in storage.GetJobRunsByJobId((int)undefinedJob.Id, pageSize: int.MaxValue).Items) - { - jobRun.Deleted = true; - jobRun.State = JobRunStates.Omitted; - storage.Update(jobRun); - numberOfChanges++; - } - - return numberOfChanges; - } - - private static int SoftDeleteTriggers(IJobStorageProvider storage, IList triggersOfJob) - { - var numberOfChanges = 0; - foreach (var trigger in triggersOfJob) - { - DeleteAndDeactivateTrigger(storage, trigger); - numberOfChanges++; - } - - return numberOfChanges; - } - - private static void DeleteAndDeactivateTrigger(IJobStorageProvider storage, JobTriggerBase trigger) - { - Logger.InfoFormat($"Deleting trigger with the id: {trigger.Id}"); + _logger.LogInformation("Deleting trigger with the id: {id}", trigger.Id); trigger.Deleted = true; trigger.IsActive = false; storage.Update(trigger.JobId, trigger as dynamic); @@ -241,7 +253,7 @@ private static void DeleteAndDeactivateTrigger(IJobStorageProvider storage, JobT private int SoftDeleteOldJobsAndTriggers(IJobStorageProvider storage) { - var allDefinedUniqueJobNames = this.Definitions.Select(d => d.UniqueName).ToList(); + var allDefinedUniqueJobNames = Definitions.Select(d => d.UniqueName).ToList(); var allJobsInStorage = storage.GetJobs(pageSize: int.MaxValue).Items; var numberOfChanges = 0; @@ -251,15 +263,15 @@ private int SoftDeleteOldJobsAndTriggers(IJobStorageProvider storage) var triggersOfJob = GetTriggersOfJobs(undefinedJobs.Select(j => j.Id), storage); numberOfChanges += SoftDeleteTriggers(storage, triggersOfJob); - numberOfChanges += this.SoftDeleteOrphanedTriggers(storage); + numberOfChanges += SoftDeleteOrphanedTriggers(storage); return numberOfChanges; } private int SoftDeleteOrphanedTriggers(IJobStorageProvider storage) { - var triggersInDefinition = this.Definitions.SelectMany(d => d.Triggers).ToList(); - var currentTriggersInStorage = this.GetTriggersFromActiveJobs(storage); + var triggersInDefinition = Definitions.SelectMany(d => d.Triggers).ToList(); + var currentTriggersInStorage = GetTriggersFromActiveJobs(storage); var orphanedTriggers = currentTriggersInStorage.Except(triggersInDefinition, new TriggerComparer()).ToList(); var numberOfChanges = 0; @@ -282,10 +294,10 @@ private int SoftDeleteOrphanedTriggers(IJobStorageProvider storage) return numberOfChanges; } - private IList GetTriggersFromActiveJobs(IJobStorageProvider storage) + private IEnumerable GetTriggersFromActiveJobs(IJobStorageProvider storage) { var triggersFromActiveJobs = new List(); - foreach (var uniqueName in this.Definitions.Select(d => d.UniqueName)) + foreach (var uniqueName in Definitions.Select(d => d.UniqueName)) { var job = storage.GetJobByUniqueName(uniqueName); if (job != null) @@ -293,6 +305,7 @@ private IList GetTriggersFromActiveJobs(IJobStorageProvider stor triggersFromActiveJobs.AddRange(storage.GetTriggersByJobId(job.Id, pageSize: int.MaxValue).Items); } } + return triggersFromActiveJobs; } diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index b16ca18..9bacebc 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -27,9 +27,7 @@ - - all - + diff --git a/source/Jobbr.Server/JobbrServer.cs b/source/Jobbr.Server/JobbrServer.cs index 6fc168d..7b920bf 100644 --- a/source/Jobbr.Server/JobbrServer.cs +++ b/source/Jobbr.Server/JobbrServer.cs @@ -11,65 +11,58 @@ using Jobbr.Server.Core.Messaging; using Jobbr.Server.Extensions; using Jobbr.Server.JobRegistry; -using Jobbr.Server.Logging; using Jobbr.Server.Scheduling; +using Microsoft.Extensions.Logging; namespace Jobbr.Server { /// - /// The jobber job server. + /// The Jobbr job server. /// public class JobbrServer : IDisposable { - /// - /// The logger. - /// - private static readonly ILog Logger = LogProvider.For(); + private readonly ILogger _logger; + private readonly IJobScheduler _scheduler; + private readonly IJobExecutor _executor; + private readonly IJobStorageProvider _jobStorageProvider; + private readonly List _jobbrComponents; + private readonly ConfigurationManager _configurationManager; + private readonly RegistryBuilder _registryBuilder; - /// - /// The scheduler. - /// - private readonly IJobScheduler scheduler; + private bool _isRunning; /// - /// The executor. + /// The state of the Jobbr server. /// - private readonly IJobExecutor executor; - - private readonly IJobStorageProvider jobStorageProvider; - - private readonly List components; - - private readonly ConfigurationManager configurationManager; - private readonly RegistryBuilder registryBuilder; - - private bool isRunning; + public JobbrState State { get; private set; } /// /// Initializes a new instance of the class. /// - public JobbrServer(IJobScheduler scheduler, IJobExecutor jobExecutor, IJobStorageProvider jobStorageProvider, List components, MessageDispatcher messageDispatcher, ConfigurationManager configurationManager, RegistryBuilder registryBuilder) + public JobbrServer(ILogger logger, IJobScheduler scheduler, IJobExecutor jobExecutor, IJobStorageProvider jobStorageProvider, List jobbrComponents, MessageDispatcher messageDispatcher, ConfigurationManager configurationManager, RegistryBuilder registryBuilder) { - Logger.Debug("A new instance of a a JobbrServer has been created."); + _logger = logger; - this.scheduler = scheduler; - this.executor = jobExecutor; + _scheduler = scheduler; + _executor = jobExecutor; + _jobbrComponents = jobbrComponents; + _configurationManager = configurationManager; + _registryBuilder = registryBuilder; + _jobStorageProvider = jobStorageProvider; - this.components = components; - this.configurationManager = configurationManager; - this.registryBuilder = registryBuilder; - this.jobStorageProvider = jobStorageProvider; + _logger.LogDebug("A new instance of a JobbrServer has been created."); messageDispatcher.WireUp(); } - public bool IsRunning => this.isRunning; - - public JobbrState State { get; private set; } - + /// + /// Start the Jobbr server synchronously. + /// + /// The timeout for the start in milliseconds. + /// True if start was a success, false if not. public bool Start(int waitForStartupTimeout = 2000) { - var startupTask = this.StartAsync(CancellationToken.None); + var startupTask = StartAsync(CancellationToken.None); try { @@ -77,55 +70,60 @@ public bool Start(int waitForStartupTimeout = 2000) } catch (AggregateException e) { - this.State = JobbrState.Error; + State = JobbrState.Error; throw e.InnerExceptions[0]; } if (!startupTask.IsCompleted) { - Logger.FatalFormat("Jobbr was unable to start within {0}ms. Keep starting but returning now from Start()", waitForStartupTimeout); + _logger.LogCritical("Jobbr was unable to start within {wait}ms. Keep starting but returning now from Start()", waitForStartupTimeout); return false; } return true; } + /// + /// Start the Jobbr server asynchronously. + /// + /// Token for cancelling the async call. + /// A task that will return true if start was a success and false if not. public async Task StartAsync(CancellationToken cancellationToken) { - this.State = JobbrState.Initializing; + State = JobbrState.Initializing; - this.LogVersions(); + LogVersions(); - Logger.InfoFormat("The JobServer has been set-up by the following configurations"); - this.configurationManager.LogConfiguration(); + _logger.LogInformation("The JobServer has been set-up by the following configurations"); + _configurationManager.LogConfiguration(); - this.State = JobbrState.Validating; + State = JobbrState.Validating; try { - this.configurationManager.ValidateConfigurationAndThrowOnErrors(); - Logger.Info("The configuration was validated and seems ok. Final configuration below:"); + _configurationManager.ValidateConfigurationAndThrowOnErrors(); + _logger.LogInformation("The configuration was validated and seems ok. Final configuration below:"); - this.configurationManager.LogConfiguration(); + _configurationManager.LogConfiguration(); } catch (Exception) { - this.State = JobbrState.Error; + State = JobbrState.Error; throw; } - this.State = JobbrState.Starting; + State = JobbrState.Starting; - var waitForDbTask = new Task(this.WaitForDb, cancellationToken); + var waitForDbTask = new Task(WaitForDb, cancellationToken); var startComponents = waitForDbTask.ContinueWith( t => { - this.RegisterJobsFromRepository(); - this.StartInternalComponents(); - this.StartOptionalComponents(); + RegisterJobsFromRepository(); + StartInternalComponents(); + StartOptionalComponents(); - this.isRunning = true; + _isRunning = true; }, cancellationToken); @@ -133,91 +131,91 @@ public async Task StartAsync(CancellationToken cancellationToken) await Task.WhenAll(waitForDbTask, startComponents); - this.State = JobbrState.Running; + State = JobbrState.Running; return true; } - private void LogVersions() - { - var sb = new StringBuilder(); - sb.AppendLine("Version Information:"); - - var assemblies = new List { this.GetType().Assembly }; - assemblies.AddRange(this.components.Select(component => component.GetType().Assembly)); - - assemblies.Distinct().ToList().ForEach(assembly => { sb.AppendLine($"{assembly.ManifestModule.Name} {assembly.GetVersion()}"); }); - - Logger.Info(sb.ToString().TrimEnd()); - } - /// - /// The stop. + /// Stop the server and it's components. /// public void Stop() { - Logger.Info("Attempt to shut down JobbrServer..."); + _logger.LogInformation("Attempting to shut down JobbrServer..."); - this.components.ForEach(component => component.Stop()); + _jobbrComponents.ForEach(component => component.Stop()); - this.scheduler.Stop(); - this.executor.Stop(); + _scheduler.Stop(); + _executor.Stop(); - Logger.Info("All components stopped."); + _logger.LogInformation("All components stopped."); } /// - /// The dispose. + /// Stop the server if it is running. /// public void Dispose() { - if (this.isRunning) + if (_isRunning) { - this.Stop(); + Stop(); } } + private void LogVersions() + { + var sb = new StringBuilder(); + sb.AppendLine("Version Information:"); + + var assemblies = new List { GetType().Assembly }; + assemblies.AddRange(_jobbrComponents.Select(component => component.GetType().Assembly)); + + assemblies.Distinct().ToList().ForEach(assembly => { sb.AppendLine($"{assembly.ManifestModule.Name} {assembly.GetVersion()}"); }); + + _logger.LogInformation("{assemblies}", sb.ToString().TrimEnd()); + } + private void StartInternalComponents() { try { - Logger.DebugFormat("Starting Scheduler ({0})...", this.scheduler.GetType().Name); - this.scheduler.Start(); + _logger.LogDebug("Starting Scheduler ({0})...", _scheduler.GetType().Name); + _scheduler.Start(); - Logger.DebugFormat("Starting Executor ({0})...", this.executor.GetType().Name); - this.executor.Start(); + _logger.LogDebug("Starting Executor ({0})...", _executor.GetType().Name); + _executor.Start(); - Logger.Info("All services (Scheduler, Executor) have been started successfully."); + _logger.LogInformation("All services (Scheduler, Executor) have been started successfully."); } catch (Exception e) { - Logger.FatalException("A least one service couldn't be started. Please see the exception for details.", e); + _logger.LogCritical("A least one service couldn't be started. Please see the exception for details. '{exception}'", e); } } private void StartOptionalComponents() { - if (this.components == null) + if (_jobbrComponents == null) { return; } try { - foreach (var jobbrComponent in this.components) + foreach (var jobbrComponent in _jobbrComponents) { var type = jobbrComponent.GetType(); - Logger.DebugFormat($"Starting JobbrComponent '{type.FullName}' ..."); + _logger.LogDebug("Starting JobbrComponent '{fullName}' ...", type.FullName); jobbrComponent.Start(); } - Logger.Info("All Optional Services have been started successfully."); + _logger.LogInformation("All Optional Services have been started successfully."); - this.isRunning = true; + _isRunning = true; } catch (Exception e) { - Logger.FatalException($"A least one service couldn't be started. Reason: {e}\n\n Please see the exception for details.", e.InnerException); + _logger.LogCritical("At least one of the services couldn't be started. Reason: {e}\n\n Please see the exception for details.", e.InnerException); throw; } } @@ -228,12 +226,12 @@ private void WaitForDb() { try { - this.jobStorageProvider.IsAvailable(); + _jobStorageProvider.IsAvailable(); return; } catch (Exception ex) { - Logger.ErrorException("Exception while connecting to database to get all Jobs on startup.", ex); + _logger.LogError("Exception while connecting to database to get all Jobs on startup: '{e}'", ex); Thread.Sleep(1000); } } @@ -241,18 +239,18 @@ private void WaitForDb() private void RegisterJobsFromRepository() { - Logger.Info("Adding jobs from the registry"); + _logger.LogInformation("Adding jobs from the registry"); try { - var numberOfChanges = this.registryBuilder.Apply(this.jobStorageProvider); - var numberOfJobs = this.jobStorageProvider.GetJobs(pageSize: int.MaxValue).Items.Count; + var numberOfChanges = _registryBuilder.Apply(_jobStorageProvider); + var numberOfJobs = _jobStorageProvider.GetJobs(pageSize: int.MaxValue).Items.Count; - Logger.InfoFormat("There were {0} changes by the JobRegistry. There are now {1} known jobs right available.", numberOfChanges, numberOfJobs); + _logger.LogInformation("There were {changeCount} changes by the JobRegistry. There are now {jobCount} known jobs right available.", numberOfChanges, numberOfJobs); } catch (Exception e) { - Logger.FatalException("Cannot register Jobs on startup. See Exception for details", e); + _logger.LogCritical("Cannot register Jobs on startup. See Exception for details: {e}", e); } } } diff --git a/source/Jobbr.Server/Scheduling/DefaultScheduler.cs b/source/Jobbr.Server/Scheduling/DefaultScheduler.cs index ceebcc6..5c80469 100644 --- a/source/Jobbr.Server/Scheduling/DefaultScheduler.cs +++ b/source/Jobbr.Server/Scheduling/DefaultScheduler.cs @@ -3,45 +3,41 @@ using System.Linq; using Jobbr.ComponentModel.Execution; using Jobbr.ComponentModel.JobStorage.Model; -using Jobbr.Server.Logging; using Jobbr.Server.Scheduling.Planer; using Jobbr.Server.Storage; -using JobRunStates = Jobbr.ComponentModel.JobStorage.Model.JobRunStates; +using Microsoft.Extensions.Logging; namespace Jobbr.Server.Scheduling { public class DefaultScheduler : IJobScheduler { - private static readonly ILog Logger = LogProvider.For(); - - private readonly IJobbrRepository repository; - private readonly IJobExecutor executor; - private readonly IPeriodicTimer periodicTimer; - private readonly IDateTimeProvider dateTimeProvider; - - private readonly InstantJobRunPlaner instantJobRunPlaner; - private readonly ScheduledJobRunPlaner scheduledJobRunPlaner; - private readonly RecurringJobRunPlaner recurringJobRunPlaner; - private readonly DefaultSchedulerConfiguration configuration; - - private readonly object evaluateTriggersLock = new object(); - - private List currentPlan = new List(); - - public DefaultScheduler(IJobbrRepository repository, IJobExecutor executor, InstantJobRunPlaner instantJobRunPlaner, ScheduledJobRunPlaner scheduledJobRunPlaner, RecurringJobRunPlaner recurringJobRunPlaner, DefaultSchedulerConfiguration configuration, IPeriodicTimer periodicTimer, IDateTimeProvider dateTimeProvider) + private readonly ILogger _logger; + private readonly IJobbrRepository _jobbrRepository; + private readonly IJobExecutor _executor; + private readonly IPeriodicTimer _periodicTimer; + private readonly IDateTimeProvider _dateTimeProvider; + private readonly InstantJobRunPlaner _instantJobRunPlanner; + private readonly ScheduledJobRunPlaner _scheduledJobRunPlanner; + private readonly RecurringJobRunPlaner _recurringJobRunPlanner; + private readonly DefaultSchedulerConfiguration _schedulerConfiguration; + private readonly object _evaluateTriggersLock = new (); + + private List _currentPlan = new (); + + public DefaultScheduler(ILogger logger, IJobbrRepository jobbrRepository, IJobExecutor executor, InstantJobRunPlaner instantJobRunPlanner, ScheduledJobRunPlaner scheduledJobRunPlanner, + RecurringJobRunPlaner recurringJobRunPlanner, DefaultSchedulerConfiguration schedulerConfiguration, IPeriodicTimer periodicTimer, IDateTimeProvider dateTimeProvider) { - this.repository = repository; - this.executor = executor; - - this.instantJobRunPlaner = instantJobRunPlaner; - this.scheduledJobRunPlaner = scheduledJobRunPlaner; - this.recurringJobRunPlaner = recurringJobRunPlaner; - - this.configuration = configuration; - this.periodicTimer = periodicTimer; - this.dateTimeProvider = dateTimeProvider; - - this.periodicTimer.Setup(this.EvaluateRecurringTriggers); + _logger = logger; + _jobbrRepository = jobbrRepository; + _executor = executor; + _periodicTimer = periodicTimer; + _dateTimeProvider = dateTimeProvider; + _instantJobRunPlanner = instantJobRunPlanner; + _scheduledJobRunPlanner = scheduledJobRunPlanner; + _recurringJobRunPlanner = recurringJobRunPlanner; + _schedulerConfiguration = schedulerConfiguration; + + _periodicTimer.Setup(EvaluateRecurringTriggers); } public void Dispose() @@ -50,33 +46,32 @@ public void Dispose() public void Start() { - this.SetScheduledJobRunsFromPastToOmitted(); + SetScheduledJobRunsFromPastToOmitted(); - this.SetRunningJobsToFailed(); + SetRunningJobsToFailed(); - this.CreateInitialPlan(); + CreateInitialPlan(); - this.periodicTimer.Start(); + _periodicTimer.Start(); } public void Stop() { - this.periodicTimer.Stop(); + _periodicTimer.Stop(); } public void OnTriggerDefinitionUpdated(long jobId, long triggerId) { - lock (this.evaluateTriggersLock) + lock (_evaluateTriggersLock) { - Logger.Info($"The trigger with id '{triggerId}' has been updated. Reflecting changes to Plan if any."); + _logger.LogInformation("The trigger with id '{triggerId}' has been updated. Reflecting changes to Plan if any.", triggerId); + var trigger = _jobbrRepository.GetTriggerById(jobId, triggerId); - var trigger = this.repository.GetTriggerById(jobId, triggerId); - - PlanResult planResult = this.GetPlanResult(trigger as dynamic, false); + PlanResult planResult = GetPlanResult(trigger as dynamic, false); if (planResult.Action != PlanAction.Possible) { - Logger.Debug($"The trigger was not considered to be relevant to the plan, skipping. PlanResult was '{planResult.Action}'"); + _logger.LogDebug("The trigger was not considered to be relevant to the plan, skipping. PlanResult was '{action}'", planResult.Action); return; } @@ -84,60 +79,60 @@ public void OnTriggerDefinitionUpdated(long jobId, long triggerId) if (!dateTime.HasValue) { - Logger.Warn("Unable to gather an expected start date for trigger, skipping."); + _logger.LogWarning("Unable to gather an expected start date for trigger, skipping."); return; } // Get the next occurrence from database - var dependentJobRun = this.repository.GetNextJobRunByTriggerId(jobId, trigger.Id, this.dateTimeProvider.GetUtcNow()); + var dependentJobRun = _jobbrRepository.GetNextJobRunByTriggerId(jobId, trigger.Id, _dateTimeProvider.GetUtcNow()); if (dependentJobRun == null) { - Logger.Error("Trigger was updated before job run has been created. Cannot apply update."); + _logger.LogError("Trigger was updated before job run has been created. Cannot apply update."); return; } - this.UpdatePlannedJobRun(dependentJobRun, trigger, dateTime.Value); + UpdatePlannedJobRun(dependentJobRun, trigger, dateTime.Value); } } public void OnTriggerStateUpdated(long jobId, long triggerId) { - lock (this.evaluateTriggersLock) + lock (_evaluateTriggersLock) { - Logger.Info($"The trigger with id '{triggerId}' has been changed its state. Reflecting changes to Plan if any."); + _logger.LogInformation("The trigger with id '{triggerId}' has been changed its state. Reflecting changes to Plan if any.", triggerId); - var trigger = this.repository.GetTriggerById(jobId, triggerId); + var trigger = _jobbrRepository.GetTriggerById(jobId, triggerId); - PlanResult planResult = this.GetPlanResult(trigger as dynamic, false); + PlanResult planResult = GetPlanResult(trigger as dynamic, false); if (planResult.Action == PlanAction.Obsolete) { // Remove from in memory plan to not publish this in future - this.currentPlan.RemoveAll(e => e.TriggerId == triggerId); + _currentPlan.RemoveAll(e => e.TriggerId == triggerId); // Set the JobRun to deleted if any - var dependentJobRun = this.repository.GetNextJobRunByTriggerId(jobId, trigger.Id, this.dateTimeProvider.GetUtcNow()); + var dependentJobRun = _jobbrRepository.GetNextJobRunByTriggerId(jobId, trigger.Id, _dateTimeProvider.GetUtcNow()); if (dependentJobRun != null) { - this.repository.Delete(dependentJobRun); + _jobbrRepository.Delete(dependentJobRun); } - this.PublishCurrentPlan(); + PublishCurrentPlan(); return; } if (planResult.Action == PlanAction.Possible) { - var newItem = this.CreateNew(planResult, trigger); + var newItem = CreateNew(planResult, trigger); if (newItem != null) { - this.currentPlan.Add(newItem); + _currentPlan.Add(newItem); - this.PublishCurrentPlan(); + PublishCurrentPlan(); } } } @@ -145,60 +140,60 @@ public void OnTriggerStateUpdated(long jobId, long triggerId) public void OnTriggerAdded(long jobId, long triggerId) { - lock (this.evaluateTriggersLock) + lock (_evaluateTriggersLock) { - Logger.Info($"The trigger with id '{triggerId}' has been added. Reflecting changes to the current plan."); + _logger.LogInformation($"The trigger with id '{triggerId}' has been added. Reflecting changes to the current plan.", triggerId); - var trigger = this.repository.GetTriggerById(jobId, triggerId); + var trigger = _jobbrRepository.GetTriggerById(jobId, triggerId); - PlanResult planResult = this.GetPlanResult(trigger as dynamic, true); + PlanResult planResult = GetPlanResult(trigger as dynamic, true); if (planResult.Action != PlanAction.Possible) { - Logger.Debug($"The trigger was not considered to be relevant to the plan, skipping. PlanResult was '{planResult.Action}'"); + _logger.LogDebug("The trigger was not considered to be relevant to the plan, skipping. PlanResult was '{action}'", planResult.Action); return; } - var newItem = this.CreateNew(planResult, trigger); + var newItem = CreateNew(planResult, trigger); if (newItem == null) { - Logger.Error("Unable to create a new Planned Item with a JobRun."); + _logger.LogError("Unable to create a new Planned Item with a JobRun."); return; } - this.currentPlan.Add(newItem); + _currentPlan.Add(newItem); - this.PublishCurrentPlan(); + PublishCurrentPlan(); } } public void OnJobRunEnded(long id) { - lock (this.evaluateTriggersLock) + lock (_evaluateTriggersLock) { - Logger.Info("A JobRun has ended. Reevaluating triggers that did not yet schedule a run"); + _logger.LogInformation("A JobRun has ended. Reevaluating triggers that did not yet schedule a run"); // Remove from in memory plan to not publish this in future - var numberOfDeletedItems = this.currentPlan.RemoveAll(e => e.Id == id); + var numberOfDeletedItems = _currentPlan.RemoveAll(e => e.Id == id); var additionalItems = new List(); // If a trigger was blocked previously, it might be a candidate to schedule now - var activeTriggers = this.repository.GetActiveTriggers(pageSize: int.MaxValue).Items; + var activeTriggers = _jobbrRepository.GetActiveTriggers(pageSize: int.MaxValue).Items; foreach (var trigger in activeTriggers) { - if (this.currentPlan.Any(p => p.TriggerId == trigger.Id)) + if (_currentPlan.Any(p => p.TriggerId == trigger.Id)) { continue; } - PlanResult planResult = this.GetPlanResult(trigger as dynamic, false); + PlanResult planResult = GetPlanResult(trigger as dynamic, false); if (planResult.Action == PlanAction.Possible) { - var scheduledItem = this.CreateNew(planResult, trigger); + var scheduledItem = CreateNew(planResult, trigger); additionalItems.Add(scheduledItem); } @@ -206,39 +201,39 @@ public void OnJobRunEnded(long id) if (additionalItems.Any() || numberOfDeletedItems > 0) { - Logger.Info($"The completion of a previous job caused the addition of {additionalItems.Count} and removal of {numberOfDeletedItems} scheduled items"); - this.currentPlan.AddRange(additionalItems); + _logger.LogInformation("The completion of a previous job caused the addition of {itemCount} and removal of {deletedCount} scheduled items", additionalItems.Count, numberOfDeletedItems); + _currentPlan.AddRange(additionalItems); - this.PublishCurrentPlan(); + PublishCurrentPlan(); } else { - Logger.Debug($"There was no possibility to scheduled new items after the completion of job with it '{id}'."); + _logger.LogDebug("There was no possibility to scheduled new items after the completion of job with it '{id}'.", id); } } } private void EvaluateRecurringTriggers() { - lock (this.evaluateTriggersLock) + lock (_evaluateTriggersLock) { // Re-evaluate recurring triggers every n seconds - var activeTriggers = this.repository.GetActiveTriggers(pageSize: int.MaxValue).Items.Where(t => t.GetType() == typeof(RecurringTrigger)); + var activeTriggers = _jobbrRepository.GetActiveTriggers(pageSize: int.MaxValue).Items.Where(t => t.GetType() == typeof(RecurringTrigger)); var additionalItems = new List(); foreach (var trigger in activeTriggers.Cast()) { - var planResult = this.GetPlanResult(trigger, false); + var planResult = GetPlanResult(trigger, false); if (planResult.Action == PlanAction.Possible) { // Check if there is already a run planned at this time - var nextRunForTrigger = this.repository.GetNextJobRunByTriggerId(trigger.JobId, trigger.Id, this.dateTimeProvider.GetUtcNow()); + var nextRunForTrigger = _jobbrRepository.GetNextJobRunByTriggerId(trigger.JobId, trigger.Id, _dateTimeProvider.GetUtcNow()); if (nextRunForTrigger == null || !nextRunForTrigger.PlannedStartDateTimeUtc.Equals(planResult.ExpectedStartDateUtc)) { - var scheduledItem = this.CreateNew(planResult, trigger); + var scheduledItem = CreateNew(planResult, trigger); additionalItems.Add(scheduledItem); } } @@ -246,10 +241,10 @@ private void EvaluateRecurringTriggers() if (additionalItems.Any()) { - Logger.Info($"The re-evaluation of recurring triggers caused the addition of {additionalItems.Count} scheduled items"); - this.currentPlan.AddRange(additionalItems); + _logger.LogInformation("The re-evaluation of recurring triggers caused the addition of {itemCount} scheduled items", additionalItems.Count); + _currentPlan.AddRange(additionalItems); - this.PublishCurrentPlan(); + PublishCurrentPlan(); } } } @@ -260,13 +255,13 @@ private ScheduledPlanItem CreateNew(PlanResult planResult, JobTriggerBase trigge if (!dateTime.HasValue) { - Logger.Warn($"Unable to gather an expected start date for trigger with id {trigger.Id}, (JobId: {trigger.JobId}), skipping."); + _logger.LogWarning("Unable to gather an expected start date for trigger with id {id}, (JobId: {jobId}), skipping.", trigger.Id, trigger.JobId); return null; } // Create the next occurrence from database - var newJobRun = this.CreateNewJobRun(trigger, dateTime.Value); + var newJobRun = CreateNewJobRun(trigger, dateTime.Value); // Add to the initial plan var newItem = new ScheduledPlanItem @@ -274,7 +269,7 @@ private ScheduledPlanItem CreateNew(PlanResult planResult, JobTriggerBase trigge TriggerId = trigger.Id, Id = newJobRun.Id, JobId = trigger.JobId, - PlannedStartDateTimeUtc = newJobRun.PlannedStartDateTimeUtc + PlannedStartDateTimeUtc = newJobRun.PlannedStartDateTimeUtc, }; return newItem; @@ -282,67 +277,68 @@ private ScheduledPlanItem CreateNew(PlanResult planResult, JobTriggerBase trigge private void SetScheduledJobRunsFromPastToOmitted() { - var dateTime = this.dateTimeProvider.GetUtcNow(); - var scheduledJobRuns = this.repository.GetJobRunsByState(JobRunStates.Scheduled, pageSize: int.MaxValue).Items.Where(p => p.PlannedStartDateTimeUtc < dateTime).ToList(); + var dateTime = _dateTimeProvider.GetUtcNow(); + var scheduledJobRuns = _jobbrRepository.GetJobRunsByState(JobRunStates.Scheduled, pageSize: int.MaxValue).Items.Where(p => p.PlannedStartDateTimeUtc < dateTime).ToList(); if (!scheduledJobRuns.Any()) { - Logger.Debug($"There were no jobs found that had been planned before {dateTime}"); + _logger.LogDebug("There were no jobs found that had been planned before {dateTime}", dateTime); return; } - - Logger.Info($"There were {scheduledJobRuns.Count} job runs that should have been started while the JobServer was not running. Need to omit them..."); + + _logger.LogInformation("There were {jobRunCount} job runs that should have been started while the JobServer was not running. Need to omit them...", scheduledJobRuns.Count); foreach (var jobRun in scheduledJobRuns) { jobRun.State = JobRunStates.Omitted; - this.repository.Update(jobRun); - Logger.Debug($"Omitted JobRun with id {jobRun.Id} for job {jobRun.Id} that has been planned for {jobRun.PlannedStartDateTimeUtc}"); + _jobbrRepository.Update(jobRun); + _logger.LogDebug("Omitted JobRun with id {jobRunId} for job {jobId} that has been planned for {plannedStartTime}", jobRun.Id, jobRun.Job.Id, jobRun.PlannedStartDateTimeUtc); } } private void SetRunningJobsToFailed() { - var runningJObRuns = this.repository.GetRunningJobs().ToList(); + var runningJobRuns = _jobbrRepository.GetRunningJobs().ToList(); - if (!runningJObRuns.Any()) + if (!runningJobRuns.Any()) { - Logger.Debug($"There were no uncompleted JobRuns while starting. The last shutdown seems to be healthy."); + _logger.LogDebug("There were no uncompleted JobRuns while starting. The last shutdown seems to be healthy."); return; } - Logger.Warn($"{runningJObRuns.Count} JobRuns are still in the 'Running'-State. They which may have crashed after an unhealthy shutdown."); - Logger.Info($"Need to manually set {runningJObRuns.Count} JobRuns to the state 'Failed'..."); - foreach (var jobRun in runningJObRuns) + _logger.LogWarning("{runningCount} JobRuns are still in the 'Running'-State. They which may have crashed after an unhealthy shutdown.", runningJobRuns.Count); + _logger.LogInformation("Need to manually set {runningCount} JobRuns to the state 'Failed'...", runningJobRuns.Count); + + foreach (var jobRun in runningJobRuns) { jobRun.State = JobRunStates.Failed; - this.repository.Update(jobRun); - - Logger.Debug($"Set JobRun with id {jobRun.Id} for job {jobRun.Id} to the state 'Failed'. Possible Reason: Unclean shutdown."); + _jobbrRepository.Update(jobRun); + + _logger.LogDebug("Set JobRun with id {jobRunId} for job {jobId} to the state 'Failed'. Possible Reason: Unclean shutdown.", jobRun.Id, jobRun.Job.Id); } } private void CreateInitialPlan() { - var activeTriggers = this.repository.GetActiveTriggers(pageSize: int.MaxValue).Items; + var activeTriggers = _jobbrRepository.GetActiveTriggers(pageSize: int.MaxValue).Items; var newPlan = new List(); foreach (var trigger in activeTriggers) { - PlanResult planResult = this.GetPlanResult(trigger as dynamic, false); + PlanResult planResult = GetPlanResult(trigger as dynamic, false); if (planResult.Action == PlanAction.Obsolete) { - Logger.WarnFormat($"Disabling trigger with id '{trigger.Id}', because startdate is in the past. (Type: '{trigger.GetType().Name}', userId: '{trigger.UserId}', userName: '{trigger.UserDisplayName}')"); + _logger.LogWarning("Disabling trigger with id '{id}', because start date is in the past. (Type: '{typeName}', userId: '{userId}', userName: '{name}')", trigger.Id, trigger.GetType().Name, trigger.UserId, trigger.UserDisplayName); - this.repository.DisableTrigger(trigger.JobId, trigger.Id); + _jobbrRepository.DisableTrigger(trigger.JobId, trigger.Id); continue; } if (planResult.Action == PlanAction.Blocked) { - // Cannot schedule jobrun, one reason could be that this job is not allowed to run because another jobrun is active + // Cannot schedule job run, one reason could be that this job is not allowed to run because another job run is active continue; } @@ -357,19 +353,19 @@ private void CreateInitialPlan() var dateTime = planResult.ExpectedStartDateUtc; // Get the next occurrence from database - var dependentJobRun = this.repository.GetNextJobRunByTriggerId(trigger.JobId, trigger.Id, this.dateTimeProvider.GetUtcNow()); + var dependentJobRun = _jobbrRepository.GetNextJobRunByTriggerId(trigger.JobId, trigger.Id, _dateTimeProvider.GetUtcNow()); if (dependentJobRun != null) { - this.UpdatePlannedJobRun(dependentJobRun, trigger, dateTime.Value); + UpdatePlannedJobRun(dependentJobRun, trigger, dateTime.Value); } else { - dependentJobRun = this.CreateNewJobRun(trigger, dateTime.Value); + dependentJobRun = CreateNewJobRun(trigger, dateTime.Value); } // Add to the initial plan - newPlan.Add(new ScheduledPlanItem() + newPlan.Add(new ScheduledPlanItem { TriggerId = trigger.Id, Id = dependentJobRun.Id, @@ -380,35 +376,35 @@ private void CreateInitialPlan() } // Set current plan - this.currentPlan = newPlan; + _currentPlan = newPlan; // Publish the initial plan top the Executor - this.PublishCurrentPlan(); + PublishCurrentPlan(); } private void PublishCurrentPlan() { - Logger.Info($"Getting new plan for upcoming scheduled jobs to the executor. Number of Items: {this.currentPlan.Count}"); + _logger.LogInformation("Getting new plan for upcoming scheduled jobs to the _executor. Number of Items: {planCount}", _currentPlan.Count); - var possibleJobRuns = MaxConcurrentJobRunPlaner.GetPossiblePlannedJobRuns(this.currentPlan, this.repository); - - Logger.Info($"Publishing new plan for upcoming planned jobs to the executor. Number of Items: {possibleJobRuns.Count}"); + var possibleJobRuns = MaxConcurrentJobRunPlaner.GetPossiblePlannedJobRuns(_currentPlan, _jobbrRepository); + + _logger.LogInformation("Publishing new plan for upcoming planned jobs to the _executor. Number of Items: {jobRunCount}", possibleJobRuns.Count); try { - this.executor.OnPlanChanged(possibleJobRuns); + _executor.OnPlanChanged(possibleJobRuns); } catch (Exception e) { - Logger.WarnException("Unable to publish current plan to Executor", e); + _logger.LogWarning("Unable to publish current plan to Executor. Exception: '{e}'", e); } } private JobRun CreateNewJobRun(JobTriggerBase trigger, DateTime dateTime) { - var job = this.repository.GetJob(trigger.JobId); + var job = _jobbrRepository.GetJob(trigger.JobId); - var jobRun = this.repository.SaveNewJobRun(job, trigger, dateTime); + var jobRun = _jobbrRepository.SaveNewJobRun(job, trigger, dateTime); return jobRun; } @@ -418,47 +414,46 @@ private void UpdatePlannedJobRun(JobRun plannedNextRun, JobTriggerBase trigger, // Is this value in sync with the schedule table? if (plannedNextRun.PlannedStartDateTimeUtc == calculatedNextRun) { - Logger.DebugFormat( - "The previously planned startdate '{0}' is still correct for JobRun (id: {1}) triggered by trigger with id '{2}' (Type: '{3}', userId: '{4}', userName: '{5}')", - calculatedNextRun, - plannedNextRun.Id, - trigger.Id, - trigger.GetType().Name, - trigger.UserId, - trigger.UserDisplayName); + _logger.LogDebug("The previously planned start date '{nextRunStart}' is still correct for JobRun (id: {nextRunId}) triggered by trigger with id '{triggerId}' (Type: '{triggerType}', userId: '{triggerUserId}', userName: '{triggerUserName}')", + calculatedNextRun, + plannedNextRun.Id, + trigger.Id, + trigger.GetType().Name, + trigger.UserId, + trigger.UserDisplayName); return; } // Was the change too close before the execution date? - var utcNow = this.dateTimeProvider.GetUtcNow(); + var utcNow = _dateTimeProvider.GetUtcNow(); - if (utcNow.AddSeconds(this.configuration.AllowChangesBeforeStartInSec) >= calculatedNextRun) + if (utcNow.AddSeconds(_schedulerConfiguration.AllowChangesBeforeStartInSec) >= calculatedNextRun) { - Logger.WarnFormat( - "The planned startdate '{0}' has changed to '{1}'. This change was done too close (less than {2} seconds) to the next planned run and cannot be adjusted", - plannedNextRun.PlannedStartDateTimeUtc, - calculatedNextRun, - this.configuration.AllowChangesBeforeStartInSec); + _logger.LogWarning( + "The planned start date '{startTime}' has changed to '{nextRunStart}'. This change was done too close (less than {changeWindowSecs} seconds) to the next planned run and cannot be adjusted", + plannedNextRun.PlannedStartDateTimeUtc, + calculatedNextRun, + _schedulerConfiguration.AllowChangesBeforeStartInSec); return; } - Logger.WarnFormat("The calculated startdate '{0}' has changed to '{1}', the planned jobRun needs to be updated as next step", plannedNextRun.PlannedStartDateTimeUtc, calculatedNextRun); + _logger.LogWarning("The calculated start date '{startTime}' has changed to '{nextRunStart}', the planned job run needs to be updated as next step", plannedNextRun.PlannedStartDateTimeUtc, calculatedNextRun); plannedNextRun.PlannedStartDateTimeUtc = calculatedNextRun; - this.repository.Update(plannedNextRun); + _jobbrRepository.Update(plannedNextRun); } - private PlanResult GetPlanResult(InstantTrigger trigger, bool isNew = false) => this.instantJobRunPlaner.Plan(trigger, isNew); + private PlanResult GetPlanResult(InstantTrigger trigger, bool isNew = false) => _instantJobRunPlanner.Plan(trigger, isNew); // ReSharper disable once UnusedParameter.Local // Reason: Parameter is used by dynamic overload - private PlanResult GetPlanResult(ScheduledTrigger trigger, bool isNew = false) => this.scheduledJobRunPlaner.Plan(trigger, isNew); + private PlanResult GetPlanResult(ScheduledTrigger trigger, bool isNew = false) => _scheduledJobRunPlanner.Plan(trigger, isNew); // ReSharper disable once UnusedParameter.Local // Reason: Parameter is used by dynamic overload - private PlanResult GetPlanResult(RecurringTrigger trigger, bool isNew = false) => this.recurringJobRunPlaner.Plan(trigger); + private PlanResult GetPlanResult(RecurringTrigger trigger, bool isNew = false) => _recurringJobRunPlanner.Plan(trigger); // ReSharper disable once UnusedParameter.Local // Reason: Parameter is used by dynamic overload diff --git a/source/Jobbr.Server/Scheduling/Planer/RecurringJobRunPlaner.cs b/source/Jobbr.Server/Scheduling/Planer/RecurringJobRunPlaner.cs index 39f145d..530afc9 100644 --- a/source/Jobbr.Server/Scheduling/Planer/RecurringJobRunPlaner.cs +++ b/source/Jobbr.Server/Scheduling/Planer/RecurringJobRunPlaner.cs @@ -1,22 +1,23 @@ using System; using System.Linq; using Jobbr.ComponentModel.JobStorage.Model; -using Jobbr.Server.Logging; using Jobbr.Server.Storage; +using Microsoft.Extensions.Logging; using NCrontab; namespace Jobbr.Server.Scheduling.Planer { public class RecurringJobRunPlaner { - private static readonly ILog Logger = LogProvider.For(); - private readonly JobbrRepository jobbrRepository; - private readonly IDateTimeProvider dateTimeProvider; + private readonly ILogger _logger; + private readonly JobbrRepository _jobbrRepository; + private readonly IDateTimeProvider _dateTimeProvider; - public RecurringJobRunPlaner(JobbrRepository repository, IDateTimeProvider dateTimeProvider) + public RecurringJobRunPlaner(ILogger logger, JobbrRepository jobbrRepository, IDateTimeProvider dateTimeProvider) { - this.jobbrRepository = repository; - this.dateTimeProvider = dateTimeProvider; + _logger = logger; + _jobbrRepository = jobbrRepository; + _dateTimeProvider = dateTimeProvider; } internal PlanResult Plan(RecurringTrigger trigger) @@ -26,29 +27,29 @@ internal PlanResult Plan(RecurringTrigger trigger) return PlanResult.FromAction(PlanAction.Obsolete); } - if (trigger.EndDateTimeUtc.HasValue && trigger.EndDateTimeUtc.Value < this.dateTimeProvider.GetUtcNow()) + if (trigger.EndDateTimeUtc.HasValue && trigger.EndDateTimeUtc.Value < _dateTimeProvider.GetUtcNow()) { - // This jobrun is not valid anymore + // This job run is not valid anymore return PlanResult.FromAction(PlanAction.Obsolete); } if (trigger.NoParallelExecution) { // find jobs that are running right now based on this trigger - var hasRunningJob = this.jobbrRepository.GetRunningJobs(trigger.JobId, trigger.Id).Any(); + var hasRunningJob = _jobbrRepository.GetRunningJobs(trigger.JobId, trigger.Id).Any(); if (hasRunningJob) { - var job = this.jobbrRepository.GetJob(trigger.JobId); + var job = _jobbrRepository.GetJob(trigger.JobId); - Logger.InfoFormat( - "No Parallel Execution: prevented planning of new JobRun for Job '{0}' (JobId: {1}). Caused by trigger with id '{2}' (Type: '{3}', userId: '{4}', userName: '{5}')", - job.UniqueName, - job.Id, - trigger.Id, - trigger.GetType().Name, - trigger.UserId, - trigger.UserDisplayName); + _logger.LogInformation( + "No Parallel Execution: prevented planning of new job run for Job '{jobName}' (JobId: {jobId}). Caused by trigger with id '{triggerId}' (Type: '{triggerType}', userId: '{userId}', userName: '{userName}')", + job.UniqueName, + job.Id, + trigger.Id, + trigger.GetType().Name, + trigger.UserId, + trigger.UserDisplayName); return PlanResult.FromAction(PlanAction.Blocked); } @@ -57,13 +58,13 @@ internal PlanResult Plan(RecurringTrigger trigger) DateTime baseTime; // Calculate the next occurrence based on current time or possible future startdate - if (trigger.StartDateTimeUtc.HasValue && trigger.StartDateTimeUtc.Value > this.dateTimeProvider.GetUtcNow()) + if (trigger.StartDateTimeUtc.HasValue && trigger.StartDateTimeUtc.Value > _dateTimeProvider.GetUtcNow()) { baseTime = trigger.StartDateTimeUtc.Value; } else { - baseTime = this.dateTimeProvider.GetUtcNow(); + baseTime = _dateTimeProvider.GetUtcNow(); } var schedule = CrontabSchedule.Parse(trigger.Definition); @@ -71,7 +72,7 @@ internal PlanResult Plan(RecurringTrigger trigger) return new PlanResult { Action = PlanAction.Possible, - ExpectedStartDateUtc = schedule.GetNextOccurrence(baseTime) + ExpectedStartDateUtc = schedule.GetNextOccurrence(baseTime), }; } } diff --git a/source/Jobbr.Server/Storage/JobbrRepository.cs b/source/Jobbr.Server/Storage/JobbrRepository.cs index 282bdd6..5e8bf7f 100644 --- a/source/Jobbr.Server/Storage/JobbrRepository.cs +++ b/source/Jobbr.Server/Storage/JobbrRepository.cs @@ -2,117 +2,117 @@ using System.Collections.Generic; using Jobbr.ComponentModel.JobStorage; using Jobbr.ComponentModel.JobStorage.Model; -using Jobbr.Server.Logging; +using Microsoft.Extensions.Logging; namespace Jobbr.Server.Storage { public class JobbrRepository : IJobbrRepository { - private static readonly ILog Logger = LogProvider.For(); + private readonly ILogger _logger; + private readonly IJobStorageProvider _jobStorageProvider; - private readonly IJobStorageProvider storageProvider; - - public JobbrRepository(IJobStorageProvider storageProvider) + public JobbrRepository(ILogger logger, IJobStorageProvider jobStorageProvider) { - this.storageProvider = storageProvider; + _logger = logger; + _jobStorageProvider = jobStorageProvider; } public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { - return this.storageProvider.GetJobs(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); + return _jobStorageProvider.GetJobs(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); } public Job GetJob(long id) { - return this.storageProvider.GetJobById(id); + return _jobStorageProvider.GetJobById(id); } public void UpdateJobRunProgress(long jobRunId, double progress) { - this.storageProvider.UpdateProgress(jobRunId, progress); + _jobStorageProvider.UpdateProgress(jobRunId, progress); } public void SetPidForJobRun(JobRun jobRun, int id) { jobRun.Pid = id; - this.storageProvider.Update(jobRun); + _jobStorageProvider.Update(jobRun); } public JobRun GetJobRun(long id) { - return this.storageProvider.GetJobRunById(id); + return _jobStorageProvider.GetJobRunById(id); } public void SaveAddTrigger(long jobId, RecurringTrigger trigger) { - this.storageProvider.AddTrigger(jobId, trigger); + _jobStorageProvider.AddTrigger(jobId, trigger); } public void UpdatePlannedStartDateTimeUtc(long jobRunId, DateTime plannedStartDateTimeUtc) { - var jobRun = this.storageProvider.GetJobRunById(jobRunId); + var jobRun = _jobStorageProvider.GetJobRunById(jobRunId); jobRun.PlannedStartDateTimeUtc = plannedStartDateTimeUtc; - this.Update(jobRun); + Update(jobRun); } public void SaveAddTrigger(long jobId, ScheduledTrigger trigger) { - this.storageProvider.AddTrigger(jobId, trigger); + _jobStorageProvider.AddTrigger(jobId, trigger); } public void SaveAddTrigger(long jobId, InstantTrigger trigger) { - this.storageProvider.AddTrigger(jobId, trigger); + _jobStorageProvider.AddTrigger(jobId, trigger); } public PagedResult GetJobRunsByStates(JobRunStates[] states, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { - return this.storageProvider.GetJobRunsByStates(states, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); + return _jobStorageProvider.GetJobRunsByStates(states, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); } public JobRun GetLastJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { - return this.storageProvider.GetLastJobRunByTriggerId(jobId, triggerId, utcNow); + return _jobStorageProvider.GetLastJobRunByTriggerId(jobId, triggerId, utcNow); } public JobRun GetNextJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { - return this.storageProvider.GetNextJobRunByTriggerId(jobId, triggerId, utcNow); + return _jobStorageProvider.GetNextJobRunByTriggerId(jobId, triggerId, utcNow); } public void EnableTrigger(long jobId, long triggerId) { // TODO: Move this logic to the storage adapter which can implement this more efficient - var trigger = this.storageProvider.GetTriggerById(jobId, triggerId); + var trigger = _jobStorageProvider.GetTriggerById(jobId, triggerId); - this.storageProvider.EnableTrigger(jobId, triggerId); + _jobStorageProvider.EnableTrigger(jobId, triggerId); } public PagedResult GetActiveTriggers(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, params string[] sort) { try { - return this.storageProvider.GetActiveTriggers(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, sort); + return _jobStorageProvider.GetActiveTriggers(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, sort); } catch (Exception e) { - Logger.FatalException("Cannot read active triggers from storage provider due to an exception. Returning empty list.", e); + _logger.LogCritical("Cannot read active triggers from storage provider due to an exception. Returning empty list. Exception: {e}", e); return new PagedResult { TotalItems = 0, Items = new List(), PageSize = pageSize, - Page = page + Page = page, }; } } public JobTriggerBase SaveUpdateTrigger(long jobId, JobTriggerBase trigger, out bool hadChanges) { - var triggerFromDb = this.storageProvider.GetTriggerById(jobId, trigger.Id); + var triggerFromDb = _jobStorageProvider.GetTriggerById(jobId, trigger.Id); hadChanges = false; @@ -123,7 +123,7 @@ public JobTriggerBase SaveUpdateTrigger(long jobId, JobTriggerBase trigger, out hadChanges = true; } - hadChanges = hadChanges || this.ApplyOtherChanges(triggerFromDb as dynamic, trigger as dynamic); + hadChanges = hadChanges || ApplyOtherChanges(triggerFromDb as dynamic, trigger as dynamic); if (hadChanges) { @@ -131,17 +131,17 @@ public JobTriggerBase SaveUpdateTrigger(long jobId, JobTriggerBase trigger, out if (trigger is InstantTrigger) { - this.storageProvider.Update(jobId, trigger as InstantTrigger); + _jobStorageProvider.Update(jobId, trigger as InstantTrigger); } if (trigger is ScheduledTrigger) { - this.storageProvider.Update(jobId, trigger as ScheduledTrigger); + _jobStorageProvider.Update(jobId, trigger as ScheduledTrigger); } if (trigger is RecurringTrigger) { - this.storageProvider.Update(jobId, trigger as RecurringTrigger); + _jobStorageProvider.Update(jobId, trigger as RecurringTrigger); } } @@ -150,12 +150,12 @@ public JobTriggerBase SaveUpdateTrigger(long jobId, JobTriggerBase trigger, out public PagedResult GetJobRunsByState(JobRunStates state, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { - return this.storageProvider.GetJobRunsByState(state, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); + return _jobStorageProvider.GetJobRunsByState(state, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); } public void AddJob(Job job) { - this.storageProvider.AddJob(job); + _jobStorageProvider.AddJob(job); } public JobRun SaveNewJobRun(Job job, JobTriggerBase trigger, DateTime plannedStartDateTimeUtc) @@ -170,77 +170,77 @@ public JobRun SaveNewJobRun(Job job, JobTriggerBase trigger, DateTime plannedSta PlannedStartDateTimeUtc = plannedStartDateTimeUtc }; - this.storageProvider.AddJobRun(jobRun); + _jobStorageProvider.AddJobRun(jobRun); return jobRun; } public void DisableTrigger(long jobId, long triggerId) { - this.storageProvider.DisableTrigger(jobId, triggerId); + _jobStorageProvider.DisableTrigger(jobId, triggerId); } public void DeleteTrigger(long jobId, long triggerId) { - this.storageProvider.DeleteTrigger(jobId, triggerId); + _jobStorageProvider.DeleteTrigger(jobId, triggerId); } public void Update(JobRun jobRun) { - this.storageProvider.Update(jobRun); + _jobStorageProvider.Update(jobRun); } public JobRun GetJobRunById(long jobRunId) { - return this.storageProvider.GetJobRunById(jobRunId); + return _jobStorageProvider.GetJobRunById(jobRunId); } public PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) { - return this.storageProvider.GetJobRunsByJobId(jobId, page, pageSize, showDeleted, sort); + return _jobStorageProvider.GetJobRunsByJobId(jobId, page, pageSize, showDeleted, sort); } public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) { - return this.storageProvider.GetJobRunsByTriggerId(jobId, triggerId, page, pageSize, showDeleted, sort); + return _jobStorageProvider.GetJobRunsByTriggerId(jobId, triggerId, page, pageSize, showDeleted, sort); } public JobTriggerBase GetTriggerById(long jobId, long triggerId) { - return this.storageProvider.GetTriggerById(jobId, triggerId); + return _jobStorageProvider.GetTriggerById(jobId, triggerId); } public PagedResult GetTriggersByJobId(long jobId, int page = 1, int pageSize = 50, bool showDeleted = false) { - return this.storageProvider.GetTriggersByJobId(jobId, page, pageSize, showDeleted); + return _jobStorageProvider.GetTriggersByJobId(jobId, page, pageSize, showDeleted); } public PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { - return this.storageProvider.GetJobRuns(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); + return _jobStorageProvider.GetJobRuns(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); } public PagedResult GetJobRunsByUserId(string userId, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) { - return this.storageProvider.GetJobRunsByUserId(userId, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); + return _jobStorageProvider.GetJobRunsByUserId(userId, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); } public PagedResult GetJobRunsByUserDisplayName(string userDisplayName, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) { - return this.storageProvider.GetJobRunsByUserDisplayName(userDisplayName, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); + return _jobStorageProvider.GetJobRunsByUserDisplayName(userDisplayName, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); } public Job GetJobByUniqueName(string identifier) { - return this.storageProvider.GetJobByUniqueName(identifier); + return _jobStorageProvider.GetJobByUniqueName(identifier); } public void Delete(JobRun jobRun) { - var jobRunFromStorage = this.storageProvider.GetJobRunById(jobRun.Id); + var jobRunFromStorage = _jobStorageProvider.GetJobRunById(jobRun.Id); jobRunFromStorage.State = JobRunStates.Deleted; - this.storageProvider.Update(jobRunFromStorage); + _jobStorageProvider.Update(jobRunFromStorage); } public IEnumerable GetRunningJobs() @@ -248,7 +248,7 @@ public IEnumerable GetRunningJobs() var minState = (int)JobRunStates.Scheduled + 1; var maxState = (int)JobRunStates.Completed - 1; - var jobRunsByStateRange = this.GetJobRunsByStateRange((JobRunStates)minState, (JobRunStates)maxState); + var jobRunsByStateRange = GetJobRunsByStateRange((JobRunStates)minState, (JobRunStates)maxState); foreach (var jobRun in jobRunsByStateRange) { @@ -258,7 +258,7 @@ public IEnumerable GetRunningJobs() public IEnumerable GetRunningJobs(long triggerJobId, long triggerId) { - var runningJobs = this.GetRunningJobs(); + var runningJobs = GetRunningJobs(); foreach (var jobRun in runningJobs) { @@ -280,7 +280,7 @@ public IEnumerable GetJobRunsByStateRange(JobRunStates minState, JobRunS { var currentState = (JobRunStates)i; - var jobRunsByState = this.GetJobRunsByState(currentState, 1, int.MaxValue); + var jobRunsByState = GetJobRunsByState(currentState, 1, int.MaxValue); foreach (var jobRun in jobRunsByState.Items) { @@ -317,7 +317,7 @@ private bool ApplyOtherChanges(RecurringTrigger fromDb, RecurringTrigger updated hadChanges = true; } - if (this.ApplyBaseChanges(fromDb, updatedOne)) + if (ApplyBaseChanges(fromDb, updatedOne)) { hadChanges = true; } @@ -336,7 +336,7 @@ private bool ApplyOtherChanges(ScheduledTrigger fromDb, ScheduledTrigger updated hadChanges = true; } - if (this.ApplyBaseChanges(fromDb, updatedOne)) + if (ApplyBaseChanges(fromDb, updatedOne)) { hadChanges = true; } @@ -377,14 +377,15 @@ private bool ApplyBaseChanges(JobTriggerBase fromDb, JobTriggerBase updatedOne) private bool ApplyOtherChanges(InstantTrigger fromDb, InstantTrigger updatedOne) { - Logger.WarnFormat("Cannot change an instant trigger!"); + _logger.LogWarning("Cannot change an instant trigger!"); return false; } private bool ApplyOtherChanges(object fromDb, object updatedOne) { - Logger.WarnFormat("Unknown trigger types: From: {1}, To: {2}!", fromDb.GetType(), updatedOne.GetType()); + _logger.LogWarning("Unknown trigger types: From: {fromDbType}, To: {updatedType}!", fromDb.GetType(), updatedOne.GetType()); + return false; } } diff --git a/source/Jobbr.Tests/Components/JobRunService/ProgressChannelTests.cs b/source/Jobbr.Tests/Components/JobRunService/ProgressChannelTests.cs index c44729d..7ceee71 100644 --- a/source/Jobbr.Tests/Components/JobRunService/ProgressChannelTests.cs +++ b/source/Jobbr.Tests/Components/JobRunService/ProgressChannelTests.cs @@ -18,13 +18,13 @@ public class ProgressUpdateTests public ProgressUpdateTests() { - var autoMapperConfig = new AutoMapperConfigurationFactory().GetNew(); + var autoMapperConfig = new AutoMapperConfigurationFactory(null).GetNew(); - this.repo = new JobbrRepository(new InMemoryJobStorageProvider()); + this.repo = new JobbrRepository(null, new InMemoryJobStorageProvider()); this.messengerHub = new TinyMessengerHub(); - this.service = new Server.Core.JobRunService(this.messengerHub, this.repo, null, autoMapperConfig.CreateMapper()); + this.service = new Server.Core.JobRunService(null, this.messengerHub, this.repo, null, autoMapperConfig.CreateMapper()); } private JobRun GivenAJobRun() diff --git a/source/Jobbr.Tests/Components/Scheduler/TestBase.cs b/source/Jobbr.Tests/Components/Scheduler/TestBase.cs index df47aa0..b2429a4 100644 --- a/source/Jobbr.Tests/Components/Scheduler/TestBase.cs +++ b/source/Jobbr.Tests/Components/Scheduler/TestBase.cs @@ -20,7 +20,7 @@ public class TestBase public TestBase() { - this.repository = new JobbrRepository(new InMemoryJobStorageProvider()); + this.repository = new JobbrRepository(null, new InMemoryJobStorageProvider()); var executorMock = new Mock(); executorMock.Setup(e => e.OnPlanChanged(It.IsNotNull>())).Callback>(p => this.lastIssuedPlan = p); @@ -33,9 +33,9 @@ public TestBase() this.repository.AddJob(job); this.demoJob1Id = job.Id; - this.scheduler = new DefaultScheduler(this.repository, executorMock.Object, + this.scheduler = new DefaultScheduler(null, this.repository, executorMock.Object, new InstantJobRunPlaner(this.currentTimeProvider), new ScheduledJobRunPlaner(this.currentTimeProvider), - new RecurringJobRunPlaner(this.repository, this.currentTimeProvider), new DefaultSchedulerConfiguration(), + new RecurringJobRunPlaner(null, this.repository, this.currentTimeProvider), new DefaultSchedulerConfiguration(), this.periodicTimer, this.currentTimeProvider); } } diff --git a/source/Jobbr.Tests/Integration/JobbrServerTestBase.cs b/source/Jobbr.Tests/Integration/JobbrServerTestBase.cs index 015e71f..861732b 100644 --- a/source/Jobbr.Tests/Integration/JobbrServerTestBase.cs +++ b/source/Jobbr.Tests/Integration/JobbrServerTestBase.cs @@ -45,7 +45,7 @@ protected static JobbrServer GivenAStartedServer() protected static JobbrServer GivenAServerInstance() { - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); builder.Register(typeof(ExposeAllServicesComponent)); diff --git a/source/Jobbr.Tests/Integration/Startup/BadEnvironmentTests.cs b/source/Jobbr.Tests/Integration/Startup/BadEnvironmentTests.cs index 5b237c4..737b805 100644 --- a/source/Jobbr.Tests/Integration/Startup/BadEnvironmentTests.cs +++ b/source/Jobbr.Tests/Integration/Startup/BadEnvironmentTests.cs @@ -15,7 +15,7 @@ public class BadEnvironmentTests [TestMethod] public void StartingJobber_GetsRunning_WhenStorageProviderTurnsHealthy() { - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); builder.Register(typeof(FaultyJobStorageProvider)); var jobbr = builder.Create(); @@ -34,7 +34,7 @@ public void StartingJobber_GetsRunning_WhenStorageProviderTurnsHealthy() [TestMethod] public void StartingJobbr_ComponentFails_IsInErrorState() { - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); builder.Register(typeof(FaultyComponent)); var jobbr = builder.Create(); @@ -55,7 +55,7 @@ public void StartingJobbr_ComponentFails_IsInErrorState() [ExpectedException(typeof(Exception))] public void StartingJobbr_ComponentFails_ExceptionIsThrown() { - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); builder.Register(typeof(FaultyComponent)); var jobbr = builder.Create(); diff --git a/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs b/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs index f2a539d..11bb08d 100644 --- a/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs +++ b/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs @@ -62,7 +62,7 @@ public bool Validate(object configuration) [TestMethod] public void ValidatorForSettings_WhenRegistered_IsCalled() { - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); builder.Add(new DemoSettings()); var isCalled = false; @@ -79,7 +79,7 @@ public void ValidatorForSettings_WhenRegistered_IsCalled() [TestMethod] public void ValidatorForSettings_WhenCalled_SettingsIsPassedThrough() { - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); var demoSettings = new DemoSettings(); object settingsToValidate = null; @@ -100,7 +100,7 @@ public void ValidatorForSettings_WhenCalled_SettingsIsPassedThrough() [ExpectedException(typeof(Exception))] public void ValidatorForSettings_ValidationFails_PreventsStart() { - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); builder.Add(new DemoSettings()); @@ -115,7 +115,7 @@ public void ValidatorForSettings_ValidationFails_PreventsStart() [ExpectedException(typeof(Exception))] public void ValidatorForSettings_ThrowsException_PreventsStart() { - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); builder.Add(new DemoSettings()); diff --git a/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs b/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs index 335ff31..4681504 100644 --- a/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs +++ b/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs @@ -35,7 +35,7 @@ public void CreateJobber_WithConsoleCapturer_CaptureMessagesFromConsole() { using (var capture = new ConsoleCapturer()) { - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); builder.Create(); @@ -49,7 +49,7 @@ public void CreateJobbr_WithNoStorageProvider_IssuesError() { using (var capture = new ConsoleCapturer()) { - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); // Register only Artefacts and Executor builder.Register(typeof(PseudoArtefactsStorageProvider)); @@ -70,7 +70,7 @@ public void CreateJobbr_WithNoArtefactsProvider_IssuesWarn() { using (var capture = new ConsoleCapturer()) { - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); // Register only Executor and JobStorage builder.Register(typeof(PseudoExecutor)); @@ -90,7 +90,7 @@ public void CreateJobbr_WithNoExecutor_IssuesError() { using (var capture = new ConsoleCapturer()) { - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); // Register only Artefacts and JoStorage builder.Register(typeof(PseudoArtefactsStorageProvider)); @@ -110,7 +110,7 @@ public void CreateJobbr_WithAllRequiredComponents_NoErrorNoWarn() { using (var capture = new ConsoleCapturer()) { - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); // Register only Artefacts and JoStorage builder.Register(typeof(PseudoArtefactsStorageProvider)); @@ -132,7 +132,7 @@ public void StartJobbr_WithAllRequiredComponents_NoErrorNoWarn() { using (var capture = new ConsoleCapturer()) { - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); // Register only Artefacts and JoStorage builder.Register(typeof(PseudoArtefactsStorageProvider)); diff --git a/source/Jobbr.Tests/Registration/BuilderTests.cs b/source/Jobbr.Tests/Registration/BuilderTests.cs index 443a493..edf788f 100644 --- a/source/Jobbr.Tests/Registration/BuilderTests.cs +++ b/source/Jobbr.Tests/Registration/BuilderTests.cs @@ -21,7 +21,7 @@ public class BuilderTests [TestMethod] public void RegisterCustomArtefactStorageProvider_AfterCreation_CorrectTypeIsActivated() { - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); builder.Register(typeof(CustomArtefactStorageAdapter)); builder.Register(typeof(ExposeAllServicesComponent)); @@ -36,7 +36,7 @@ public void RegisterCustomArtefactStorageProvider_AfterCreation_CorrectTypeIsAct [TestMethod] public void RegisterCustomJobStorageProvider_AfterCreation_CorrectTypeIsActivated() { - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); builder.Register(typeof(CustomJobStorageProvider)); builder.Register(typeof(ExposeAllServicesComponent)); @@ -56,8 +56,8 @@ public void ShouldDeleteJobsAndTriggers_WhenSingleSourceOfTruthIsActivated() const long nonExistingJobId = 2; const long existingTriggerId = 10; const long nonExistingTriggerId = 20; - var existingJob = new Job {Id = 1, UniqueName = existingJobName}; - var nonExistingJob = new Job {Id = 2, UniqueName = "DoIDieNow?"}; + var existingJob = new Job { Id = 1, UniqueName = existingJobName }; + var nonExistingJob = new Job { Id = 2, UniqueName = "DoIDieNow?" }; var pagedJobs = CreatePagedResult(existingJob, nonExistingJob); var triggerForExistingJob = new RecurringTrigger { Id = existingTriggerId, JobId = existingJobId }; var triggerForNonExistingJob = new RecurringTrigger { Id = nonExistingTriggerId, JobId = nonExistingJobId }; @@ -68,7 +68,7 @@ public void ShouldDeleteJobsAndTriggers_WhenSingleSourceOfTruthIsActivated() storage.Setup(s => s.GetTriggersByJobId(nonExistingJobId, 1, int.MaxValue, false)) .Returns(CreatePagedResult(triggerForNonExistingJob)); SetupForSuccessfulRun(storage); - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); builder.Add(storage.Object); builder.AddJobs(repo => repo.AsSingleSourceOfTruth().Define(existingJobName, "CLR.Type")); @@ -85,10 +85,10 @@ public void ShouldDeleteOrphanedTriggers_WhenSingleSourceOfTruthIsActivated() { const string jobName = "JobName"; var storage = new Mock(); - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); var job = new Job { Id = 1, UniqueName = jobName }; - var trigger = new RecurringTrigger { Definition = "0 * * * *", JobId = 1, Id = 1}; - var toDeleteTrigger = new RecurringTrigger { Definition = "0 1 * * *", JobId = 1, Id = 10}; + var trigger = new RecurringTrigger { Definition = "0 * * * *", JobId = 1, Id = 1 }; + var toDeleteTrigger = new RecurringTrigger { Definition = "0 1 * * *", JobId = 1, Id = 10 }; storage.Setup(s => s.GetJobs(1, int.MaxValue, null, null, null, false)).Returns(CreatePagedResult(job)); storage.Setup(s => s.GetTriggersByJobId(1, 1, int.MaxValue, false)) .Returns(CreatePagedResult(trigger, toDeleteTrigger)); @@ -110,7 +110,7 @@ public void ShouldReActivateJob_WhenJobIsRedefined() { const string jobName = "JobName"; var storage = new Mock(); - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); var job = new Job { Id = 1, UniqueName = jobName }; storage.Setup(s => s.GetJobs(1, int.MaxValue, null, null, null, false)).Returns(CreatePagedResult(job)); builder.AddJobs(repo => @@ -132,12 +132,12 @@ public void ShouldOmitScheduledJob_WhenJobIsDeactivated() var existingJob = new Job { Id = 1, UniqueName = existingJobName }; var nonExistingJob = new Job { Id = 2, UniqueName = "DoIDieNow?" }; var pagedJobs = CreatePagedResult(existingJob, nonExistingJob); - var toOmitJobRun = new JobRun {State = JobRunStates.Scheduled, Deleted = false}; + var toOmitJobRun = new JobRun { State = JobRunStates.Scheduled, Deleted = false }; var storage = new Mock(); storage.Setup(s => s.GetJobs(1, int.MaxValue, null, null, null, false)).Returns(pagedJobs); storage.Setup(s => s.GetJobRunsByJobId((int)nonExistingJobId, 1, int.MaxValue, false)) .Returns(CreatePagedResult(toOmitJobRun)); - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); builder.Add(storage.Object); builder.AddJobs(repo => repo.AsSingleSourceOfTruth().Define(existingJobName, "CLR.Type")); @@ -153,7 +153,7 @@ public void ShouldOmitScheduledJob_WhenTriggerIsDeactivated() { const string jobName = "JobName"; var storage = new Mock(); - var builder = new JobbrBuilder(); + var builder = new JobbrBuilder(null); var job = new Job { Id = 1, UniqueName = jobName }; var toDeleteTrigger = new RecurringTrigger { Definition = "0 1 * * *", JobId = 1, Id = 10 }; var toOmitJobRun = new JobRun { State = JobRunStates.Scheduled, Deleted = false }; diff --git a/source/JobbrRuleSet.ruleset b/source/JobbrRuleSet.ruleset index 5506b17..37c8e5f 100644 --- a/source/JobbrRuleSet.ruleset +++ b/source/JobbrRuleSet.ruleset @@ -1,5 +1,5 @@  - + @@ -101,7 +101,6 @@ - @@ -234,12 +233,20 @@ + + + + + + + + From 19120607c44c3caa81788f3210828af157788e43 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Wed, 16 Nov 2022 13:48:33 +0100 Subject: [PATCH 09/41] Replace Newtonsoft.Json with System.Text.Json --- README.md | 2 - source/Jobbr.Server.sln | 5 ++ source/Jobbr.Server/ConfigurationManager.cs | 28 ++----- .../Jobbr.Server/JobRegistry/JobDefinition.cs | 84 +++++++++++++++---- source/Jobbr.Server/Jobbr.Server.csproj | 1 - 5 files changed, 82 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 692d3db..9ec0f29 100644 --- a/README.md +++ b/README.md @@ -92,9 +92,7 @@ This software is licenced under GPLv3. See [LICENSE](LICENSE), please see the re Jobbr Server is based on following great open source projects: * [AutoMapper](https://github.com/AutoMapper/AutoMapper]) [(MIT)](https://github.com/AutoMapper/AutoMapper/blob/master/LICENSE.txt) -* [LibLog](https://github.com/damianh/LibLog) [(MIT)](https://github.com/damianh/LibLog/blob/master/licence.txt) * [NCrontab](https://github.com/atifaziz/NCrontab) [(Apache-2.0)](https://github.com/atifaziz/NCrontab/blob/master/COPYING.txt) -* [Newtonsoft Json.NET](https://github.com/JamesNK/Newtonsoft.Json) [(MIT)](https://github.com/JamesNK/Newtonsoft.Json/blob/master/LICENSE.md) * [Ninject](https://github.com/ninject/Ninject) [(Apache-2.0)](https://github.com/ninject/ninject/blob/master/LICENSE.txt) * [TinyMessenger](https://github.com/grumpydev/TinyMessenger/blob/master/licence.txt) [(Ms-PL)](https://github.com/grumpydev/TinyMessenger/blob/master/licence.txt) diff --git a/source/Jobbr.Server.sln b/source/Jobbr.Server.sln index 7a22aab..705636b 100644 --- a/source/Jobbr.Server.sln +++ b/source/Jobbr.Server.sln @@ -26,6 +26,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "submodules", "submodules", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jobbr.DevSupport.ReferencedVersionAsserter", "submodules\devsupport\src\Jobbr.DevSupport.ReferencedVersionAsserter\Jobbr.DevSupport.ReferencedVersionAsserter.csproj", "{D7C78DBD-D440-4D0C-B9A9-AD8B7473364A}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F17D736E-BFAE-4D06-A6FA-2F61EFCF458C}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/source/Jobbr.Server/ConfigurationManager.cs b/source/Jobbr.Server/ConfigurationManager.cs index d72d6c9..3ff15a5 100644 --- a/source/Jobbr.Server/ConfigurationManager.cs +++ b/source/Jobbr.Server/ConfigurationManager.cs @@ -2,12 +2,11 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using System.Reflection; +using System.Text.Json; +using System.Text.Json.Serialization; using Jobbr.ComponentModel.Registration; using Jobbr.Server.ComponentServices.Registration; using Microsoft.Extensions.Logging; -using Newtonsoft.Json; -using Newtonsoft.Json.Serialization; namespace Jobbr.Server { @@ -49,8 +48,12 @@ public void LogConfiguration() foreach (var config in _featureConfigurations) { - var jsonSettings = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore, ContractResolver = new IgnoreDelegatesFromSerializationContractResolver() }; - var serialized = JsonConvert.SerializeObject(config, jsonSettings); + var jsonSettings = new JsonSerializerOptions + { + ReferenceHandler = ReferenceHandler.IgnoreCycles + }; + + var serialized = JsonSerializer.Serialize(config, jsonSettings); serialized = serialized.Replace("{", "[", StringComparison.CurrentCulture); serialized = serialized.Replace("}", "]", StringComparison.CurrentCulture); @@ -126,20 +129,5 @@ public void ValidateConfigurationAndThrowOnErrors() throw new ArgumentNullException("Configuration failed for one or more configurations"); } } - - private class IgnoreDelegatesFromSerializationContractResolver : DefaultContractResolver - { - protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) - { - var property = base.CreateProperty(member, memberSerialization); - - if (typeof(MulticastDelegate).IsAssignableFrom(property.PropertyType.BaseType)) - { - property.ShouldSerialize = o => false; - } - - return property; - } - } } } \ No newline at end of file diff --git a/source/Jobbr.Server/JobRegistry/JobDefinition.cs b/source/Jobbr.Server/JobRegistry/JobDefinition.cs index fe68e37..ef36bfc 100644 --- a/source/Jobbr.Server/JobRegistry/JobDefinition.cs +++ b/source/Jobbr.Server/JobRegistry/JobDefinition.cs @@ -1,46 +1,86 @@ using System; using System.Collections.Generic; +using System.Text.Json; using Jobbr.ComponentModel.JobStorage.Model; -using Newtonsoft.Json; namespace Jobbr.Server.JobRegistry { + /// + /// Definition for a . + /// public class JobDefinition { - private readonly List triggers = new List(); + private readonly List _triggers = new (); + private bool _hasTriggerDefinition; - private bool hasTriggerDefinition; + /// + /// If trigger for the job has been defined. + /// + public bool HasTriggerDefinition => _hasTriggerDefinition; - public bool HasTriggerDefinition => this.hasTriggerDefinition; + /// + /// Determines how many s can be run at the same time. + /// + public int MaxConcurrentJobRuns { get; set; } + /// + /// Unique name for the . + /// internal string UniqueName { get; set; } + /// + /// CLR type for the . + /// internal string ClrType { get; set; } + /// + /// Parameter. + /// internal string Parameter { get; set; } - internal List Triggers => this.triggers; - public int MaxConcurrentJobRuns { get; set; } - + /// + /// List of triggers for the . + /// + internal List Triggers => _triggers; + + /// + /// Adds a trigger to the . + /// + /// Trigger start time. + /// Parameters for the trigger. + /// User ID. + /// User display name. + /// The resulting . public JobDefinition WithTrigger(DateTime startDateTimeUtc, object parameters = null, string userId = null, string userDisplayName = null) { - this.hasTriggerDefinition = true; + _hasTriggerDefinition = true; string parametersAsJson = null; if (parameters != null) { - parametersAsJson = JsonConvert.SerializeObject(parameters); + parametersAsJson = JsonSerializer.Serialize(parameters); } - this.triggers.Add(new ScheduledTrigger { StartDateTimeUtc = startDateTimeUtc, Parameters = parametersAsJson, UserId = userId, UserDisplayName = userDisplayName }); + _triggers.Add(new ScheduledTrigger { StartDateTimeUtc = startDateTimeUtc, Parameters = parametersAsJson, UserId = userId, UserDisplayName = userDisplayName }); return this; } + /// + /// Adds a trigger to the . + /// + /// CRON time definition for the trigger. + /// Validity start time. + /// Validity end time. + /// If parallel execution is allowed. + /// Parameters for the trigger. + /// User ID. + /// User display name. + /// The resulting . public JobDefinition WithTrigger(string cronDefinition, DateTime? validFromDateTimeUtc = null, DateTime? validToDateTimeUtc = null, bool noParallelExecution = false, object parameters = null, string userId = null, string userDisplayName = null) { - this.hasTriggerDefinition = true; + _hasTriggerDefinition = true; NCrontab.CrontabSchedule.Parse(cronDefinition); @@ -48,17 +88,31 @@ public JobDefinition WithTrigger(string cronDefinition, DateTime? validFromDateT if (parameters != null) { - parametersAsJson = JsonConvert.SerializeObject(parameters); + parametersAsJson = JsonSerializer.Serialize(parameters); } - - this.triggers.Add(new RecurringTrigger { StartDateTimeUtc = validFromDateTimeUtc, EndDateTimeUtc = validToDateTimeUtc, Definition = cronDefinition, NoParallelExecution = noParallelExecution, Parameters = parametersAsJson, UserId = userId, UserDisplayName = userDisplayName }); + + _triggers.Add(new RecurringTrigger + { + StartDateTimeUtc = validFromDateTimeUtc, + EndDateTimeUtc = validToDateTimeUtc, + Definition = cronDefinition, + NoParallelExecution = noParallelExecution, + Parameters = parametersAsJson, + UserId = userId, + UserDisplayName = userDisplayName + }); return this; } + /// + /// Adds a parameter to a . + /// + /// The parameter that is being added. + /// with the new parameter. public JobDefinition WithParameter(object parameter) { - this.Parameter = JsonConvert.SerializeObject(parameter); + Parameter = JsonSerializer.Serialize(parameter); return this; } diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index 9bacebc..3e50eac 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -29,7 +29,6 @@ - all From 1ee15e6705fda9912d61057bfbcc6d1376706e48 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Wed, 16 Nov 2022 14:19:25 +0100 Subject: [PATCH 10/41] Update AutoMapper from v. 7.0.1 to v. 12.0.0 --- .../Management/MappingProfile.cs | 42 ++++++++++--------- source/Jobbr.Server/Jobbr.Server.csproj | 2 +- source/Jobbr.Tests/Jobbr.Tests.csproj | 2 +- 3 files changed, 25 insertions(+), 21 deletions(-) diff --git a/source/Jobbr.Server/ComponentServices/Management/MappingProfile.cs b/source/Jobbr.Server/ComponentServices/Management/MappingProfile.cs index 1cf0b4e..2c28713 100644 --- a/source/Jobbr.Server/ComponentServices/Management/MappingProfile.cs +++ b/source/Jobbr.Server/ComponentServices/Management/MappingProfile.cs @@ -7,27 +7,31 @@ namespace Jobbr.Server.ComponentServices.Management { + /// + /// MappingProfiles for AutoMapper. + /// internal class MappingProfile : Profile { + /// + /// Initializes a new instance of the class. + /// public MappingProfile() { - this.AddMappingFromComponentToInternalModel(); - - this.AddMappingFromStorageToComponentModel(); - - this.AddMappingsFromInternalToComponentModel(); + AddMappingFromComponentToInternalModel(); + AddMappingFromStorageToComponentModel(); + AddMappingsFromInternalToComponentModel(); } private void AddMappingFromStorageToComponentModel() { - this.CreateMap(); - this.CreateMap(); + CreateMap(); + CreateMap(); - this.CreateMap().IncludeBase(); - this.CreateMap().IncludeBase(); - this.CreateMap().IncludeBase(); + CreateMap().IncludeBase(); + CreateMap().IncludeBase(); + CreateMap().IncludeBase(); - this.CreateMap() + CreateMap() .ForMember(m => m.Id, o => o.MapFrom(m => m.Id)) .ForMember(m => m.TriggerType, o => o.MapFrom(m => m.Trigger.GetType().Name)) .ForMember(m => m.JobType, o => o.MapFrom(m => m.Job.Type)) @@ -41,31 +45,31 @@ private void AddMappingFromStorageToComponentModel() .ForMember(m => m.JobName, o => o.MapFrom(m => m.Job.UniqueName)) .ForMember(m => m.PlannedStartDateTimeUtc, o => o.MapFrom(m => m.PlannedStartDateTimeUtc)) .ForMember(m => m.Progress, o => o.MapFrom(m => m.Progress)) - .ForMember(m => m.State, o => o.ResolveUsing(r => (ComponentModel.Management.Model.JobRunStates) Enum.Parse(typeof(ComponentModel.Management.Model.JobRunStates), r.State.ToString()))) + .ForMember(m => m.State, o => o.MapFrom(r => (ComponentModel.Management.Model.JobRunStates)Enum.Parse(typeof(ComponentModel.Management.Model.JobRunStates), r.State.ToString()))) .ForMember(m => m.TriggerId, o => o.MapFrom(m => m.Trigger.Id)) .ForMember(m => m.UserId, o => o.MapFrom(m => m.Trigger.UserId)) .ForMember(m => m.UserDisplayName, o => o.MapFrom(m => m.Trigger.UserDisplayName)) - .ForMember(m => m.Definition, o => o.ResolveUsing(r => (r.Trigger as ComponentModel.JobStorage.Model.RecurringTrigger)?.Definition)); + .ForMember(m => m.Definition, o => o.MapFrom(r => (r.Trigger as ComponentModel.JobStorage.Model.RecurringTrigger).Definition)); } private void AddMappingFromComponentToInternalModel() { - this.CreateMap() + CreateMap() .ForMember(d => d.CreatedDateTimeUtc, c => c.Ignore()); - this.CreateMap() + CreateMap() .ForMember(d => d.CreatedDateTimeUtc, c => c.Ignore()); - this.CreateMap() + CreateMap() .ForMember(d => d.CreatedDateTimeUtc, c => c.Ignore()); - this.CreateMap(); + CreateMap(); } private void AddMappingsFromInternalToComponentModel() { - this.CreateMap() - .ForMember(d => d.Type, cfg => cfg.ResolveUsing(s => s.MimeType)); + CreateMap() + .ForMember(d => d.Type, cfg => cfg.MapFrom(s => s.MimeType)); } } } diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index 3e50eac..8a735a5 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -26,7 +26,7 @@ - + diff --git a/source/Jobbr.Tests/Jobbr.Tests.csproj b/source/Jobbr.Tests/Jobbr.Tests.csproj index 9d2bab7..3969fcb 100644 --- a/source/Jobbr.Tests/Jobbr.Tests.csproj +++ b/source/Jobbr.Tests/Jobbr.Tests.csproj @@ -49,7 +49,7 @@ - + From 5e2722f5c663ac1592194cd02fa839420ab1d0a0 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Wed, 7 Dec 2022 11:52:48 +0100 Subject: [PATCH 11/41] Switch DI from Ninject to SimpleInjector and cleanup code --- README.md | 6 +- source/Jobbr.Server.nuspec | 8 +- .../Builder/AutoMapperConfigurationFactory.cs | 6 +- .../Builder/AutoMapperProvider.cs | 23 --- .../Jobbr.Server/Builder/DefaultContainer.cs | 61 +++++-- source/Jobbr.Server/Builder/JobbrBuilder.cs | 81 ++++++--- .../Execution/JobRunInformationService.cs | 6 +- .../Execution/JobRunProgressReceiver.cs | 4 +- .../Management/JobManagementService.cs | 66 ++++---- .../Registration/JobbrServiceProvider.cs | 45 ++--- source/Jobbr.Server/ConfigurationManager.cs | 20 +-- source/Jobbr.Server/Core/IJobRunService.cs | 62 +++++++ source/Jobbr.Server/Core/IJobService.cs | 26 +++ source/Jobbr.Server/Core/ITriggerService.cs | 81 +++++++++ source/Jobbr.Server/Core/JobRunService.cs | 49 ++---- source/Jobbr.Server/Core/JobService.cs | 33 ++-- .../Core/Messaging/IMessageDispatcher.cs | 13 ++ .../Core/Messaging/MessageDispatcher.cs | 30 ++-- .../Core/Models/InstantTriggerModel.cs | 8 +- .../Core/Models/RecurringTriggerModel.cs | 17 +- .../Core/Models/ScheduledTriggerModel.cs | 8 +- .../Core/Models/TriggerModelBase.cs | 32 +++- source/Jobbr.Server/Core/TriggerService.cs | 38 +++-- source/Jobbr.Server/IConfigurationManager.cs | 18 ++ .../JobRegistry/IRegistryBuilder.cs | 47 ++++++ .../JobRegistry/JobbrBuilderExtension.cs | 8 +- .../JobRegistry/RegistryBuilder.cs | 34 ++-- source/Jobbr.Server/Jobbr.Server.csproj | 6 +- source/Jobbr.Server/JobbrServer.cs | 8 +- .../Scheduling/DefaultScheduler.cs | 14 +- .../Scheduling/Planer/IInstantJobRunPlaner.cs | 18 ++ .../Planer/IRecurringJobRunPlaner.cs | 17 ++ .../Planer/IScheduledJobRunPlaner.cs | 18 ++ .../Scheduling/Planer/InstantJobRunPlaner.cs | 17 +- .../Scheduling/Planer/PlanResult.cs | 4 +- .../Planer/RecurringJobRunPlaner.cs | 17 +- .../Planer/ScheduledJobRunPlaner.cs | 17 +- .../Jobbr.Server/Storage/JobbrRepository.cs | 4 +- source/Jobbr.Server/TinyMessenger.cs | 157 ++++++++++++------ .../JobRunService/ProgressChannelTests.cs | 7 +- .../Components/Scheduler/TestBase.cs | 7 +- .../Integration/ExposeAllServicesComponent.cs | 18 +- .../Integration/JobbrServerTestBase.cs | 7 +- .../Startup/BadEnvironmentTests.cs | 15 +- .../Startup/ConfigurationValidationTests.cs | 25 +-- .../Integration/Startup/ConsoleCapturer.cs | 36 ++-- .../Startup/SetupValidationTests.cs | 55 +++++- source/Jobbr.Tests/Jobbr.Tests.csproj | 6 +- .../Jobbr.Tests/Registration/BuilderTests.cs | 140 ++++++++++------ 49 files changed, 998 insertions(+), 445 deletions(-) delete mode 100644 source/Jobbr.Server/Builder/AutoMapperProvider.cs create mode 100644 source/Jobbr.Server/Core/IJobRunService.cs create mode 100644 source/Jobbr.Server/Core/IJobService.cs create mode 100644 source/Jobbr.Server/Core/ITriggerService.cs create mode 100644 source/Jobbr.Server/Core/Messaging/IMessageDispatcher.cs create mode 100644 source/Jobbr.Server/IConfigurationManager.cs create mode 100644 source/Jobbr.Server/JobRegistry/IRegistryBuilder.cs create mode 100644 source/Jobbr.Server/Scheduling/Planer/IInstantJobRunPlaner.cs create mode 100644 source/Jobbr.Server/Scheduling/Planer/IRecurringJobRunPlaner.cs create mode 100644 source/Jobbr.Server/Scheduling/Planer/IScheduledJobRunPlaner.cs diff --git a/README.md b/README.md index 9ec0f29..83d9bdd 100644 --- a/README.md +++ b/README.md @@ -80,9 +80,6 @@ By default Jobbr runs in memory, thus all data is lost when Jobbr is restarted. - [Filesystem Storage Provider](https://github.com/jobbrIO/jobbr-artefactstorage-filesystem) to store the data in a folder - [RavenFS Storage Provider](https://github.com/jobbrIO/jobbr-artefactstorage-ravenfs) to store the data in [RavenDB](http://ravendb.net) -## Logging - -Jobbr uses the LibLog library to detect your Logging-Framework of the Hosting Process. When using Jobbr, you don't introduce a new dependency to an existing Logging-Framework. See https://github.com/damianh/LibLog for details. # License @@ -93,7 +90,7 @@ This software is licenced under GPLv3. See [LICENSE](LICENSE), please see the re Jobbr Server is based on following great open source projects: * [AutoMapper](https://github.com/AutoMapper/AutoMapper]) [(MIT)](https://github.com/AutoMapper/AutoMapper/blob/master/LICENSE.txt) * [NCrontab](https://github.com/atifaziz/NCrontab) [(Apache-2.0)](https://github.com/atifaziz/NCrontab/blob/master/COPYING.txt) -* [Ninject](https://github.com/ninject/Ninject) [(Apache-2.0)](https://github.com/ninject/ninject/blob/master/LICENSE.txt) +* [SimpleInjector](https://github.com/simpleinjector/SimpleInjector) [(MIT)](https://github.com/simpleinjector/SimpleInjector/blob/master/LICENSE) * [TinyMessenger](https://github.com/grumpydev/TinyMessenger/blob/master/licence.txt) [(Ms-PL)](https://github.com/grumpydev/TinyMessenger/blob/master/licence.txt) ## Credits @@ -106,3 +103,4 @@ This application was built by the following awesome developers: * [Steven Giesel](https://github.com/linkdotnet) * [David Fiebig](https://github.com/david-fiebig) * [Lukas Dürrenberger](https://github.com/eXpl0it3r) +* [Roope Kivioja](https://github.com/RKivioja) diff --git a/source/Jobbr.Server.nuspec b/source/Jobbr.Server.nuspec index c564605..e8d3a1e 100644 --- a/source/Jobbr.Server.nuspec +++ b/source/Jobbr.Server.nuspec @@ -12,11 +12,11 @@ Copyright 2022 images\icon.png - - - + + + - + diff --git a/source/Jobbr.Server/Builder/AutoMapperConfigurationFactory.cs b/source/Jobbr.Server/Builder/AutoMapperConfigurationFactory.cs index 496a2d1..1279e13 100644 --- a/source/Jobbr.Server/Builder/AutoMapperConfigurationFactory.cs +++ b/source/Jobbr.Server/Builder/AutoMapperConfigurationFactory.cs @@ -16,10 +16,10 @@ public class AutoMapperConfigurationFactory /// /// Initializes a new instance of the class. /// - /// The logger. - public AutoMapperConfigurationFactory(ILogger logger) + /// The logger factory. + public AutoMapperConfigurationFactory(ILoggerFactory loggerFactory) { - _logger = logger; + _logger = loggerFactory.CreateLogger(); } /// diff --git a/source/Jobbr.Server/Builder/AutoMapperProvider.cs b/source/Jobbr.Server/Builder/AutoMapperProvider.cs deleted file mode 100644 index 5ceed1b..0000000 --- a/source/Jobbr.Server/Builder/AutoMapperProvider.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using AutoMapper; -using Ninject.Activation; - -namespace Jobbr.Server.Builder -{ - internal class AutoMapperProvider : IProvider - { - private readonly MapperConfiguration mapperConfiguration; - - public AutoMapperProvider(MapperConfiguration mapperConfiguration) - { - this.mapperConfiguration = mapperConfiguration; - } - - public Type Type => typeof(IMapper); - - public object Create(IContext context) - { - return this.mapperConfiguration.CreateMapper(); - } - } -} \ No newline at end of file diff --git a/source/Jobbr.Server/Builder/DefaultContainer.cs b/source/Jobbr.Server/Builder/DefaultContainer.cs index 52b8bdb..ddaa7f4 100644 --- a/source/Jobbr.Server/Builder/DefaultContainer.cs +++ b/source/Jobbr.Server/Builder/DefaultContainer.cs @@ -1,21 +1,26 @@ -using AutoMapper; +using System; +using System.Collections.Generic; using Jobbr.ComponentModel.Execution; using Jobbr.ComponentModel.Management; using Jobbr.ComponentModel.Registration; using Jobbr.Server.ComponentServices.Execution; using Jobbr.Server.ComponentServices.Management; using Jobbr.Server.ComponentServices.Registration; +using Jobbr.Server.Core; +using Jobbr.Server.Core.Messaging; +using Jobbr.Server.JobRegistry; +using Jobbr.Server.Scheduling.Planer; using Jobbr.Server.Storage; using Microsoft.Extensions.Logging; -using Ninject; +using SimpleInjector; using TinyMessenger; namespace Jobbr.Server.Builder { /// - /// The kernel. + /// The default dependency injection container for Jobbr. /// - internal class DefaultContainer : StandardKernel + internal class DefaultContainer : Container { private readonly AutoMapperConfigurationFactory _autoMapperConfigurationFactory; @@ -24,7 +29,14 @@ internal class DefaultContainer : StandardKernel /// public DefaultContainer(ILoggerFactory loggerFactory) { - _autoMapperConfigurationFactory = new AutoMapperConfigurationFactory(loggerFactory.CreateLogger()); + // This is done so we can manually check for the services in the container and use in-memory ones if something is missing. + // SimpleInjector will throw an error if this is enabled. + Options.EnableAutoVerification = false; + + // This is allowed to provide overriding the defaults set in this class. + Options.AllowOverridingRegistrations = true; + + _autoMapperConfigurationFactory = new AutoMapperConfigurationFactory(loggerFactory); AddCoreServices(); AddAutoMapper(); AddComponentModelImplementations(); @@ -32,31 +44,50 @@ public DefaultContainer(ILoggerFactory loggerFactory) private void AddCoreServices() { - Bind().To().InSingletonScope(); - Bind().To().InSingletonScope(); + Register(Lifestyle.Singleton); + Register(Lifestyle.Singleton); } private void AddAutoMapper() { var config = _autoMapperConfigurationFactory.GetNew(); - Bind().ToConstant(config); - Bind().ToProvider(); + // RegisterInstance(config); + // Register(() => config.CreateMapper()); + RegisterInstance(config.CreateMapper()); } private void AddComponentModelImplementations() { // Registration - Bind().ToConstant(new JobbrServiceProvider(this)); + RegisterInstance(new JobbrServiceProvider(this)); // Management related services - Bind().To().InSingletonScope(); - Bind().To().InSingletonScope(); - Bind().To().InSingletonScope(); + Register(Lifestyle.Singleton); + Register(Lifestyle.Singleton); + Register(Lifestyle.Singleton); // Execution related services - Bind().To().InSingletonScope(); - Bind().To().InSingletonScope(); + Register(Lifestyle.Singleton); + Register(Lifestyle.Singleton); + + // Job run planners + Register(Lifestyle.Singleton); + Register(Lifestyle.Singleton); + Register(Lifestyle.Singleton); + + // Services + Register(Lifestyle.Singleton); + Register(Lifestyle.Singleton); + Register(Lifestyle.Singleton); + + Register(Lifestyle.Singleton); + Register(Lifestyle.Singleton); + Register(Lifestyle.Singleton); + + Collection.Register(typeof(IConfigurationValidator), new List()); + Collection.Register(typeof(IFeatureConfiguration), new List()); + Collection.Register(typeof(IJobbrComponent), new List()); } } } \ No newline at end of file diff --git a/source/Jobbr.Server/Builder/JobbrBuilder.cs b/source/Jobbr.Server/Builder/JobbrBuilder.cs index dbc8157..ff911ac 100644 --- a/source/Jobbr.Server/Builder/JobbrBuilder.cs +++ b/source/Jobbr.Server/Builder/JobbrBuilder.cs @@ -1,5 +1,4 @@ using System; -using System.Diagnostics.CodeAnalysis; using Jobbr.ComponentModel.ArtefactStorage; using Jobbr.ComponentModel.Execution; using Jobbr.ComponentModel.JobStorage; @@ -8,27 +7,28 @@ using Jobbr.Server.Scheduling; using Jobbr.Server.Storage; using Microsoft.Extensions.Logging; -using Ninject; +using SimpleInjector; namespace Jobbr.Server.Builder { /// /// Builder class for the entire Jobbr server. /// - [SuppressMessage("Design", "CA1001:Types that own disposable fields should be disposable", Justification = "Cannot dispose container, it is used for the jobbr-server instance.")] public class JobbrBuilder : IJobbrBuilder { private readonly ILogger _logger; - private readonly StandardKernel _container; + private readonly Container _dependencyContainer; /// /// Initializes a new instance of the class. /// - /// Factory for creating typed loggers. + /// The logger. public JobbrBuilder(ILoggerFactory loggerFactory) { + _dependencyContainer = new DefaultContainer(loggerFactory); + RegisterLogging(loggerFactory); + _logger = loggerFactory.CreateLogger(); - _container = new DefaultContainer(loggerFactory); } /// @@ -38,41 +38,41 @@ public JobbrBuilder(ILoggerFactory loggerFactory) /// A new . public JobbrServer Create(int maxConcurrentJobs = 4) { + _dependencyContainer.Register(); + // Register default implementations if user did not specify any separate - if (_container.TryGet() == null) + if (_dependencyContainer.GetRegistration(typeof(IJobStorageProvider)) == null) { _logger.LogError("There was no JobStorageProvider registered. Will continue building with an in-memory version, which does not support production scenarios."); - - var inMemoryJobStorageProvider = new InMemoryJobStorageProvider(); - _container.Bind().ToConstant(inMemoryJobStorageProvider); + _dependencyContainer.RegisterInstance(new InMemoryJobStorageProvider()); } // Register default implementations if user did not specify any separate - if (_container.TryGet() == null) + if (_dependencyContainer.GetRegistration(typeof(IArtefactsStorageProvider)) == null) { _logger.LogWarning("There was no ArtefactsStorageProvider registered. Adding a default InMemoryArtefactStorage, which stores artefacts in memory. Please register a proper ArtefactStorage for production use."); - var fileSystemArtefactsStorageProvider = new InMemoryArtefactsStorage(); - _container.Bind().ToConstant(fileSystemArtefactsStorageProvider); + _dependencyContainer.RegisterInstance(new InMemoryArtefactsStorage()); } // Register default implementations if user did not specify any separate - if (_container.TryGet() == null) + if (_dependencyContainer.GetRegistration(typeof(IJobExecutor)) == null) { _logger.LogError("There was no JobExecutor registered. Adding a Non-Operational JobExecutor"); - _container.Bind().To(); + _dependencyContainer.Register(Lifestyle.Singleton); } // Register default implementations if user did not specify any separate - if (_container.TryGet() == null) + if (_dependencyContainer.GetRegistration(typeof(IJobScheduler)) == null) { // Don't warn because the internal Scheduler is usually in use this.AddDefaultScheduler(); } - var serverManagementService = _container.TryGet(); + var serverMngmtRegistration = _dependencyContainer.GetRegistration(); - if (serverManagementService != null) + if (serverMngmtRegistration != null) { + var serverManagementService = _dependencyContainer.GetInstance(); serverManagementService.MaxConcurrentJobs = maxConcurrentJobs; } else @@ -80,22 +80,53 @@ public JobbrServer Create(int maxConcurrentJobs = 4) _logger.LogError("No Server Management Service found."); } - return _container.Get(); + return _dependencyContainer.GetInstance(); } + /// + /// Registers given implementation type to given service type as singleton. + /// + /// Service type. + /// Implementation type. public void Register(Type type) { - _container.Bind().To(type).InSingletonScope(); + _dependencyContainer.Register(typeof(T), type, Lifestyle.Singleton); } + /// + /// Registers given instance to given service type. + /// + /// Service type. + /// Instance to register. public void Add(object instance) { - if (instance is IFeatureConfiguration featureConfiguration) - { - _container.Bind().ToConstant(featureConfiguration); - } + _dependencyContainer.RegisterInstance(typeof(T), instance); + } - _container.Bind().ToConstant((T)instance); + /// + /// Appends given instance to a collection of service type registrations. + /// + /// Service type. + /// Instance to register. + public void AppendInstanceToCollection(object instance) + { + _dependencyContainer.Collection.AppendInstance(typeof(T), instance); + } + + /// + /// Appends given type to a collection of service type registrations. + /// + /// Service type. + /// Type to register. + public void AppendTypeToCollection(Type type) + { + _dependencyContainer.Collection.Append(typeof(T), type); + } + + private void RegisterLogging(ILoggerFactory loggerFactory) + { + _dependencyContainer.RegisterInstance(loggerFactory); + _dependencyContainer.RegisterSingleton(typeof(ILogger<>), typeof(Logger<>)); } } } \ No newline at end of file diff --git a/source/Jobbr.Server/ComponentServices/Execution/JobRunInformationService.cs b/source/Jobbr.Server/ComponentServices/Execution/JobRunInformationService.cs index fbcb60d..bf97382 100644 --- a/source/Jobbr.Server/ComponentServices/Execution/JobRunInformationService.cs +++ b/source/Jobbr.Server/ComponentServices/Execution/JobRunInformationService.cs @@ -18,12 +18,12 @@ internal class JobRunInformationService : IJobRunInformationService /// /// Initializes a new instance of the class. /// - /// The logger. + /// The logger factory. /// Repository that contains the jobs. /// The mapper. - public JobRunInformationService(ILogger logger, IJobbrRepository jobbrRepository, IMapper mapper) + public JobRunInformationService(ILoggerFactory loggerFactory, IJobbrRepository jobbrRepository, IMapper mapper) { - _logger = logger; + _logger = loggerFactory.CreateLogger(); _jobbrRepository = jobbrRepository; _mapper = mapper; } diff --git a/source/Jobbr.Server/ComponentServices/Execution/JobRunProgressReceiver.cs b/source/Jobbr.Server/ComponentServices/Execution/JobRunProgressReceiver.cs index ea4a51c..50aa565 100644 --- a/source/Jobbr.Server/ComponentServices/Execution/JobRunProgressReceiver.cs +++ b/source/Jobbr.Server/ComponentServices/Execution/JobRunProgressReceiver.cs @@ -11,7 +11,7 @@ namespace Jobbr.Server.ComponentServices.Execution /// internal class JobRunProgressReceiver : IJobRunProgressChannel { - private readonly JobRunService _jobRunService; + private readonly IJobRunService _jobRunService; private readonly IMapper _mapper; /// @@ -19,7 +19,7 @@ internal class JobRunProgressReceiver : IJobRunProgressChannel /// /// Job run service. /// The mapper. - public JobRunProgressReceiver(JobRunService jobRunService, IMapper mapper) + public JobRunProgressReceiver(IJobRunService jobRunService, IMapper mapper) { _jobRunService = jobRunService; _mapper = mapper; diff --git a/source/Jobbr.Server/ComponentServices/Management/JobManagementService.cs b/source/Jobbr.Server/ComponentServices/Management/JobManagementService.cs index 89a675a..9fd4782 100644 --- a/source/Jobbr.Server/ComponentServices/Management/JobManagementService.cs +++ b/source/Jobbr.Server/ComponentServices/Management/JobManagementService.cs @@ -14,48 +14,48 @@ namespace Jobbr.Server.ComponentServices.Management /// internal class JobManagementService : IJobManagementService { - private readonly TriggerService triggerService; - private readonly JobService jobService; - private readonly JobRunService jobRunService; + private readonly ITriggerService _triggerService; + private readonly IJobService _jobService; + private readonly IJobRunService _jobRunService; - private readonly IMapper mapper; + private readonly IMapper _mapper; - public JobManagementService(TriggerService triggerService, JobService jobService, JobRunService jobRunService, IMapper mapper) + public JobManagementService(ITriggerService triggerService, IJobService jobService, IJobRunService jobRunService, IMapper mapper) { - this.triggerService = triggerService; - this.jobService = jobService; - this.jobRunService = jobRunService; - this.mapper = mapper; + _triggerService = triggerService; + _jobService = jobService; + _jobRunService = jobRunService; + _mapper = mapper; } public void AddJob(Job job) { - var model = this.mapper.Map(job); + var model = _mapper.Map(job); - var newJOb = this.jobService.Add(model); + var newJOb = _jobService.Add(model); job.Id = newJOb.Id; } public void UpdateJob(Job job) { - var model = this.mapper.Map(job); + var model = _mapper.Map(job); - this.jobService.Update(model); + _jobService.Update(model); } public void DeleteJob(long jobId) { // TODO: implement :) // - terminate job if it is running - + throw new NotImplementedException(); } public void AddTrigger(long jobId, RecurringTrigger trigger) { - var model = this.mapper.Map(trigger); + var model = _mapper.Map(trigger); - this.triggerService.Add(jobId, model); + _triggerService.Add(jobId, model); trigger.Id = model.Id; trigger.JobId = jobId; @@ -63,9 +63,9 @@ public void AddTrigger(long jobId, RecurringTrigger trigger) public void AddTrigger(long jobId, ScheduledTrigger trigger) { - var model = this.mapper.Map(trigger); + var model = _mapper.Map(trigger); - this.triggerService.Add(jobId, model); + _triggerService.Add(jobId, model); trigger.Id = model.Id; trigger.JobId = jobId; @@ -73,9 +73,9 @@ public void AddTrigger(long jobId, ScheduledTrigger trigger) public void AddTrigger(long jobId, InstantTrigger trigger) { - var model = this.mapper.Map(trigger); + var model = _mapper.Map(trigger); - this.triggerService.Add(jobId, model); + _triggerService.Add(jobId, model); trigger.Id = model.Id; trigger.JobId = jobId; @@ -83,58 +83,58 @@ public void AddTrigger(long jobId, InstantTrigger trigger) public void DisableTrigger(long jobId, long triggerId) { - this.triggerService.Disable(jobId, triggerId); + _triggerService.Disable(jobId, triggerId); } public void EnableTrigger(long jobId, long triggerId) { - this.triggerService.Enable(jobId, triggerId); + _triggerService.Enable(jobId, triggerId); } public void DeleteTrigger(long jobId, long triggerId) { - this.triggerService.Delete(jobId, triggerId); + _triggerService.Delete(jobId, triggerId); } public void UpdateTriggerDefinition(long jobId, long triggerId, string definition) { - this.triggerService.Update(jobId, triggerId, definition); + _triggerService.Update(jobId, triggerId, definition); } public void Update(RecurringTrigger trigger) { - var triggerModel = this.mapper.Map(trigger); + var triggerModel = _mapper.Map(trigger); - this.triggerService.Update(triggerModel); + _triggerService.Update(triggerModel); } public void Update(ScheduledTrigger trigger) { - var triggerModel = this.mapper.Map(trigger); + var triggerModel = _mapper.Map(trigger); - this.triggerService.Update(triggerModel); + _triggerService.Update(triggerModel); } public void UpdateTriggerStartTime(long jobId, long triggerId, DateTime startDateTimeUtc) { - this.triggerService.Update(jobId, triggerId, startDateTimeUtc); + _triggerService.Update(jobId, triggerId, startDateTimeUtc); } public void DeleteJobRun(long jobRunId) { - this.jobRunService.Delete(jobRunId); + _jobRunService.Delete(jobRunId); } public List GetArtefactForJob(long jobRunId) { - var artefacts = this.jobRunService.GetArtefactsByJobRunId(jobRunId); + var artefacts = _jobRunService.GetArtefactsByJobRunId(jobRunId); - return this.mapper.Map>(artefacts); + return _mapper.Map>(artefacts); } public Stream GetArtefactAsStream(long jobRunId, string filename) { - return this.jobRunService.GetArtefactAsStream(jobRunId, filename); + return _jobRunService.GetArtefactAsStream(jobRunId, filename); } } } \ No newline at end of file diff --git a/source/Jobbr.Server/ComponentServices/Registration/JobbrServiceProvider.cs b/source/Jobbr.Server/ComponentServices/Registration/JobbrServiceProvider.cs index 30a3911..b1e5080 100644 --- a/source/Jobbr.Server/ComponentServices/Registration/JobbrServiceProvider.cs +++ b/source/Jobbr.Server/ComponentServices/Registration/JobbrServiceProvider.cs @@ -1,59 +1,60 @@ using System; using System.Collections.Generic; -using System.Diagnostics.CodeAnalysis; using Jobbr.ComponentModel.Registration; -using Ninject; +using SimpleInjector; namespace Jobbr.Server.ComponentServices.Registration { /// - /// The jobbr dependency resolver. + /// The Jobbr dependency resolver. /// - [SuppressMessage("Design", "CA2213:Disposable fields should be disposed", Justification = "Cannot disopose kernel, because it's an external dependency")] public class JobbrServiceProvider : IJobbrServiceProvider { /// - /// The ninject kernel. + /// The dependency injection container. /// - private readonly IKernel ninjectKernel; + private readonly Container _container; /// /// Initializes a new instance of the class. /// - /// - /// The ninject kernel. + /// + /// The dependency injection container. /// - public JobbrServiceProvider(IKernel ninjectKernel) + public JobbrServiceProvider(Container container) { - this.ninjectKernel = ninjectKernel; + _container = container; } /// - /// The get service. + /// Gets services based on the type. /// - /// - /// The service type. - /// - /// - /// The . - /// + /// Target service type. + /// An instance of the service as a generic object. public object GetService(Type serviceType) { - return this.ninjectKernel.TryGet(serviceType); + return _container.GetInstance(serviceType); } + /// + /// Gets a service wrapped inside a list. + /// + /// Target service type. + /// An instance of the service within a generic object list. public IEnumerable GetServices(Type serviceType) { - return new List(new[] { this.GetService(serviceType) }); + return new List(new[] { GetService(serviceType) }); } - #pragma warning disable CA1024 // Use properties where appropriate. + /// + /// Creates a new provider. + /// + /// A new instance of . public IJobbrServiceProvider GetChild() - #pragma warning restore CA1024 // Use properties where appropriate. { // If you need a request scoped container, please file a issue in GitHub. // Because the WebAPI is not request aware, we decided to keep this implementation - return new JobbrServiceProvider(this.ninjectKernel); + return new JobbrServiceProvider(_container); } } } \ No newline at end of file diff --git a/source/Jobbr.Server/ConfigurationManager.cs b/source/Jobbr.Server/ConfigurationManager.cs index 3ff15a5..2c37fb5 100644 --- a/source/Jobbr.Server/ConfigurationManager.cs +++ b/source/Jobbr.Server/ConfigurationManager.cs @@ -5,7 +5,6 @@ using System.Text.Json; using System.Text.Json.Serialization; using Jobbr.ComponentModel.Registration; -using Jobbr.Server.ComponentServices.Registration; using Microsoft.Extensions.Logging; namespace Jobbr.Server @@ -13,31 +12,29 @@ namespace Jobbr.Server /// /// Manages configuration for the Jobbr server. /// - public class ConfigurationManager + public class ConfigurationManager : IConfigurationManager { private readonly ILogger _logger; private readonly Collection _configurationValidators; - private readonly JobbrServiceProvider _jobbrServiceProvider; + private readonly IJobbrServiceProvider _jobbrServiceProvider; private readonly Collection _featureConfigurations; /// /// Initializes a new instance of the class. /// - /// The logger. + /// The logger factory. /// Collection of validators for the configurations. /// Jobbr dependency resolver. /// Configurations for the Jobbr server. - public ConfigurationManager(ILogger logger, Collection configurationValidators, JobbrServiceProvider jobbrServiceProvider, Collection featureConfigurations) + public ConfigurationManager(ILoggerFactory loggerFactory, Collection configurationValidators, IJobbrServiceProvider jobbrServiceProvider, Collection featureConfigurations) { - _logger = logger; + _logger = loggerFactory.CreateLogger(); _configurationValidators = configurationValidators; _jobbrServiceProvider = jobbrServiceProvider; _featureConfigurations = featureConfigurations; } - /// - /// Logs the current configurations. - /// + /// public void LogConfiguration() { if (_featureConfigurations == null || !_featureConfigurations.Any()) @@ -72,10 +69,7 @@ public void LogConfiguration() } } - /// - /// Validates configurations. - /// - /// At least one of the configuration validations failed. + /// public void ValidateConfigurationAndThrowOnErrors() { if (_configurationValidators == null || !_configurationValidators.Any()) diff --git a/source/Jobbr.Server/Core/IJobRunService.cs b/source/Jobbr.Server/Core/IJobRunService.cs new file mode 100644 index 0000000..84c3f0f --- /dev/null +++ b/source/Jobbr.Server/Core/IJobRunService.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using System.IO; +using Jobbr.Server.Core.Models; + +namespace Jobbr.Server.Core +{ + /// + /// Interface for job run services. + /// + public interface IJobRunService + { + /// + /// Update the progress of a job. + /// + /// ID for the job run. + /// How far the job has progressed. + void UpdateProgress(long jobRunId, double progress); + + /// + /// Update the state of a job. + /// + /// The ID of the job run. + /// The new state for the job. + void UpdateState(long jobRunId, JobRunStates state); + + /// + /// Gets job artifacts. + /// + /// ID of the job. + /// A list of s. List is empty if none are found or an error is thrown in the process. + List GetArtefactsByJobRunId(long jobRunId); + + /// + /// Gets a of artifacts for the job. + /// + /// ID of the job. + /// Target file to stream to. + /// An artifact pointed towards the file. Null if none are found or error is thrown in the process. + Stream GetArtefactAsStream(long jobRunId, string filename); + + /// + /// Adds an artifact to a job. + /// + /// ID of the job. + /// Filename of the file containing an artifact. + /// Result . + void AddArtefact(long jobRunId, string fileName, Stream result); + + /// + /// Updates the process ID of the job. + /// + /// ID of the job. + /// New process ID. + void UpdatePid(long jobRunId, int processId); + + /// + /// Deletes a job. + /// + /// ID of the job. + void Delete(long jobRunId); + } +} \ No newline at end of file diff --git a/source/Jobbr.Server/Core/IJobService.cs b/source/Jobbr.Server/Core/IJobService.cs new file mode 100644 index 0000000..a949460 --- /dev/null +++ b/source/Jobbr.Server/Core/IJobService.cs @@ -0,0 +1,26 @@ +using Jobbr.Server.Core.Models; + +namespace Jobbr.Server.Core +{ + public interface IJobService + { + /// + /// Adds a job to the repository. + /// + /// Model that is used for the creation of the job. + /// Model that has the job ID. + JobModel Add(JobModel model); + + /// + /// Updates a job. Throws NotImplementedException. + /// + /// Model for the updated job. + void Update(JobModel model); + + /// + /// Deletes a job from the repository. + /// + /// Job ID. + void Delete(long id); + } +} \ No newline at end of file diff --git a/source/Jobbr.Server/Core/ITriggerService.cs b/source/Jobbr.Server/Core/ITriggerService.cs new file mode 100644 index 0000000..048c4d1 --- /dev/null +++ b/source/Jobbr.Server/Core/ITriggerService.cs @@ -0,0 +1,81 @@ +using System; +using Jobbr.Server.Core.Models; + +namespace Jobbr.Server.Core +{ + /// + /// Interface for a trigger management service. + /// + public interface ITriggerService + { + /// + /// Adds a new recurring trigger to a job. + /// + /// ID of the job. + /// The model for the trigger. + void Add(long jobId, RecurringTriggerModel trigger); + + /// + /// Adds a new scheduled trigger to a job. + /// + /// ID of the job. + /// The model for the trigger. + void Add(long jobId, ScheduledTriggerModel trigger); + + /// + /// Adds a new instant trigger to a job. + /// + /// ID of the job. + /// The model for the trigger. + void Add(long jobId, InstantTriggerModel trigger); + + /// + /// Disables a trigger. + /// + /// Job ID. + /// Trigger ID. + void Disable(long jobId, long triggerId); + + /// + /// Deletes a trigger. + /// + /// Job ID + /// Trigger ID. + void Delete(long jobId, long triggerId); + + /// + /// Enables a trigger. + /// + /// Job ID. + /// Trigger ID. + void Enable(long jobId, long triggerId); + + /// + /// Updates a trigger definition. + /// + /// Job ID. + /// Trigger ID. + /// Trigger definition. + void Update(long jobId, long triggerId, string definition); + + /// + /// Updates a recurring trigger. + /// + /// Trigger model used for the update. + void Update(RecurringTriggerModel trigger); + + /// + /// Updates a scheduled trigger. + /// + /// Trigger model used for the update. + void Update(ScheduledTriggerModel trigger); + + /// + /// Updates a trigger start time. + /// + /// Job ID. + /// Trigger ID. + /// New start time in UTC. + void Update(long jobId, long triggerId, DateTime startDateTimeUtc); + } +} \ No newline at end of file diff --git a/source/Jobbr.Server/Core/JobRunService.cs b/source/Jobbr.Server/Core/JobRunService.cs index f9e3246..d5b28e7 100644 --- a/source/Jobbr.Server/Core/JobRunService.cs +++ b/source/Jobbr.Server/Core/JobRunService.cs @@ -14,7 +14,7 @@ namespace Jobbr.Server.Core /// /// Service for managing the job states, artifacts and IDs. /// - public class JobRunService + public class JobRunService : IJobRunService { private readonly ILogger _logger; private readonly ITinyMessengerHub _messengerHub; @@ -25,30 +25,22 @@ public class JobRunService /// /// Initializes a new instance of the class. /// - public JobRunService(ILogger logger, ITinyMessengerHub messengerHub, IJobbrRepository jobbrRepository, IArtefactsStorageProvider artefactsStorageProvider, IMapper mapper) + public JobRunService(ILoggerFactory loggerFactory, ITinyMessengerHub messengerHub, IJobbrRepository jobbrRepository, IArtefactsStorageProvider artefactsStorageProvider, IMapper mapper) { - _logger = logger; + _logger = loggerFactory.CreateLogger(); _messengerHub = messengerHub; _jobbrRepository = jobbrRepository; _artefactsStorageProvider = artefactsStorageProvider; _mapper = mapper; } - /// - /// Update the progress of a job. - /// - /// ID for the job run. - /// How far the job has progressed. + /// public void UpdateProgress(long jobRunId, double progress) { _jobbrRepository.UpdateJobRunProgress(jobRunId, progress); } - /// - /// Update the state of a job. - /// - /// The ID of the job run. - /// The new state for the job. + /// public void UpdateState(long jobRunId, JobRunStates state) { _logger.LogInformation("[{jobRunId}] The JobRun with id: {jobRunId} has switched to the '{state}'-State", jobRunId, jobRunId, state); @@ -74,11 +66,7 @@ public void UpdateState(long jobRunId, JobRunStates state) } } - /// - /// Gets job artifacts. - /// - /// ID of the job. - /// A list of s. List is empty if none are found or an error is thrown in the process. + /// public List GetArtefactsByJobRunId(long jobRunId) { try @@ -94,12 +82,7 @@ public List GetArtefactsByJobRunId(long jobRunId) return new List(); } - /// - /// Gets a of artifacts for the job. - /// - /// ID of the job. - /// Target file to stream to. - /// An artifact pointed towards the file. Null if none are found or error is thrown in the process. + /// public Stream GetArtefactAsStream(long jobRunId, string filename) { try @@ -114,22 +97,13 @@ public Stream GetArtefactAsStream(long jobRunId, string filename) return null; } - /// - /// Adds an artifact to a job. - /// - /// ID of the job. - /// Filename of the file containing an artifact. - /// Result . + /// public void AddArtefact(long jobRunId, string fileName, Stream result) { _artefactsStorageProvider.Save(jobRunId.ToString(), fileName, result); } - /// - /// Updates the process ID of the job. - /// - /// ID of the job. - /// New process ID. + /// public void UpdatePid(long jobRunId, int processId) { var jobRun = _jobbrRepository.GetJobRunById(jobRunId); @@ -138,10 +112,7 @@ public void UpdatePid(long jobRunId, int processId) _jobbrRepository.Update(jobRun); } - /// - /// Deletes a job. - /// - /// ID of the job. + /// public void Delete(long jobRunId) { var jobRun = _jobbrRepository.GetJobRunById(jobRunId); diff --git a/source/Jobbr.Server/Core/JobService.cs b/source/Jobbr.Server/Core/JobService.cs index 2197b82..8d8ddb2 100644 --- a/source/Jobbr.Server/Core/JobService.cs +++ b/source/Jobbr.Server/Core/JobService.cs @@ -6,32 +6,42 @@ namespace Jobbr.Server.Core { - public class JobService + /// + /// Service for jobs. + /// + public class JobService : IJobService { - private readonly IJobbrRepository repository; - private readonly IMapper mapper; - + private readonly IJobbrRepository _repository; + private readonly IMapper _mapper; + + /// + /// Initializes a new instance of the class. + /// + /// The Jobbr repository. + /// The mapper. public JobService(IJobbrRepository repository, IMapper mapper) { - this.repository = repository; - this.mapper = mapper; + _repository = repository; + _mapper = mapper; } + /// public JobModel Add(JobModel model) { - var entity = this.mapper.Map(model); + var entity = _mapper.Map(model); - this.repository.AddJob(entity); + _repository.AddJob(entity); model.Id = entity.Id; return model; } + /// public void Update(JobModel model) { - var entity = this.mapper.Map(model); + var entity = _mapper.Map(model); - var fromDb = this.repository.GetJob(model.Id); + var fromDb = _repository.GetJob(model.Id); fromDb.Parameters = entity.Parameters; fromDb.Title = entity.Title; @@ -40,9 +50,10 @@ public void Update(JobModel model) throw new NotImplementedException(); } + /// public void Delete(long id) { - var job = this.repository.GetJob(id); + var job = _repository.GetJob(id); job.Deleted = true; } } diff --git a/source/Jobbr.Server/Core/Messaging/IMessageDispatcher.cs b/source/Jobbr.Server/Core/Messaging/IMessageDispatcher.cs new file mode 100644 index 0000000..79f5301 --- /dev/null +++ b/source/Jobbr.Server/Core/Messaging/IMessageDispatcher.cs @@ -0,0 +1,13 @@ +namespace Jobbr.Server.Core.Messaging +{ + /// + /// Interface for message dispatchers. + /// + public interface IMessageDispatcher + { + /// + /// Subscribers all the different message types. + /// + void WireUp(); + } +} \ No newline at end of file diff --git a/source/Jobbr.Server/Core/Messaging/MessageDispatcher.cs b/source/Jobbr.Server/Core/Messaging/MessageDispatcher.cs index d502df7..396c287 100644 --- a/source/Jobbr.Server/Core/Messaging/MessageDispatcher.cs +++ b/source/Jobbr.Server/Core/Messaging/MessageDispatcher.cs @@ -1,28 +1,34 @@ -using System.Diagnostics.CodeAnalysis; using Jobbr.Server.Scheduling; using TinyMessenger; namespace Jobbr.Server.Core.Messaging { - [SuppressMessage("Design", "CA2213:Disposable fields should be disposed", Justification = "Cannot disopose scheduler, because it's an external dependency")] - public class MessageDispatcher + /// + /// Sets up message subscriptions. + /// + public class MessageDispatcher : IMessageDispatcher { - private readonly ITinyMessengerHub messengerHub; - private readonly IJobScheduler scheduler; + private readonly ITinyMessengerHub _messengerHub; + private readonly IJobScheduler _scheduler; + /// + /// Initializes a new instance of the class. + /// + /// The TinyMessenger message hub. + /// The job scheduler. public MessageDispatcher(ITinyMessengerHub messengerHub, IJobScheduler scheduler) { - this.messengerHub = messengerHub; - this.scheduler = scheduler; + _messengerHub = messengerHub; + _scheduler = scheduler; } + /// public void WireUp() { - this.messengerHub.Subscribe(m => this.scheduler.OnTriggerAdded(m.JobId, m.TriggerId)); - this.messengerHub.Subscribe(m => this.scheduler.OnTriggerDefinitionUpdated(m.JobId, m.TriggerId)); - this.messengerHub.Subscribe(m => this.scheduler.OnTriggerStateUpdated(m.JobId, m.TriggerId)); - - this.messengerHub.Subscribe(m => this.scheduler.OnJobRunEnded(m.Id)); + _messengerHub.Subscribe(m => _scheduler.OnTriggerAdded(m.JobId, m.TriggerId)); + _messengerHub.Subscribe(m => _scheduler.OnTriggerDefinitionUpdated(m.JobId, m.TriggerId)); + _messengerHub.Subscribe(m => _scheduler.OnTriggerStateUpdated(m.JobId, m.TriggerId)); + _messengerHub.Subscribe(m => _scheduler.OnJobRunEnded(m.Id)); } } } \ No newline at end of file diff --git a/source/Jobbr.Server/Core/Models/InstantTriggerModel.cs b/source/Jobbr.Server/Core/Models/InstantTriggerModel.cs index 2e8b85f..f963659 100644 --- a/source/Jobbr.Server/Core/Models/InstantTriggerModel.cs +++ b/source/Jobbr.Server/Core/Models/InstantTriggerModel.cs @@ -1,7 +1,13 @@ namespace Jobbr.Server.Core.Models { - internal class InstantTriggerModel : TriggerModelBase + /// + /// Model for an instant trigger. + /// + public class InstantTriggerModel : TriggerModelBase { + /// + /// Delay in minutes. + /// public int DelayedMinutes { get; set; } } } \ No newline at end of file diff --git a/source/Jobbr.Server/Core/Models/RecurringTriggerModel.cs b/source/Jobbr.Server/Core/Models/RecurringTriggerModel.cs index 5b711a3..694b244 100644 --- a/source/Jobbr.Server/Core/Models/RecurringTriggerModel.cs +++ b/source/Jobbr.Server/Core/Models/RecurringTriggerModel.cs @@ -2,14 +2,29 @@ namespace Jobbr.Server.Core.Models { - internal class RecurringTriggerModel : TriggerModelBase + /// + /// Model for recurring trigger. + /// + public class RecurringTriggerModel : TriggerModelBase { + /// + /// Trigger definition. + /// public string Definition { get; set; } + /// + /// Trigger start time. + /// public DateTime? StartDateTimeUtc { get; set; } + /// + /// Trigger end time. + /// public DateTime? EndDateTimeUtc { get; set; } + /// + /// If parallel execution is allowed. + /// public bool NoParallelExecution { get; set; } } } \ No newline at end of file diff --git a/source/Jobbr.Server/Core/Models/ScheduledTriggerModel.cs b/source/Jobbr.Server/Core/Models/ScheduledTriggerModel.cs index 8a44964..351bbc2 100644 --- a/source/Jobbr.Server/Core/Models/ScheduledTriggerModel.cs +++ b/source/Jobbr.Server/Core/Models/ScheduledTriggerModel.cs @@ -2,8 +2,14 @@ namespace Jobbr.Server.Core.Models { - internal class ScheduledTriggerModel : TriggerModelBase + /// + /// Model for a scheduled trigger. + /// + public class ScheduledTriggerModel : TriggerModelBase { + /// + /// Start time. + /// public DateTime StartDateTimeUtc { get; set; } } } \ No newline at end of file diff --git a/source/Jobbr.Server/Core/Models/TriggerModelBase.cs b/source/Jobbr.Server/Core/Models/TriggerModelBase.cs index 0541e88..ca04fce 100644 --- a/source/Jobbr.Server/Core/Models/TriggerModelBase.cs +++ b/source/Jobbr.Server/Core/Models/TriggerModelBase.cs @@ -2,24 +2,54 @@ namespace Jobbr.Server.Core.Models { - internal class TriggerModelBase + /// + /// Base class for trigger models. + /// + public class TriggerModelBase { + /// + /// Comment. + /// public string Comment { get; set; } + /// + /// The ID of the job. + /// public long JobId { get; set; } + /// + /// Trigger parameters. + /// public string Parameters { get; set; } + /// + /// If trigger is active. + /// public bool IsActive { get; set; } + /// + /// User display name. + /// public string UserDisplayName { get; set; } + /// + /// User ID. + /// public string UserId { get; set; } + /// + /// Trigger ID. + /// public long Id { get; set; } + /// + /// Creation time in UTC. + /// public DateTime CreatedDateTimeUtc { get; set; } + /// + /// If trigger has been deleted. + /// public bool Deleted { get; set; } } } \ No newline at end of file diff --git a/source/Jobbr.Server/Core/TriggerService.cs b/source/Jobbr.Server/Core/TriggerService.cs index b53784d..daf9ef3 100644 --- a/source/Jobbr.Server/Core/TriggerService.cs +++ b/source/Jobbr.Server/Core/TriggerService.cs @@ -12,7 +12,7 @@ namespace Jobbr.Server.Core /// /// Service for managing triggers. /// - internal class TriggerService + internal class TriggerService : ITriggerService { private readonly ILogger _logger; private readonly IJobbrRepository _jobbrRepository; @@ -22,19 +22,20 @@ internal class TriggerService /// /// Initializes a new instance of the class. /// - /// The logger. + /// The logger factory. /// Repository for accessing job data, /// SubPub messenger hub. /// The mapper. - public TriggerService(ILogger logger, IJobbrRepository jobbrRepository, ITinyMessengerHub messengerHub, IMapper mapper) + public TriggerService(ILoggerFactory loggerFactory, IJobbrRepository jobbrRepository, ITinyMessengerHub messengerHub, IMapper mapper) { - _logger = logger; + _logger = loggerFactory.CreateLogger(); _jobbrRepository = jobbrRepository; _messengerHub = messengerHub; _mapper = mapper; } - internal void Add(long jobId, RecurringTriggerModel trigger) + /// + public void Add(long jobId, RecurringTriggerModel trigger) { var triggerEntity = _mapper.Map(trigger); @@ -45,7 +46,8 @@ internal void Add(long jobId, RecurringTriggerModel trigger) _messengerHub.PublishAsync(new TriggerAddedMessage(this, new TriggerKey { JobId = triggerEntity.JobId, TriggerId = triggerEntity.Id })); } - internal void Add(long jobId, ScheduledTriggerModel trigger) + /// + public void Add(long jobId, ScheduledTriggerModel trigger) { var triggerEntity = _mapper.Map(trigger); @@ -56,7 +58,8 @@ internal void Add(long jobId, ScheduledTriggerModel trigger) _messengerHub.PublishAsync(new TriggerAddedMessage(this, new TriggerKey { JobId = triggerEntity.JobId, TriggerId = triggerEntity.Id })); } - internal void Add(long jobId, InstantTriggerModel trigger) + /// + public void Add(long jobId, InstantTriggerModel trigger) { var triggerEntity = _mapper.Map(trigger); @@ -67,27 +70,31 @@ internal void Add(long jobId, InstantTriggerModel trigger) _messengerHub.PublishAsync(new TriggerAddedMessage(this, new TriggerKey { JobId = triggerEntity.JobId, TriggerId = triggerEntity.Id })); } - internal void Disable(long jobId, long triggerId) + /// + public void Disable(long jobId, long triggerId) { _jobbrRepository.DisableTrigger(jobId, triggerId); _messengerHub.PublishAsync(new TriggerStateChangedMessage(this, new TriggerKey { JobId = jobId, TriggerId = triggerId })); } - internal void Delete(long jobId, long triggerId) + /// + public void Delete(long jobId, long triggerId) { _jobbrRepository.DeleteTrigger(jobId, triggerId); _messengerHub.PublishAsync(new TriggerStateChangedMessage(this, new TriggerKey { JobId = jobId, TriggerId = triggerId })); } - internal void Enable(long jobId, long triggerId) + /// + public void Enable(long jobId, long triggerId) { _jobbrRepository.EnableTrigger(jobId, triggerId); _messengerHub.PublishAsync(new TriggerStateChangedMessage(this, new TriggerKey { JobId = jobId, TriggerId = triggerId })); } + /// // TODO: combine update methods, too much copy-paste here - internal void Update(long jobId, long triggerId, string definition) + public void Update(long jobId, long triggerId, string definition) { var trigger = _jobbrRepository.GetTriggerById(jobId, triggerId); @@ -109,7 +116,8 @@ internal void Update(long jobId, long triggerId, string definition) } } - internal void Update(RecurringTriggerModel trigger) + /// + public void Update(RecurringTriggerModel trigger) { var triggerEntity = _mapper.Map(trigger); @@ -130,7 +138,8 @@ internal void Update(RecurringTriggerModel trigger) } } - internal void Update(ScheduledTriggerModel trigger) + /// + public void Update(ScheduledTriggerModel trigger) { var triggerEntity = _mapper.Map(trigger); @@ -151,7 +160,8 @@ internal void Update(ScheduledTriggerModel trigger) } } - internal void Update(long jobId, long triggerId, DateTime startDateTimeUtc) + /// + public void Update(long jobId, long triggerId, DateTime startDateTimeUtc) { var trigger = _jobbrRepository.GetTriggerById(jobId, triggerId); diff --git a/source/Jobbr.Server/IConfigurationManager.cs b/source/Jobbr.Server/IConfigurationManager.cs new file mode 100644 index 0000000..ef1f3f7 --- /dev/null +++ b/source/Jobbr.Server/IConfigurationManager.cs @@ -0,0 +1,18 @@ +namespace Jobbr.Server +{ + /// + /// Interface for configuration managers. + /// + public interface IConfigurationManager + { + /// + /// Logs the current configurations. + /// + void LogConfiguration(); + + /// + /// Validates configurations and throws errors if they are not valid. + /// + void ValidateConfigurationAndThrowOnErrors(); + } +} \ No newline at end of file diff --git a/source/Jobbr.Server/JobRegistry/IRegistryBuilder.cs b/source/Jobbr.Server/JobRegistry/IRegistryBuilder.cs new file mode 100644 index 0000000..8c2c7b1 --- /dev/null +++ b/source/Jobbr.Server/JobRegistry/IRegistryBuilder.cs @@ -0,0 +1,47 @@ +using Jobbr.ComponentModel.JobStorage; +using System; + +namespace Jobbr.Server.JobRegistry +{ + /// + /// Interface for a registry builder. + /// + public interface IRegistryBuilder + { + /// + /// Sets HasConfiguration to true and returns the current . + /// + /// itself. + RegistryBuilder RemoveAll(); + + /// + /// Sets isSingleSourceOfTruth to true. + /// + /// itself. + RegistryBuilder AsSingleSourceOfTruth(); + + /// + /// Adds a new . + /// + /// The job type that is being defined. + /// The maximum amount of concurrent job runs. + /// The created . + JobDefinition Define(Type jobType, int maxConcurrentJobRuns = 0); + + /// + /// Adds a new . + /// + /// Name of the job definition. + /// Name of the target type. + /// The maximum amount of concurrent job runs. + /// The created . + JobDefinition Define(string uniqueName, string typeName, int maxConcurrentJobRuns = 0); + + /// + /// Applies new s if available. + /// + /// Storage provider where to apply the new s. + /// The number of changes. + int Apply(IJobStorageProvider storage); + } +} \ No newline at end of file diff --git a/source/Jobbr.Server/JobRegistry/JobbrBuilderExtension.cs b/source/Jobbr.Server/JobRegistry/JobbrBuilderExtension.cs index db9554e..b593c79 100644 --- a/source/Jobbr.Server/JobRegistry/JobbrBuilderExtension.cs +++ b/source/Jobbr.Server/JobRegistry/JobbrBuilderExtension.cs @@ -1,5 +1,6 @@ using System; using Jobbr.ComponentModel.Registration; +using Microsoft.Extensions.Logging; namespace Jobbr.Server.JobRegistry { @@ -12,15 +13,16 @@ public static class JobbrBuilderExtension /// Extract jobs from given and add to a . /// /// where the jobs are added. + /// The logger factory. /// Typed that contains the jobs. /// The original with the added jobs. - public static IJobbrBuilder AddJobs(this IJobbrBuilder builder, Action repository) + public static IJobbrBuilder AddJobs(this IJobbrBuilder builder, ILoggerFactory loggerFactory, Action repository) { - var repoBuilder = new RegistryBuilder(null); + var repoBuilder = new RegistryBuilder(loggerFactory); repository(repoBuilder); - builder.Add(repoBuilder); + builder.Add(repoBuilder); return builder; } diff --git a/source/Jobbr.Server/JobRegistry/RegistryBuilder.cs b/source/Jobbr.Server/JobRegistry/RegistryBuilder.cs index ae3e6e4..d3b509f 100644 --- a/source/Jobbr.Server/JobRegistry/RegistryBuilder.cs +++ b/source/Jobbr.Server/JobRegistry/RegistryBuilder.cs @@ -10,25 +10,31 @@ namespace Jobbr.Server.JobRegistry /// /// Builds a registry that contains jobs, job descriptions and their triggers. /// - public class RegistryBuilder + public class RegistryBuilder : IRegistryBuilder { private readonly ILogger _logger; - private readonly List _definitions = new (); private bool _isSingleSourceOfTruth; - internal bool HasConfiguration { get; private set; } - - internal List Definitions => _definitions; - /// /// Initializes a new instance of the class. /// - /// The logger. - public RegistryBuilder(ILogger logger) + /// The logger. + public RegistryBuilder(ILoggerFactory loggerFactory) { - _logger = logger; + _logger = loggerFactory.CreateLogger(); } + /// + /// If registry builder has a configuration. + /// + internal bool HasConfiguration { get; private set; } + + /// + /// Accessor for s. + /// + internal List Definitions { get; } = new (); + + /// public RegistryBuilder RemoveAll() { HasConfiguration = true; @@ -36,12 +42,14 @@ public RegistryBuilder RemoveAll() return this; } + /// public RegistryBuilder AsSingleSourceOfTruth() { _isSingleSourceOfTruth = true; return this; } + /// public JobDefinition Define(Type jobType, int maxConcurrentJobRuns = 0) { if (jobType == null) @@ -52,9 +60,10 @@ public JobDefinition Define(Type jobType, int maxConcurrentJobRuns = 0) return Define(jobType.Name, jobType.FullName, maxConcurrentJobRuns); } + /// public JobDefinition Define(string uniqueName, string typeName, int maxConcurrentJobRuns = 0) { - var existing = _definitions.FirstOrDefault(d => string.Equals(d.UniqueName, uniqueName, StringComparison.OrdinalIgnoreCase)); + var existing = Definitions.FirstOrDefault(d => string.Equals(d.UniqueName, uniqueName, StringComparison.OrdinalIgnoreCase)); if (existing != null) { @@ -63,14 +72,15 @@ public JobDefinition Define(string uniqueName, string typeName, int maxConcurren } var definition = new JobDefinition() { UniqueName = uniqueName, ClrType = typeName, MaxConcurrentJobRuns = maxConcurrentJobRuns }; - _definitions.Add(definition); + Definitions.Add(definition); HasConfiguration = true; return definition; } - internal int Apply(IJobStorageProvider storage) + /// + public int Apply(IJobStorageProvider storage) { var numberOfChanges = 0; diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index 8a735a5..59be916 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -6,7 +6,7 @@ Zuehlke Technology Group Jobbr.Server Copyright © Zuehlke Technology Group 2015 - 1.0.0-pre + 1.0.6-pre ..\JobbrRuleSet.ruleset bin\$(Configuration)\ @@ -27,9 +27,11 @@ + + - + all diff --git a/source/Jobbr.Server/JobbrServer.cs b/source/Jobbr.Server/JobbrServer.cs index 7b920bf..e3216c3 100644 --- a/source/Jobbr.Server/JobbrServer.cs +++ b/source/Jobbr.Server/JobbrServer.cs @@ -26,8 +26,8 @@ public class JobbrServer : IDisposable private readonly IJobExecutor _executor; private readonly IJobStorageProvider _jobStorageProvider; private readonly List _jobbrComponents; - private readonly ConfigurationManager _configurationManager; - private readonly RegistryBuilder _registryBuilder; + private readonly IConfigurationManager _configurationManager; + private readonly IRegistryBuilder _registryBuilder; private bool _isRunning; @@ -39,9 +39,9 @@ public class JobbrServer : IDisposable /// /// Initializes a new instance of the class. /// - public JobbrServer(ILogger logger, IJobScheduler scheduler, IJobExecutor jobExecutor, IJobStorageProvider jobStorageProvider, List jobbrComponents, MessageDispatcher messageDispatcher, ConfigurationManager configurationManager, RegistryBuilder registryBuilder) + public JobbrServer(ILoggerFactory loggerFactory, IJobScheduler scheduler, IJobExecutor jobExecutor, IJobStorageProvider jobStorageProvider, List jobbrComponents, IMessageDispatcher messageDispatcher, IConfigurationManager configurationManager, IRegistryBuilder registryBuilder) { - _logger = logger; + _logger = loggerFactory.CreateLogger(); _scheduler = scheduler; _executor = jobExecutor; diff --git a/source/Jobbr.Server/Scheduling/DefaultScheduler.cs b/source/Jobbr.Server/Scheduling/DefaultScheduler.cs index 5c80469..32bc6fc 100644 --- a/source/Jobbr.Server/Scheduling/DefaultScheduler.cs +++ b/source/Jobbr.Server/Scheduling/DefaultScheduler.cs @@ -16,18 +16,18 @@ public class DefaultScheduler : IJobScheduler private readonly IJobExecutor _executor; private readonly IPeriodicTimer _periodicTimer; private readonly IDateTimeProvider _dateTimeProvider; - private readonly InstantJobRunPlaner _instantJobRunPlanner; - private readonly ScheduledJobRunPlaner _scheduledJobRunPlanner; - private readonly RecurringJobRunPlaner _recurringJobRunPlanner; + private readonly IInstantJobRunPlaner _instantJobRunPlanner; + private readonly IScheduledJobRunPlaner _scheduledJobRunPlanner; + private readonly IRecurringJobRunPlaner _recurringJobRunPlanner; private readonly DefaultSchedulerConfiguration _schedulerConfiguration; private readonly object _evaluateTriggersLock = new (); private List _currentPlan = new (); - public DefaultScheduler(ILogger logger, IJobbrRepository jobbrRepository, IJobExecutor executor, InstantJobRunPlaner instantJobRunPlanner, ScheduledJobRunPlaner scheduledJobRunPlanner, - RecurringJobRunPlaner recurringJobRunPlanner, DefaultSchedulerConfiguration schedulerConfiguration, IPeriodicTimer periodicTimer, IDateTimeProvider dateTimeProvider) + public DefaultScheduler(ILoggerFactory loggerFactory, IJobbrRepository jobbrRepository, IJobExecutor executor, IInstantJobRunPlaner instantJobRunPlanner, IScheduledJobRunPlaner scheduledJobRunPlanner, + IRecurringJobRunPlaner recurringJobRunPlanner, DefaultSchedulerConfiguration schedulerConfiguration, IPeriodicTimer periodicTimer, IDateTimeProvider dateTimeProvider) { - _logger = logger; + _logger = loggerFactory.CreateLogger(); _jobbrRepository = jobbrRepository; _executor = executor; _periodicTimer = periodicTimer; @@ -285,7 +285,7 @@ private void SetScheduledJobRunsFromPastToOmitted() _logger.LogDebug("There were no jobs found that had been planned before {dateTime}", dateTime); return; } - + _logger.LogInformation("There were {jobRunCount} job runs that should have been started while the JobServer was not running. Need to omit them...", scheduledJobRuns.Count); foreach (var jobRun in scheduledJobRuns) { diff --git a/source/Jobbr.Server/Scheduling/Planer/IInstantJobRunPlaner.cs b/source/Jobbr.Server/Scheduling/Planer/IInstantJobRunPlaner.cs new file mode 100644 index 0000000..b55a7e3 --- /dev/null +++ b/source/Jobbr.Server/Scheduling/Planer/IInstantJobRunPlaner.cs @@ -0,0 +1,18 @@ +using Jobbr.ComponentModel.JobStorage.Model; + +namespace Jobbr.Server.Scheduling.Planer +{ + /// + /// Interface for instant job run planners. + /// + public interface IInstantJobRunPlaner + { + /// + /// Plans an instant job run. + /// + /// Job run trigger. + /// If the plan is new. + /// The created . + PlanResult Plan(InstantTrigger trigger, bool isNew = false); + } +} \ No newline at end of file diff --git a/source/Jobbr.Server/Scheduling/Planer/IRecurringJobRunPlaner.cs b/source/Jobbr.Server/Scheduling/Planer/IRecurringJobRunPlaner.cs new file mode 100644 index 0000000..40c26fc --- /dev/null +++ b/source/Jobbr.Server/Scheduling/Planer/IRecurringJobRunPlaner.cs @@ -0,0 +1,17 @@ +using Jobbr.ComponentModel.JobStorage.Model; + +namespace Jobbr.Server.Scheduling.Planer +{ + /// + /// Interface for recurring job run planners. + /// + public interface IRecurringJobRunPlaner + { + /// + /// Plans a recurring job run. + /// + /// Job run trigger. + /// The created . + PlanResult Plan(RecurringTrigger trigger); + } +} \ No newline at end of file diff --git a/source/Jobbr.Server/Scheduling/Planer/IScheduledJobRunPlaner.cs b/source/Jobbr.Server/Scheduling/Planer/IScheduledJobRunPlaner.cs new file mode 100644 index 0000000..7b53710 --- /dev/null +++ b/source/Jobbr.Server/Scheduling/Planer/IScheduledJobRunPlaner.cs @@ -0,0 +1,18 @@ +using Jobbr.ComponentModel.JobStorage.Model; + +namespace Jobbr.Server.Scheduling.Planer +{ + /// + /// Interface for scheduled job run planners. + /// + public interface IScheduledJobRunPlaner + { + /// + /// Plans a scheduled job run. + /// + /// Job run trigger. + /// If the plan is new. + /// The created . + PlanResult Plan(ScheduledTrigger trigger, bool isNew); + } +} \ No newline at end of file diff --git a/source/Jobbr.Server/Scheduling/Planer/InstantJobRunPlaner.cs b/source/Jobbr.Server/Scheduling/Planer/InstantJobRunPlaner.cs index 0883c8c..d73e285 100644 --- a/source/Jobbr.Server/Scheduling/Planer/InstantJobRunPlaner.cs +++ b/source/Jobbr.Server/Scheduling/Planer/InstantJobRunPlaner.cs @@ -2,16 +2,23 @@ namespace Jobbr.Server.Scheduling.Planer { - public class InstantJobRunPlaner + /// + /// Class for planning instant job runs. + /// + public class InstantJobRunPlaner : IInstantJobRunPlaner { - private readonly IDateTimeProvider dateTimeProvider; + private readonly IDateTimeProvider _dateTimeProvider; + /// + /// Initializes a new instance of the class. + /// public InstantJobRunPlaner(IDateTimeProvider dateTimeProvider) { - this.dateTimeProvider = dateTimeProvider; + _dateTimeProvider = dateTimeProvider; } - internal PlanResult Plan(InstantTrigger trigger, bool isNew = false) + /// + public PlanResult Plan(InstantTrigger trigger, bool isNew = false) { if (!trigger.IsActive) { @@ -21,7 +28,7 @@ internal PlanResult Plan(InstantTrigger trigger, bool isNew = false) var baseDateTimeUtc = trigger.CreatedDateTimeUtc; var calculatedNextRun = baseDateTimeUtc.AddMinutes(trigger.DelayedMinutes); - if (calculatedNextRun < this.dateTimeProvider.GetUtcNow() && !isNew) + if (calculatedNextRun < _dateTimeProvider.GetUtcNow() && !isNew) { return PlanResult.FromAction(PlanAction.Obsolete); } diff --git a/source/Jobbr.Server/Scheduling/Planer/PlanResult.cs b/source/Jobbr.Server/Scheduling/Planer/PlanResult.cs index 6900219..a6cccc5 100644 --- a/source/Jobbr.Server/Scheduling/Planer/PlanResult.cs +++ b/source/Jobbr.Server/Scheduling/Planer/PlanResult.cs @@ -2,14 +2,14 @@ namespace Jobbr.Server.Scheduling.Planer { - internal struct PlanResult + public struct PlanResult { internal PlanAction Action; internal DateTime? ExpectedStartDateUtc; internal static PlanResult FromAction(PlanAction action) { - return new PlanResult() { Action = action }; + return new PlanResult { Action = action }; } } } \ No newline at end of file diff --git a/source/Jobbr.Server/Scheduling/Planer/RecurringJobRunPlaner.cs b/source/Jobbr.Server/Scheduling/Planer/RecurringJobRunPlaner.cs index 530afc9..793a3b7 100644 --- a/source/Jobbr.Server/Scheduling/Planer/RecurringJobRunPlaner.cs +++ b/source/Jobbr.Server/Scheduling/Planer/RecurringJobRunPlaner.cs @@ -7,20 +7,27 @@ namespace Jobbr.Server.Scheduling.Planer { - public class RecurringJobRunPlaner + /// + /// Class for planning recurring job runs. + /// + public class RecurringJobRunPlaner : IRecurringJobRunPlaner { private readonly ILogger _logger; - private readonly JobbrRepository _jobbrRepository; + private readonly IJobbrRepository _jobbrRepository; private readonly IDateTimeProvider _dateTimeProvider; - public RecurringJobRunPlaner(ILogger logger, JobbrRepository jobbrRepository, IDateTimeProvider dateTimeProvider) + /// + /// Initializes a new instance of the class. + /// + public RecurringJobRunPlaner(ILoggerFactory loggerFactory, IJobbrRepository jobbrRepository, IDateTimeProvider dateTimeProvider) { - _logger = logger; + _logger = loggerFactory.CreateLogger(); _jobbrRepository = jobbrRepository; _dateTimeProvider = dateTimeProvider; } - internal PlanResult Plan(RecurringTrigger trigger) + /// + public PlanResult Plan(RecurringTrigger trigger) { if (!trigger.IsActive) { diff --git a/source/Jobbr.Server/Scheduling/Planer/ScheduledJobRunPlaner.cs b/source/Jobbr.Server/Scheduling/Planer/ScheduledJobRunPlaner.cs index 02f09de..fd9cfb7 100644 --- a/source/Jobbr.Server/Scheduling/Planer/ScheduledJobRunPlaner.cs +++ b/source/Jobbr.Server/Scheduling/Planer/ScheduledJobRunPlaner.cs @@ -2,16 +2,23 @@ namespace Jobbr.Server.Scheduling.Planer { - public class ScheduledJobRunPlaner + /// + /// Class for planning scheduled job runs. + /// + public class ScheduledJobRunPlaner : IScheduledJobRunPlaner { - private readonly IDateTimeProvider dateTimeProvider; + private readonly IDateTimeProvider _dateTimeProvider; + /// + /// Initializes a new instance of the class. + /// public ScheduledJobRunPlaner(IDateTimeProvider dateTimeProvider) { - this.dateTimeProvider = dateTimeProvider; + _dateTimeProvider = dateTimeProvider; } - internal PlanResult Plan(ScheduledTrigger trigger, bool isNew) + /// + public PlanResult Plan(ScheduledTrigger trigger, bool isNew) { if (!trigger.IsActive) { @@ -20,7 +27,7 @@ internal PlanResult Plan(ScheduledTrigger trigger, bool isNew) var calculatedNextRun = trigger.StartDateTimeUtc; - if (calculatedNextRun < this.dateTimeProvider.GetUtcNow() && !isNew) + if (calculatedNextRun < _dateTimeProvider.GetUtcNow() && !isNew) { return PlanResult.FromAction(PlanAction.Obsolete); } diff --git a/source/Jobbr.Server/Storage/JobbrRepository.cs b/source/Jobbr.Server/Storage/JobbrRepository.cs index 5e8bf7f..64f80a7 100644 --- a/source/Jobbr.Server/Storage/JobbrRepository.cs +++ b/source/Jobbr.Server/Storage/JobbrRepository.cs @@ -11,9 +11,9 @@ public class JobbrRepository : IJobbrRepository private readonly ILogger _logger; private readonly IJobStorageProvider _jobStorageProvider; - public JobbrRepository(ILogger logger, IJobStorageProvider jobStorageProvider) + public JobbrRepository(ILoggerFactory loggerFactory, IJobStorageProvider jobStorageProvider) { - _logger = logger; + _logger = loggerFactory.CreateLogger(); _jobStorageProvider = jobStorageProvider; } diff --git a/source/Jobbr.Server/TinyMessenger.cs b/source/Jobbr.Server/TinyMessenger.cs index ff11a97..4025d8c 100644 --- a/source/Jobbr.Server/TinyMessenger.cs +++ b/source/Jobbr.Server/TinyMessenger.cs @@ -1,5 +1,4 @@ -// -//=============================================================================== +//=============================================================================== // TinyIoC - TinyMessenger // // A simple messenger/event aggregator. @@ -17,10 +16,12 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using System.Threading.Tasks; namespace TinyMessenger { #region Message Types / Interfaces + /// /// A TinyMessage to be published/delivered by TinyMessenger /// @@ -42,12 +43,10 @@ public abstract class TinyMessageBase : ITinyMessage /// keep the message around and prevent the sender from being collected. /// private WeakReference _Sender; + public object Sender { - get - { - return (_Sender == null) ? null : _Sender.Target; - } + get { return (_Sender == null) ? null : _Sender.Target; } } /// @@ -150,9 +149,10 @@ public void Dispose() if (hub != null) { - var unsubscribeMethod = typeof(ITinyMessengerHub).GetMethod("Unsubscribe", new Type[] {typeof(TinyMessageSubscriptionToken)}); + var unsubscribeMethod = typeof(ITinyMessengerHub).GetMethod("Unsubscribe", + new Type[] { typeof(TinyMessageSubscriptionToken) }); unsubscribeMethod = unsubscribeMethod.MakeGenericMethod(_MessageType); - unsubscribeMethod.Invoke(hub, new object[] {this}); + unsubscribeMethod.Invoke(hub, new object[] { this }); } } @@ -213,10 +213,7 @@ static DefaultTinyMessageProxy() /// public static DefaultTinyMessageProxy Instance { - get - { - return _Instance; - } + get { return _Instance; } } private DefaultTinyMessageProxy() @@ -228,9 +225,11 @@ public void Deliver(ITinyMessage message, ITinyMessageSubscription subscription) subscription.Deliver(message); } } + #endregion #region Exceptions + /// /// Thrown when an exceptions occurs while subscribing to a message type /// @@ -241,18 +240,18 @@ public class TinyMessengerSubscriptionException : Exception public TinyMessengerSubscriptionException(Type messageType, string reason) : base(String.Format(ERROR_TEXT, messageType, reason)) { - } public TinyMessengerSubscriptionException(Type messageType, string reason, Exception innerException) : base(String.Format(ERROR_TEXT, messageType, reason), innerException) { - } } + #endregion #region Hub Interface + /// /// Messenger hub responsible for taking subscriptions/publications and delivering of messages. /// @@ -267,7 +266,8 @@ public interface ITinyMessengerHub /// Type of message /// Action to invoke when message is delivered /// TinyMessageSubscription used to unsubscribing - TinyMessageSubscriptionToken Subscribe(Action deliveryAction) where TMessage : class, ITinyMessage; + TinyMessageSubscriptionToken Subscribe(Action deliveryAction) + where TMessage : class, ITinyMessage; /// /// Subscribe to a message type with the given destination and delivery action. @@ -280,7 +280,8 @@ public interface ITinyMessengerHub /// Action to invoke when message is delivered /// Proxy to use when delivering the messages /// TinyMessageSubscription used to unsubscribing - TinyMessageSubscriptionToken Subscribe(Action deliveryAction, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage; + TinyMessageSubscriptionToken Subscribe(Action deliveryAction, ITinyMessageProxy proxy) + where TMessage : class, ITinyMessage; /// /// Subscribe to a message type with the given destination and delivery action. @@ -291,7 +292,8 @@ public interface ITinyMessengerHub /// Action to invoke when message is delivered /// Use strong references to destination and deliveryAction /// TinyMessageSubscription used to unsubscribing - TinyMessageSubscriptionToken Subscribe(Action deliveryAction, bool useStrongReferences) where TMessage : class, ITinyMessage; + TinyMessageSubscriptionToken Subscribe(Action deliveryAction, bool useStrongReferences) + where TMessage : class, ITinyMessage; /// /// Subscribe to a message type with the given destination and delivery action. @@ -304,7 +306,8 @@ public interface ITinyMessengerHub /// Use strong references to destination and deliveryAction /// Proxy to use when delivering the messages /// TinyMessageSubscription used to unsubscribing - TinyMessageSubscriptionToken Subscribe(Action deliveryAction, bool useStrongReferences, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage; + TinyMessageSubscriptionToken Subscribe(Action deliveryAction, bool useStrongReferences, + ITinyMessageProxy proxy) where TMessage : class, ITinyMessage; /// /// Subscribe to a message type with the given destination and delivery action with the given filter. @@ -314,8 +317,10 @@ public interface ITinyMessengerHub /// /// Type of message /// Action to invoke when message is delivered + /// /// TinyMessageSubscription used to unsubscribing - TinyMessageSubscriptionToken Subscribe(Action deliveryAction, Func messageFilter) where TMessage : class, ITinyMessage; + TinyMessageSubscriptionToken Subscribe(Action deliveryAction, + Func messageFilter) where TMessage : class, ITinyMessage; /// /// Subscribe to a message type with the given destination and delivery action with the given filter. @@ -326,9 +331,11 @@ public interface ITinyMessengerHub /// /// Type of message /// Action to invoke when message is delivered + /// /// Proxy to use when delivering the messages /// TinyMessageSubscription used to unsubscribing - TinyMessageSubscriptionToken Subscribe(Action deliveryAction, Func messageFilter, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage; + TinyMessageSubscriptionToken Subscribe(Action deliveryAction, + Func messageFilter, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage; /// /// Subscribe to a message type with the given destination and delivery action with the given filter. @@ -338,9 +345,11 @@ public interface ITinyMessengerHub /// /// Type of message /// Action to invoke when message is delivered + /// /// Use strong references to destination and deliveryAction /// TinyMessageSubscription used to unsubscribing - TinyMessageSubscriptionToken Subscribe(Action deliveryAction, Func messageFilter, bool useStrongReferences) where TMessage : class, ITinyMessage; + TinyMessageSubscriptionToken Subscribe(Action deliveryAction, + Func messageFilter, bool useStrongReferences) where TMessage : class, ITinyMessage; /// /// Subscribe to a message type with the given destination and delivery action with the given filter. @@ -351,10 +360,13 @@ public interface ITinyMessengerHub /// /// Type of message /// Action to invoke when message is delivered + /// /// Use strong references to destination and deliveryAction /// Proxy to use when delivering the messages /// TinyMessageSubscription used to unsubscribing - TinyMessageSubscriptionToken Subscribe(Action deliveryAction, Func messageFilter, bool useStrongReferences, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage; + TinyMessageSubscriptionToken Subscribe(Action deliveryAction, + Func messageFilter, bool useStrongReferences, ITinyMessageProxy proxy) + where TMessage : class, ITinyMessage; /// /// Unsubscribe from a particular message type. @@ -387,15 +399,18 @@ public interface ITinyMessengerHub /// AsyncCallback called on completion void PublishAsync(TMessage message, AsyncCallback callback) where TMessage : class, ITinyMessage; } + #endregion #region Hub Implementation + /// /// Messenger hub responsible for taking subscriptions/publications and delivering of messages. /// public sealed class TinyMessengerHub : ITinyMessengerHub { #region Private Types and Interfaces + private class WeakTinyMessageSubscription : ITinyMessageSubscription where TMessage : class, ITinyMessage { @@ -436,10 +451,11 @@ public void Deliver(ITinyMessage message) /// /// Initializes a new instance of the WeakTinyMessageSubscription class. /// - /// Destination object + /// /// Delivery action /// Filter function - public WeakTinyMessageSubscription(TinyMessageSubscriptionToken subscriptionToken, Action deliveryAction, Func messageFilter) + public WeakTinyMessageSubscription(TinyMessageSubscriptionToken subscriptionToken, + Action deliveryAction, Func messageFilter) { if (subscriptionToken == null) throw new ArgumentNullException("subscriptionToken"); @@ -487,10 +503,11 @@ public void Deliver(ITinyMessage message) /// /// Initializes a new instance of the TinyMessageSubscription class. /// - /// Destination object + /// /// Delivery action /// Filter function - public StrongTinyMessageSubscription(TinyMessageSubscriptionToken subscriptionToken, Action deliveryAction, Func messageFilter) + public StrongTinyMessageSubscription(TinyMessageSubscriptionToken subscriptionToken, + Action deliveryAction, Func messageFilter) { if (subscriptionToken == null) throw new ArgumentNullException("subscriptionToken"); @@ -506,9 +523,11 @@ public StrongTinyMessageSubscription(TinyMessageSubscriptionToken subscriptionTo _MessageFilter = messageFilter; } } + #endregion #region Subscription dictionary + private class SubscriptionItem { public ITinyMessageProxy Proxy { get; private set; } @@ -522,10 +541,14 @@ public SubscriptionItem(ITinyMessageProxy proxy, ITinyMessageSubscription subscr } private readonly object _SubscriptionsPadlock = new object(); - private readonly Dictionary> _Subscriptions = new Dictionary>(); + + private readonly Dictionary> _Subscriptions = + new Dictionary>(); + #endregion #region Public API + /// /// Subscribe to a message type with the given destination and delivery action. /// All references are held with strong references @@ -535,9 +558,11 @@ public SubscriptionItem(ITinyMessageProxy proxy, ITinyMessageSubscription subscr /// Type of message /// Action to invoke when message is delivered /// TinyMessageSubscription used to unsubscribing - public TinyMessageSubscriptionToken Subscribe(Action deliveryAction) where TMessage : class, ITinyMessage + public TinyMessageSubscriptionToken Subscribe(Action deliveryAction) + where TMessage : class, ITinyMessage { - return AddSubscriptionInternal(deliveryAction, (m) => true, true, DefaultTinyMessageProxy.Instance); + return AddSubscriptionInternal(deliveryAction, (m) => true, true, + DefaultTinyMessageProxy.Instance); } /// @@ -551,7 +576,8 @@ public TinyMessageSubscriptionToken Subscribe(Action deliver /// Action to invoke when message is delivered /// Proxy to use when delivering the messages /// TinyMessageSubscription used to unsubscribing - public TinyMessageSubscriptionToken Subscribe(Action deliveryAction, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage + public TinyMessageSubscriptionToken Subscribe(Action deliveryAction, + ITinyMessageProxy proxy) where TMessage : class, ITinyMessage { return AddSubscriptionInternal(deliveryAction, (m) => true, true, proxy); } @@ -565,9 +591,11 @@ public TinyMessageSubscriptionToken Subscribe(Action deliver /// Action to invoke when message is delivered /// Use strong references to destination and deliveryAction /// TinyMessageSubscription used to unsubscribing - public TinyMessageSubscriptionToken Subscribe(Action deliveryAction, bool useStrongReferences) where TMessage : class, ITinyMessage + public TinyMessageSubscriptionToken Subscribe(Action deliveryAction, + bool useStrongReferences) where TMessage : class, ITinyMessage { - return AddSubscriptionInternal(deliveryAction, (m) => true, useStrongReferences, DefaultTinyMessageProxy.Instance); + return AddSubscriptionInternal(deliveryAction, (m) => true, useStrongReferences, + DefaultTinyMessageProxy.Instance); } /// @@ -581,7 +609,8 @@ public TinyMessageSubscriptionToken Subscribe(Action deliver /// Use strong references to destination and deliveryAction /// Proxy to use when delivering the messages /// TinyMessageSubscription used to unsubscribing - public TinyMessageSubscriptionToken Subscribe(Action deliveryAction, bool useStrongReferences, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage + public TinyMessageSubscriptionToken Subscribe(Action deliveryAction, + bool useStrongReferences, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage { return AddSubscriptionInternal(deliveryAction, (m) => true, useStrongReferences, proxy); } @@ -594,10 +623,13 @@ public TinyMessageSubscriptionToken Subscribe(Action deliver /// /// Type of message /// Action to invoke when message is delivered + /// /// TinyMessageSubscription used to unsubscribing - public TinyMessageSubscriptionToken Subscribe(Action deliveryAction, Func messageFilter) where TMessage : class, ITinyMessage + public TinyMessageSubscriptionToken Subscribe(Action deliveryAction, + Func messageFilter) where TMessage : class, ITinyMessage { - return AddSubscriptionInternal(deliveryAction, messageFilter, true, DefaultTinyMessageProxy.Instance); + return AddSubscriptionInternal(deliveryAction, messageFilter, true, + DefaultTinyMessageProxy.Instance); } /// @@ -609,9 +641,11 @@ public TinyMessageSubscriptionToken Subscribe(Action deliver /// /// Type of message /// Action to invoke when message is delivered + /// /// Proxy to use when delivering the messages /// TinyMessageSubscription used to unsubscribing - public TinyMessageSubscriptionToken Subscribe(Action deliveryAction, Func messageFilter, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage + public TinyMessageSubscriptionToken Subscribe(Action deliveryAction, + Func messageFilter, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage { return AddSubscriptionInternal(deliveryAction, messageFilter, true, proxy); } @@ -624,11 +658,14 @@ public TinyMessageSubscriptionToken Subscribe(Action deliver /// /// Type of message /// Action to invoke when message is delivered + /// /// Use strong references to destination and deliveryAction /// TinyMessageSubscription used to unsubscribing - public TinyMessageSubscriptionToken Subscribe(Action deliveryAction, Func messageFilter, bool useStrongReferences) where TMessage : class, ITinyMessage + public TinyMessageSubscriptionToken Subscribe(Action deliveryAction, + Func messageFilter, bool useStrongReferences) where TMessage : class, ITinyMessage { - return AddSubscriptionInternal(deliveryAction, messageFilter, useStrongReferences, DefaultTinyMessageProxy.Instance); + return AddSubscriptionInternal(deliveryAction, messageFilter, useStrongReferences, + DefaultTinyMessageProxy.Instance); } /// @@ -640,10 +677,13 @@ public TinyMessageSubscriptionToken Subscribe(Action deliver /// /// Type of message /// Action to invoke when message is delivered + /// /// Use strong references to destination and deliveryAction /// Proxy to use when delivering the messages /// TinyMessageSubscription used to unsubscribing - public TinyMessageSubscriptionToken Subscribe(Action deliveryAction, Func messageFilter, bool useStrongReferences, ITinyMessageProxy proxy) where TMessage : class, ITinyMessage + public TinyMessageSubscriptionToken Subscribe(Action deliveryAction, + Func messageFilter, bool useStrongReferences, ITinyMessageProxy proxy) + where TMessage : class, ITinyMessage { return AddSubscriptionInternal(deliveryAction, messageFilter, useStrongReferences, proxy); } @@ -655,7 +695,8 @@ public TinyMessageSubscriptionToken Subscribe(Action deliver /// /// Type of message /// Subscription token received from Subscribe - public void Unsubscribe(TinyMessageSubscriptionToken subscriptionToken) where TMessage : class, ITinyMessage + public void Unsubscribe(TinyMessageSubscriptionToken subscriptionToken) + where TMessage : class, ITinyMessage { RemoveSubscriptionInternal(subscriptionToken); } @@ -686,15 +727,19 @@ public void PublishAsync(TMessage message) where TMessage : class, ITi /// Type of message /// Message to deliver /// AsyncCallback called on completion - public void PublishAsync(TMessage message, AsyncCallback callback) where TMessage : class, ITinyMessage + public void PublishAsync(TMessage message, AsyncCallback callback) + where TMessage : class, ITinyMessage { PublishAsyncInternal(message, callback); } + #endregion #region Internal Methods - private TinyMessageSubscriptionToken AddSubscriptionInternal(Action deliveryAction, Func messageFilter, bool strongReference, ITinyMessageProxy proxy) - where TMessage : class, ITinyMessage + + private TinyMessageSubscriptionToken AddSubscriptionInternal(Action deliveryAction, + Func messageFilter, bool strongReference, ITinyMessageProxy proxy) + where TMessage : class, ITinyMessage { if (deliveryAction == null) throw new ArgumentNullException("deliveryAction"); @@ -719,9 +764,11 @@ private TinyMessageSubscriptionToken AddSubscriptionInternal(Action(subscriptionToken, deliveryAction, messageFilter); + subscription = + new StrongTinyMessageSubscription(subscriptionToken, deliveryAction, messageFilter); else - subscription = new WeakTinyMessageSubscription(subscriptionToken, deliveryAction, messageFilter); + subscription = + new WeakTinyMessageSubscription(subscriptionToken, deliveryAction, messageFilter); currentSubscriptions.Add(new SubscriptionItem(proxy, subscription)); @@ -730,7 +777,7 @@ private TinyMessageSubscriptionToken AddSubscriptionInternal(Action(TinyMessageSubscriptionToken subscriptionToken) - where TMessage : class, ITinyMessage + where TMessage : class, ITinyMessage { if (subscriptionToken == null) throw new ArgumentNullException("subscriptionToken"); @@ -742,15 +789,15 @@ private void RemoveSubscriptionInternal(TinyMessageSubscriptionToken s return; var currentlySubscribed = (from sub in currentSubscriptions - where object.ReferenceEquals(sub.Subscription.SubscriptionToken, subscriptionToken) - select sub).ToList(); + where object.ReferenceEquals(sub.Subscription.SubscriptionToken, subscriptionToken) + select sub).ToList(); currentlySubscribed.ForEach(sub => currentSubscriptions.Remove(sub)); } } private void PublishInternal(TMessage message) - where TMessage : class, ITinyMessage + where TMessage : class, ITinyMessage { if (message == null) throw new ArgumentNullException("message"); @@ -763,8 +810,8 @@ private void PublishInternal(TMessage message) return; currentlySubscribed = (from sub in currentSubscriptions - where sub.Subscription.ShouldAttemptDelivery(message) - select sub).ToList(); + where sub.Subscription.ShouldAttemptDelivery(message) + select sub).ToList(); } currentlySubscribed.ForEach(sub => @@ -783,11 +830,11 @@ where sub.Subscription.ShouldAttemptDelivery(message) private void PublishAsyncInternal(TMessage message, AsyncCallback callback) where TMessage : class, ITinyMessage { - Action publishAction = () => { PublishInternal(message); }; - - publishAction.BeginInvoke(callback, null); + Task.Run(() => PublishInternal(message)).ContinueWith(t => callback?.Invoke(t)); } + #endregion } + #endregion -} +} \ No newline at end of file diff --git a/source/Jobbr.Tests/Components/JobRunService/ProgressChannelTests.cs b/source/Jobbr.Tests/Components/JobRunService/ProgressChannelTests.cs index 7ceee71..275a832 100644 --- a/source/Jobbr.Tests/Components/JobRunService/ProgressChannelTests.cs +++ b/source/Jobbr.Tests/Components/JobRunService/ProgressChannelTests.cs @@ -3,6 +3,7 @@ using Jobbr.Server.Builder; using Jobbr.Server.Core.Messaging; using Jobbr.Server.Storage; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.VisualStudio.TestTools.UnitTesting; using TinyMessenger; using JobRunStates = Jobbr.Server.Core.Models.JobRunStates; @@ -18,13 +19,13 @@ public class ProgressUpdateTests public ProgressUpdateTests() { - var autoMapperConfig = new AutoMapperConfigurationFactory(null).GetNew(); + var autoMapperConfig = new AutoMapperConfigurationFactory(new NullLoggerFactory()).GetNew(); - this.repo = new JobbrRepository(null, new InMemoryJobStorageProvider()); + this.repo = new JobbrRepository(new NullLoggerFactory(), new InMemoryJobStorageProvider()); this.messengerHub = new TinyMessengerHub(); - this.service = new Server.Core.JobRunService(null, this.messengerHub, this.repo, null, autoMapperConfig.CreateMapper()); + this.service = new Server.Core.JobRunService(new NullLoggerFactory(), this.messengerHub, this.repo, null, autoMapperConfig.CreateMapper()); } private JobRun GivenAJobRun() diff --git a/source/Jobbr.Tests/Components/Scheduler/TestBase.cs b/source/Jobbr.Tests/Components/Scheduler/TestBase.cs index b2429a4..3e80a36 100644 --- a/source/Jobbr.Tests/Components/Scheduler/TestBase.cs +++ b/source/Jobbr.Tests/Components/Scheduler/TestBase.cs @@ -5,6 +5,7 @@ using Jobbr.Server.Scheduling; using Jobbr.Server.Scheduling.Planer; using Jobbr.Server.Storage; +using Microsoft.Extensions.Logging.Abstractions; using Moq; namespace Jobbr.Tests.Components.Scheduler @@ -20,7 +21,7 @@ public class TestBase public TestBase() { - this.repository = new JobbrRepository(null, new InMemoryJobStorageProvider()); + this.repository = new JobbrRepository(new NullLoggerFactory(), new InMemoryJobStorageProvider()); var executorMock = new Mock(); executorMock.Setup(e => e.OnPlanChanged(It.IsNotNull>())).Callback>(p => this.lastIssuedPlan = p); @@ -33,9 +34,9 @@ public TestBase() this.repository.AddJob(job); this.demoJob1Id = job.Id; - this.scheduler = new DefaultScheduler(null, this.repository, executorMock.Object, + this.scheduler = new DefaultScheduler(new NullLoggerFactory(), this.repository, executorMock.Object, new InstantJobRunPlaner(this.currentTimeProvider), new ScheduledJobRunPlaner(this.currentTimeProvider), - new RecurringJobRunPlaner(null, this.repository, this.currentTimeProvider), new DefaultSchedulerConfiguration(), + new RecurringJobRunPlaner(new NullLoggerFactory(), this.repository, this.currentTimeProvider), new DefaultSchedulerConfiguration(), this.periodicTimer, this.currentTimeProvider); } } diff --git a/source/Jobbr.Tests/Integration/ExposeAllServicesComponent.cs b/source/Jobbr.Tests/Integration/ExposeAllServicesComponent.cs index e268d17..601a66b 100644 --- a/source/Jobbr.Tests/Integration/ExposeAllServicesComponent.cs +++ b/source/Jobbr.Tests/Integration/ExposeAllServicesComponent.cs @@ -16,18 +16,18 @@ public class ExposeAllServicesComponent : IJobbrComponent { public static ExposeAllServicesComponent Instance => instancesPerThread.Value; - private static ThreadLocal instancesPerThread = new ThreadLocal(); + private static ThreadLocal instancesPerThread = new (); public ExposeAllServicesComponent(IJobbrServiceProvider serviceProvider, IArtefactsStorageProvider artefactsStorageProvider, IJobStorageProvider jobStorageProvider, IJobManagementService jobManagementService, IQueryService queryService, IServerManagementService managementService, IJobRunInformationService informationService, IJobRunProgressChannel progressChannel) { - this.ServiceProvider = serviceProvider; - this.ArtefactsStorageProvider = artefactsStorageProvider; - this.JobStorageProvider = jobStorageProvider; - this.JobManagementService = jobManagementService; - this.QueryService = queryService; - this.ManagementService = managementService; - this.InformationService = informationService; - this.ProgressChannel = progressChannel; + ServiceProvider = serviceProvider; + ArtefactsStorageProvider = artefactsStorageProvider; + JobStorageProvider = jobStorageProvider; + JobManagementService = jobManagementService; + QueryService = queryService; + ManagementService = managementService; + InformationService = informationService; + ProgressChannel = progressChannel; instancesPerThread.Value = this; } diff --git a/source/Jobbr.Tests/Integration/JobbrServerTestBase.cs b/source/Jobbr.Tests/Integration/JobbrServerTestBase.cs index 861732b..c0c0c48 100644 --- a/source/Jobbr.Tests/Integration/JobbrServerTestBase.cs +++ b/source/Jobbr.Tests/Integration/JobbrServerTestBase.cs @@ -2,6 +2,7 @@ using Jobbr.ComponentModel.Registration; using Jobbr.Server; using Jobbr.Server.Builder; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Jobbr.Tests.Integration @@ -45,9 +46,9 @@ protected static JobbrServer GivenAStartedServer() protected static JobbrServer GivenAServerInstance() { - var builder = new JobbrBuilder(null); - - builder.Register(typeof(ExposeAllServicesComponent)); + var builder = new JobbrBuilder(new NullLoggerFactory()); + + builder.AppendTypeToCollection(typeof(ExposeAllServicesComponent)); var server = builder.Create(); return server; diff --git a/source/Jobbr.Tests/Integration/Startup/BadEnvironmentTests.cs b/source/Jobbr.Tests/Integration/Startup/BadEnvironmentTests.cs index 737b805..b16c5da 100644 --- a/source/Jobbr.Tests/Integration/Startup/BadEnvironmentTests.cs +++ b/source/Jobbr.Tests/Integration/Startup/BadEnvironmentTests.cs @@ -5,6 +5,7 @@ using Jobbr.Server; using Jobbr.Server.Builder; using Jobbr.Tests.Infrastructure; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Jobbr.Tests.Integration.Startup @@ -15,7 +16,7 @@ public class BadEnvironmentTests [TestMethod] public void StartingJobber_GetsRunning_WhenStorageProviderTurnsHealthy() { - var builder = new JobbrBuilder(null); + var builder = new JobbrBuilder(new NullLoggerFactory()); builder.Register(typeof(FaultyJobStorageProvider)); var jobbr = builder.Create(); @@ -26,7 +27,7 @@ public void StartingJobber_GetsRunning_WhenStorageProviderTurnsHealthy() faultyJobStorageProvider.EnableImplementation(); - this.WaitForStatusChange(() => jobbr.State, 5000); + WaitForStatusChange(() => jobbr.State, 5000); Assert.AreEqual(JobbrState.Running, jobbr.State); } @@ -34,8 +35,9 @@ public void StartingJobber_GetsRunning_WhenStorageProviderTurnsHealthy() [TestMethod] public void StartingJobbr_ComponentFails_IsInErrorState() { - var builder = new JobbrBuilder(null); - builder.Register(typeof(FaultyComponent)); + var nullLoggerFactory = new NullLoggerFactory(); + var builder = new JobbrBuilder(nullLoggerFactory); + builder.AppendTypeToCollection(typeof(FaultyComponent)); var jobbr = builder.Create(); @@ -49,14 +51,15 @@ public void StartingJobbr_ComponentFails_IsInErrorState() } Assert.AreEqual(JobbrState.Error, jobbr.State); + nullLoggerFactory.Dispose(); } [TestMethod] [ExpectedException(typeof(Exception))] public void StartingJobbr_ComponentFails_ExceptionIsThrown() { - var builder = new JobbrBuilder(null); - builder.Register(typeof(FaultyComponent)); + var builder = new JobbrBuilder(new NullLoggerFactory()); + builder.AppendTypeToCollection(typeof(FaultyComponent)); var jobbr = builder.Create(); diff --git a/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs b/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs index 11bb08d..97df34d 100644 --- a/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs +++ b/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs @@ -1,6 +1,7 @@ using System; using Jobbr.ComponentModel.Registration; using Jobbr.Server.Builder; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Jobbr.Tests.Integration.Startup @@ -62,12 +63,12 @@ public bool Validate(object configuration) [TestMethod] public void ValidatorForSettings_WhenRegistered_IsCalled() { - var builder = new JobbrBuilder(null); + var builder = new JobbrBuilder(new NullLoggerFactory()); builder.Add(new DemoSettings()); var isCalled = false; - - builder.Add(new DemoComponentValidator(s => isCalled = true)); + + builder.AppendInstanceToCollection(new DemoComponentValidator(s => isCalled = true)); var jobbr = builder.Create(); @@ -79,14 +80,14 @@ public void ValidatorForSettings_WhenRegistered_IsCalled() [TestMethod] public void ValidatorForSettings_WhenCalled_SettingsIsPassedThrough() { - var builder = new JobbrBuilder(null); + var builder = new JobbrBuilder(new NullLoggerFactory()); var demoSettings = new DemoSettings(); object settingsToValidate = null; builder.Add(demoSettings); - builder.Add(new DemoComponentValidator(s => settingsToValidate = s)); + builder.AppendInstanceToCollection(new DemoComponentValidator(s => settingsToValidate = s)); var jobbr = builder.Create(); @@ -97,14 +98,14 @@ public void ValidatorForSettings_WhenCalled_SettingsIsPassedThrough() } [TestMethod] - [ExpectedException(typeof(Exception))] + [ExpectedException(typeof(ArgumentNullException))] public void ValidatorForSettings_ValidationFails_PreventsStart() { - var builder = new JobbrBuilder(null); + var builder = new JobbrBuilder(new NullLoggerFactory()); builder.Add(new DemoSettings()); - - builder.Add(new DemoComponentValidator(validationShouldFail: true, throwException: false)); + + builder.AppendInstanceToCollection(new DemoComponentValidator(validationShouldFail: true, throwException: false)); var jobbr = builder.Create(); @@ -112,14 +113,14 @@ public void ValidatorForSettings_ValidationFails_PreventsStart() } [TestMethod] - [ExpectedException(typeof(Exception))] + [ExpectedException(typeof(ArgumentNullException))] public void ValidatorForSettings_ThrowsException_PreventsStart() { - var builder = new JobbrBuilder(null); + var builder = new JobbrBuilder(new NullLoggerFactory()); builder.Add(new DemoSettings()); - builder.Add(new DemoComponentValidator(validationShouldFail: false, throwException: true)); + builder.AppendInstanceToCollection(new DemoComponentValidator(validationShouldFail: false, throwException: true)); var jobbr = builder.Create(); diff --git a/source/Jobbr.Tests/Integration/Startup/ConsoleCapturer.cs b/source/Jobbr.Tests/Integration/Startup/ConsoleCapturer.cs index f365c5b..79e9d4d 100644 --- a/source/Jobbr.Tests/Integration/Startup/ConsoleCapturer.cs +++ b/source/Jobbr.Tests/Integration/Startup/ConsoleCapturer.cs @@ -8,46 +8,38 @@ namespace Jobbr.Tests.Integration.Startup { public class ConsoleCapturer : TextWriter { - private readonly TextWriter consoleWriter; - private readonly StringBuilder capture; + private readonly TextWriter _consoleWriter; + private readonly StringBuilder _capture; - public IEnumerable GetLines() + public ConsoleCapturer() { - return this.capture.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.None); + _consoleWriter = Console.Out; + _capture = new StringBuilder(); + + Console.SetOut(this); } - public IEnumerable GetLines(params string[] needles) + public IEnumerable GetLines() { - var allLines = this.GetLines(); - - foreach (var line in allLines) - { - if (needles.All(n => line.Contains(n))) - { - yield return line; - } - } + return _capture.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.None); } - public ConsoleCapturer() + public IEnumerable GetLines(params string[] needles) { - this.consoleWriter = Console.Out; - this.capture = new StringBuilder(); - - Console.SetOut(this); + return GetLines().Where(l => needles.Any(l.Contains)); } public override Encoding Encoding => Encoding.UTF8; public override void Write(char value) { - this.consoleWriter.Write(value); - this.capture.Append(value); + _consoleWriter.Write(value); + _capture.Append(value); } protected override void Dispose(bool disposing) { - Console.SetOut(this.consoleWriter); + Console.SetOut(_consoleWriter); base.Dispose(disposing); } } diff --git a/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs b/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs index 4681504..101974e 100644 --- a/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs +++ b/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs @@ -5,6 +5,8 @@ using Jobbr.ComponentModel.JobStorage; using Jobbr.Server.Builder; using Jobbr.Tests.Infrastructure; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Jobbr.Tests.Integration.Startup @@ -35,7 +37,7 @@ public void CreateJobber_WithConsoleCapturer_CaptureMessagesFromConsole() { using (var capture = new ConsoleCapturer()) { - var builder = new JobbrBuilder(null); + var builder = new JobbrBuilder(new NullLoggerFactory()); builder.Create(); @@ -49,7 +51,12 @@ public void CreateJobbr_WithNoStorageProvider_IssuesError() { using (var capture = new ConsoleCapturer()) { - var builder = new JobbrBuilder(null); + var loggerFactory = LoggerFactory.Create(builder => + { + _ = builder.AddConsole(); + }); + + var builder = new JobbrBuilder(loggerFactory); // Register only Artefacts and Executor builder.Register(typeof(PseudoArtefactsStorageProvider)); @@ -62,6 +69,8 @@ public void CreateJobbr_WithNoStorageProvider_IssuesError() Assert.IsTrue(storageWarnLogs.Any()); Assert.AreEqual(1, storageWarnLogs.Count); + + loggerFactory.Dispose(); } } @@ -70,7 +79,12 @@ public void CreateJobbr_WithNoArtefactsProvider_IssuesWarn() { using (var capture = new ConsoleCapturer()) { - var builder = new JobbrBuilder(null); + var loggerFactory = LoggerFactory.Create(builder => + { + _ = builder.AddConsole(); + }); + + var builder = new JobbrBuilder(loggerFactory); // Register only Executor and JobStorage builder.Register(typeof(PseudoExecutor)); @@ -78,10 +92,12 @@ public void CreateJobbr_WithNoArtefactsProvider_IssuesWarn() builder.Create(); - var artefactsWarnings = capture.GetLines("WARN", "Artefacts").ToList(); + var artefactsWarnings = capture.GetLines("warn", "Artefacts").ToList(); Assert.IsTrue(artefactsWarnings.Any()); - Assert.AreEqual(1, artefactsWarnings.Count); + Assert.AreEqual(2, artefactsWarnings.Count); + + loggerFactory.Dispose(); } } @@ -90,7 +106,12 @@ public void CreateJobbr_WithNoExecutor_IssuesError() { using (var capture = new ConsoleCapturer()) { - var builder = new JobbrBuilder(null); + var loggerFactory = LoggerFactory.Create(builder => + { + _ = builder.AddConsole(); + }); + + var builder = new JobbrBuilder(loggerFactory); // Register only Artefacts and JoStorage builder.Register(typeof(PseudoArtefactsStorageProvider)); @@ -98,10 +119,12 @@ public void CreateJobbr_WithNoExecutor_IssuesError() builder.Create(); - var artefactsWarnings = capture.GetLines("ERROR", "Executor").ToList(); + var artefactsWarnings = capture.GetLines("error", "Executor").ToList(); Assert.IsTrue(artefactsWarnings.Any()); Assert.AreEqual(1, artefactsWarnings.Count); + + loggerFactory.Dispose(); } } @@ -110,7 +133,12 @@ public void CreateJobbr_WithAllRequiredComponents_NoErrorNoWarn() { using (var capture = new ConsoleCapturer()) { - var builder = new JobbrBuilder(null); + var loggerFactory = LoggerFactory.Create(builder => + { + _ = builder.AddConsole(); + }); + + var builder = new JobbrBuilder(loggerFactory); // Register only Artefacts and JoStorage builder.Register(typeof(PseudoArtefactsStorageProvider)); @@ -124,6 +152,8 @@ public void CreateJobbr_WithAllRequiredComponents_NoErrorNoWarn() Assert.IsFalse(errors.Any()); Assert.IsFalse(warnings.Any()); + + loggerFactory.Dispose(); } } @@ -132,7 +162,12 @@ public void StartJobbr_WithAllRequiredComponents_NoErrorNoWarn() { using (var capture = new ConsoleCapturer()) { - var builder = new JobbrBuilder(null); + var loggerFactory = LoggerFactory.Create(builder => + { + _ = builder.AddConsole(); + }); + + var builder = new JobbrBuilder(loggerFactory); // Register only Artefacts and JoStorage builder.Register(typeof(PseudoArtefactsStorageProvider)); @@ -150,6 +185,8 @@ public void StartJobbr_WithAllRequiredComponents_NoErrorNoWarn() Assert.IsFalse(fatals.Any(), "Got too many fatals: \n\n * " + string.Join("\n * ", fatals)); Assert.IsFalse(errors.Any(), "Got too many errors: \n\n * " + string.Join("\n * ", errors)); Assert.IsFalse(warnings.Any(), "Got too many warnings: \n\n * " + string.Join("\n * ", warnings)); + + loggerFactory.Dispose(); } } } diff --git a/source/Jobbr.Tests/Jobbr.Tests.csproj b/source/Jobbr.Tests/Jobbr.Tests.csproj index 3969fcb..5392a0b 100644 --- a/source/Jobbr.Tests/Jobbr.Tests.csproj +++ b/source/Jobbr.Tests/Jobbr.Tests.csproj @@ -23,6 +23,10 @@ + + + + @@ -50,7 +54,7 @@ - + \ No newline at end of file diff --git a/source/Jobbr.Tests/Registration/BuilderTests.cs b/source/Jobbr.Tests/Registration/BuilderTests.cs index edf788f..bbe57ef 100644 --- a/source/Jobbr.Tests/Registration/BuilderTests.cs +++ b/source/Jobbr.Tests/Registration/BuilderTests.cs @@ -10,6 +10,7 @@ using Jobbr.Server.Builder; using Jobbr.Server.JobRegistry; using Jobbr.Tests.Integration; +using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -18,16 +19,33 @@ namespace Jobbr.Tests.Registration [TestClass] public class BuilderTests { + ILoggerFactory _loggerFactory; + + [TestInitialize] + public void Initialize() + { + _loggerFactory = new LoggerFactory(); + } + + [TestCleanup] + public void Cleanup() + { + _loggerFactory.Dispose(); + } + [TestMethod] public void RegisterCustomArtefactStorageProvider_AfterCreation_CorrectTypeIsActivated() { - var builder = new JobbrBuilder(null); + // Arrange + var builder = new JobbrBuilder(_loggerFactory); builder.Register(typeof(CustomArtefactStorageAdapter)); - builder.Register(typeof(ExposeAllServicesComponent)); + builder.AppendTypeToCollection(typeof(ExposeAllServicesComponent)); + // Act builder.Create(); + // Assert Assert.IsNotNull(ExposeAllServicesComponent.Instance.ArtefactsStorageProvider); Assert.AreEqual(typeof(CustomArtefactStorageAdapter), ExposeAllServicesComponent.Instance.ArtefactsStorageProvider.GetType()); @@ -36,13 +54,16 @@ public void RegisterCustomArtefactStorageProvider_AfterCreation_CorrectTypeIsAct [TestMethod] public void RegisterCustomJobStorageProvider_AfterCreation_CorrectTypeIsActivated() { - var builder = new JobbrBuilder(null); + // Arrange + var builder = new JobbrBuilder(_loggerFactory); builder.Register(typeof(CustomJobStorageProvider)); - builder.Register(typeof(ExposeAllServicesComponent)); + builder.AppendTypeToCollection(typeof(ExposeAllServicesComponent)); + // Act builder.Create(); + // Assert Assert.IsNotNull(ExposeAllServicesComponent.Instance.ArtefactsStorageProvider); Assert.AreEqual(typeof(CustomJobStorageProvider), ExposeAllServicesComponent.Instance.JobStorageProvider.GetType()); @@ -51,55 +72,66 @@ public void RegisterCustomJobStorageProvider_AfterCreation_CorrectTypeIsActivate [TestMethod] public void ShouldDeleteJobsAndTriggers_WhenSingleSourceOfTruthIsActivated() { + // Arrange const string existingJobName = "MyJobExists"; const long existingJobId = 1; const long nonExistingJobId = 2; const long existingTriggerId = 10; const long nonExistingTriggerId = 20; + var existingJob = new Job { Id = 1, UniqueName = existingJobName }; var nonExistingJob = new Job { Id = 2, UniqueName = "DoIDieNow?" }; var pagedJobs = CreatePagedResult(existingJob, nonExistingJob); var triggerForExistingJob = new RecurringTrigger { Id = existingTriggerId, JobId = existingJobId }; var triggerForNonExistingJob = new RecurringTrigger { Id = nonExistingTriggerId, JobId = nonExistingJobId }; - var storage = new Mock(); - storage.Setup(s => s.GetJobs(1, int.MaxValue, null, null, null, false)).Returns(pagedJobs); - storage.Setup(s => s.GetTriggersByJobId(existingJobId, 1, int.MaxValue, false)) + + var storageMock = new Mock(); + storageMock.Setup(s => s.GetJobs(1, int.MaxValue, null, null, null, false)) + .Returns(pagedJobs); + storageMock.Setup(s => s.GetTriggersByJobId(existingJobId, 1, int.MaxValue, false)) .Returns(CreatePagedResult(triggerForExistingJob)); - storage.Setup(s => s.GetTriggersByJobId(nonExistingJobId, 1, int.MaxValue, false)) + storageMock.Setup(s => s.GetTriggersByJobId(nonExistingJobId, 1, int.MaxValue, false)) .Returns(CreatePagedResult(triggerForNonExistingJob)); - SetupForSuccessfulRun(storage); - var builder = new JobbrBuilder(null); - builder.Add(storage.Object); - builder.AddJobs(repo => - repo.AsSingleSourceOfTruth().Define(existingJobName, "CLR.Type")); + SetupForSuccessfulRun(storageMock); + + var builder = new JobbrBuilder(_loggerFactory); + builder.Add(storageMock.Object); + builder.AddJobs(_loggerFactory, repo => repo.AsSingleSourceOfTruth().Define(existingJobName, "CLR.Type")); + // Act builder.Create().Start(); - Assert.IsTrue(nonExistingJob.Deleted); + // Assert Assert.IsFalse(triggerForNonExistingJob.IsActive); Assert.IsTrue(triggerForNonExistingJob.Deleted); + _loggerFactory.Dispose(); } [TestMethod] public void ShouldDeleteOrphanedTriggers_WhenSingleSourceOfTruthIsActivated() { + // Arrange const string jobName = "JobName"; - var storage = new Mock(); - var builder = new JobbrBuilder(null); + var storageMock = new Mock(); + var builder = new JobbrBuilder(_loggerFactory); var job = new Job { Id = 1, UniqueName = jobName }; var trigger = new RecurringTrigger { Definition = "0 * * * *", JobId = 1, Id = 1 }; var toDeleteTrigger = new RecurringTrigger { Definition = "0 1 * * *", JobId = 1, Id = 10 }; - storage.Setup(s => s.GetJobs(1, int.MaxValue, null, null, null, false)).Returns(CreatePagedResult(job)); - storage.Setup(s => s.GetTriggersByJobId(1, 1, int.MaxValue, false)) + + storageMock.Setup(s => s.GetJobs(1, int.MaxValue, null, null, null, false)).Returns(CreatePagedResult(job)); + storageMock.Setup(s => s.GetTriggersByJobId(1, 1, int.MaxValue, false)) .Returns(CreatePagedResult(trigger, toDeleteTrigger)); - storage.Setup(s => s.GetJobByUniqueName(jobName)).Returns(job); - SetupForSuccessfulRun(storage); - builder.Add(storage.Object); - builder.AddJobs(repo => + storageMock.Setup(s => s.GetJobByUniqueName(jobName)).Returns(job); + SetupForSuccessfulRun(storageMock); + + builder.Add(storageMock.Object); + builder.AddJobs(_loggerFactory, repo => repo.AsSingleSourceOfTruth().Define(jobName, "CLR.Type").WithTrigger("0 * * * *")); + // Act builder.Create().Start(); + // Assert Assert.IsFalse(job.Deleted); Assert.IsFalse(toDeleteTrigger.IsActive); Assert.IsTrue(toDeleteTrigger.Deleted); @@ -108,42 +140,49 @@ public void ShouldDeleteOrphanedTriggers_WhenSingleSourceOfTruthIsActivated() [TestMethod] public void ShouldReActivateJob_WhenJobIsRedefined() { + // Arrange const string jobName = "JobName"; - var storage = new Mock(); - var builder = new JobbrBuilder(null); + var storageMock = new Mock(); + var builder = new JobbrBuilder(_loggerFactory); var job = new Job { Id = 1, UniqueName = jobName }; - storage.Setup(s => s.GetJobs(1, int.MaxValue, null, null, null, false)).Returns(CreatePagedResult(job)); - builder.AddJobs(repo => + storageMock.Setup(s => s.GetJobs(1, int.MaxValue, null, null, null, false)).Returns(CreatePagedResult(job)); + builder.AddJobs(_loggerFactory, repo => repo.AsSingleSourceOfTruth().Define(jobName, "CLR.Type").WithTrigger("0 * * * *")); var jobbr = builder.Create(); + + // Act jobbr.Start(); jobbr.Stop(); - jobbr.Start(); + // Assert Assert.IsFalse(job.Deleted); } [TestMethod] public void ShouldOmitScheduledJob_WhenJobIsDeactivated() { + // Arrange const string existingJobName = "MyJobExists"; const long nonExistingJobId = 2; var existingJob = new Job { Id = 1, UniqueName = existingJobName }; var nonExistingJob = new Job { Id = 2, UniqueName = "DoIDieNow?" }; var pagedJobs = CreatePagedResult(existingJob, nonExistingJob); var toOmitJobRun = new JobRun { State = JobRunStates.Scheduled, Deleted = false }; - var storage = new Mock(); - storage.Setup(s => s.GetJobs(1, int.MaxValue, null, null, null, false)).Returns(pagedJobs); - storage.Setup(s => s.GetJobRunsByJobId((int)nonExistingJobId, 1, int.MaxValue, false)) + + var storageMock = new Mock(); + storageMock.Setup(s => s.GetJobs(1, int.MaxValue, null, null, null, false)).Returns(pagedJobs); + storageMock.Setup(s => s.GetJobRunsByJobId((int)nonExistingJobId, 1, int.MaxValue, false)) .Returns(CreatePagedResult(toOmitJobRun)); - var builder = new JobbrBuilder(null); - builder.Add(storage.Object); - builder.AddJobs(repo => - repo.AsSingleSourceOfTruth().Define(existingJobName, "CLR.Type")); + var builder = new JobbrBuilder(_loggerFactory); + builder.Add(storageMock.Object); + builder.AddJobs(_loggerFactory, repo => repo.AsSingleSourceOfTruth().Define(existingJobName, "CLR.Type")); + + // Act builder.Create().Start(); + // Assert Assert.IsTrue(toOmitJobRun.Deleted); Assert.AreEqual(JobRunStates.Omitted, toOmitJobRun.State); } @@ -151,24 +190,29 @@ public void ShouldOmitScheduledJob_WhenJobIsDeactivated() [TestMethod] public void ShouldOmitScheduledJob_WhenTriggerIsDeactivated() { + // Arrange const string jobName = "JobName"; - var storage = new Mock(); - var builder = new JobbrBuilder(null); + var storageMock = new Mock(); + var builder = new JobbrBuilder(_loggerFactory); var job = new Job { Id = 1, UniqueName = jobName }; var toDeleteTrigger = new RecurringTrigger { Definition = "0 1 * * *", JobId = 1, Id = 10 }; var toOmitJobRun = new JobRun { State = JobRunStates.Scheduled, Deleted = false }; - storage.Setup(s => s.GetJobs(1, int.MaxValue, null, null, null, false)).Returns(CreatePagedResult(job)); - storage.Setup(s => s.GetTriggersByJobId(1, 1, int.MaxValue, false)) + + storageMock.Setup(s => s.GetJobs(1, int.MaxValue, null, null, null, false)).Returns(CreatePagedResult(job)); + storageMock.Setup(s => s.GetTriggersByJobId(1, 1, int.MaxValue, false)) .Returns(CreatePagedResult(toDeleteTrigger)); - storage.Setup(s => s.GetJobByUniqueName(jobName)).Returns(job); - storage.Setup(s => s.GetJobRunsByTriggerId(1, 10, 1, int.MaxValue, false)) + storageMock.Setup(s => s.GetJobByUniqueName(jobName)).Returns(job); + storageMock.Setup(s => s.GetJobRunsByTriggerId(1, 10, 1, int.MaxValue, false)) .Returns(CreatePagedResult(toOmitJobRun)); - builder.Add(storage.Object); - builder.AddJobs(repo => + + builder.Add(storageMock.Object); + builder.AddJobs(_loggerFactory, repo => repo.AsSingleSourceOfTruth().Define(jobName, "CLR.Type").WithTrigger("* * * * *")); + // Act builder.Create().Start(); - + + // Assert Assert.IsTrue(toOmitJobRun.Deleted); Assert.AreEqual(JobRunStates.Omitted, toOmitJobRun.State); } @@ -180,15 +224,15 @@ private static PagedResult CreatePagedResult(params T[] args) return new PagedResult { Items = items }; } - private static void SetupForSuccessfulRun(Mock storage) + private static void SetupForSuccessfulRun(Mock storageMock) { - storage.Setup(s => s.GetJobRunsByState(It.IsAny(), 1, int.MaxValue, null, null, null, false)) + storageMock.Setup(s => s.GetJobRunsByState(It.IsAny(), 1, int.MaxValue, null, null, null, false)) .Returns(CreatePagedResult()); - storage.Setup(s => s.GetActiveTriggers(1, int.MaxValue, null, null, null)) + storageMock.Setup(s => s.GetActiveTriggers(1, int.MaxValue, null, null, null)) .Returns(CreatePagedResult()); var anyId = It.IsAny(); - storage.Setup(s => s.GetJobRunsByJobId(It.IsAny(), 1, int.MaxValue, false)).Returns(CreatePagedResult()); - storage.Setup(s => s.GetJobRunsByTriggerId(anyId, anyId, 1, int.MaxValue, false)).Returns(CreatePagedResult()); + storageMock.Setup(s => s.GetJobRunsByJobId(It.IsAny(), 1, int.MaxValue, false)).Returns(CreatePagedResult()); + storageMock.Setup(s => s.GetJobRunsByTriggerId(anyId, anyId, 1, int.MaxValue, false)).Returns(CreatePagedResult()); } } From f931137de3691a483c51565bdecb9a5f341b5680 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Wed, 7 Dec 2022 13:02:04 +0100 Subject: [PATCH 12/41] Update Appveyor image to VS2022 --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 0eca95f..3bbdf6a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -image: Visual Studio 2019 +image: Visual Studio 2022 branches: only: From 6e8cbb7b866bd1d63e929b955fba2a2d9d699bdb Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Wed, 7 Dec 2022 13:30:54 +0100 Subject: [PATCH 13/41] Update .nuspec file to NET6 --- source/Jobbr.Server.nuspec | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/source/Jobbr.Server.nuspec b/source/Jobbr.Server.nuspec index e8d3a1e..ea9dc8e 100644 --- a/source/Jobbr.Server.nuspec +++ b/source/Jobbr.Server.nuspec @@ -11,17 +11,17 @@ Jobbr is a non-invasive .NET JobServer Copyright 2022 images\icon.png - - - - - - - + + + + + + + - - + + From 5e3134ecd9ab8b11ee1861005f5bb27448f0c277 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Wed, 7 Dec 2022 17:19:19 +0100 Subject: [PATCH 14/41] Small logging syntax fixes --- .../Jobbr.Server/Builder/DefaultContainer.cs | 2 -- source/Jobbr.Server/ConfigurationManager.cs | 2 +- source/Jobbr.Server/Jobbr.Server.csproj | 6 +---- source/Jobbr.Server/JobbrServer.cs | 6 ++--- .../Scheduling/DefaultScheduler.cs | 27 ++++++++++--------- .../Jobbr.Server/Storage/JobbrRepository.cs | 2 +- .../Startup/ConfigurationValidationTests.cs | 4 +-- .../Startup/SetupValidationTests.cs | 10 +++++-- source/Jobbr.Tests/Jobbr.Tests.csproj | 3 --- .../Jobbr.Tests/Registration/BuilderTests.cs | 1 - 10 files changed, 30 insertions(+), 33 deletions(-) diff --git a/source/Jobbr.Server/Builder/DefaultContainer.cs b/source/Jobbr.Server/Builder/DefaultContainer.cs index ddaa7f4..855ded6 100644 --- a/source/Jobbr.Server/Builder/DefaultContainer.cs +++ b/source/Jobbr.Server/Builder/DefaultContainer.cs @@ -52,8 +52,6 @@ private void AddAutoMapper() { var config = _autoMapperConfigurationFactory.GetNew(); - // RegisterInstance(config); - // Register(() => config.CreateMapper()); RegisterInstance(config.CreateMapper()); } diff --git a/source/Jobbr.Server/ConfigurationManager.cs b/source/Jobbr.Server/ConfigurationManager.cs index 2c37fb5..81c91c3 100644 --- a/source/Jobbr.Server/ConfigurationManager.cs +++ b/source/Jobbr.Server/ConfigurationManager.cs @@ -120,7 +120,7 @@ public void ValidateConfigurationAndThrowOnErrors() if (!results.Values.All(r => r)) { - throw new ArgumentNullException("Configuration failed for one or more configurations"); + throw new Exception("Configuration failed for one or more configurations"); } } } diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index 59be916..e15918f 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -5,8 +5,7 @@ Jobber.Server Zuehlke Technology Group Jobbr.Server - Copyright © Zuehlke Technology Group 2015 - 1.0.6-pre + Copyright © Zuehlke Technology Group 2022 ..\JobbrRuleSet.ruleset bin\$(Configuration)\ @@ -36,9 +35,6 @@ all - - all - diff --git a/source/Jobbr.Server/JobbrServer.cs b/source/Jobbr.Server/JobbrServer.cs index e3216c3..9322d8b 100644 --- a/source/Jobbr.Server/JobbrServer.cs +++ b/source/Jobbr.Server/JobbrServer.cs @@ -215,7 +215,7 @@ private void StartOptionalComponents() } catch (Exception e) { - _logger.LogCritical("At least one of the services couldn't be started. Reason: {e}\n\n Please see the exception for details.", e.InnerException); + _logger.LogCritical(e, "At least one of the services couldn't be started. Reason: {e}\n\n Please see the exception for details.", e.InnerException); throw; } } @@ -231,7 +231,7 @@ private void WaitForDb() } catch (Exception ex) { - _logger.LogError("Exception while connecting to database to get all Jobs on startup: '{e}'", ex); + _logger.LogError(ex, "Exception while connecting to database to get all Jobs on startup"); Thread.Sleep(1000); } } @@ -250,7 +250,7 @@ private void RegisterJobsFromRepository() } catch (Exception e) { - _logger.LogCritical("Cannot register Jobs on startup. See Exception for details: {e}", e); + _logger.LogCritical(e, "Cannot register Jobs on startup. See exception for details."); } } } diff --git a/source/Jobbr.Server/Scheduling/DefaultScheduler.cs b/source/Jobbr.Server/Scheduling/DefaultScheduler.cs index 32bc6fc..16ff07a 100644 --- a/source/Jobbr.Server/Scheduling/DefaultScheduler.cs +++ b/source/Jobbr.Server/Scheduling/DefaultScheduler.cs @@ -313,7 +313,7 @@ private void SetRunningJobsToFailed() { jobRun.State = JobRunStates.Failed; _jobbrRepository.Update(jobRun); - + _logger.LogDebug("Set JobRun with id {jobRunId} for job {jobId} to the state 'Failed'. Possible Reason: Unclean shutdown.", jobRun.Id, jobRun.Job.Id); } } @@ -396,7 +396,7 @@ private void PublishCurrentPlan() } catch (Exception e) { - _logger.LogWarning("Unable to publish current plan to Executor. Exception: '{e}'", e); + _logger.LogWarning(e, "Unable to publish current plan to Executor."); } } @@ -414,13 +414,14 @@ private void UpdatePlannedJobRun(JobRun plannedNextRun, JobTriggerBase trigger, // Is this value in sync with the schedule table? if (plannedNextRun.PlannedStartDateTimeUtc == calculatedNextRun) { - _logger.LogDebug("The previously planned start date '{nextRunStart}' is still correct for JobRun (id: {nextRunId}) triggered by trigger with id '{triggerId}' (Type: '{triggerType}', userId: '{triggerUserId}', userName: '{triggerUserName}')", - calculatedNextRun, - plannedNextRun.Id, - trigger.Id, - trigger.GetType().Name, - trigger.UserId, - trigger.UserDisplayName); + _logger.LogDebug( + "The previously planned start date '{nextRunStart}' is still correct for JobRun (id: {nextRunId}) triggered by trigger with id '{triggerId}' (Type: '{triggerType}', userId: '{triggerUserId}', userName: '{triggerUserName}')", + calculatedNextRun, + plannedNextRun.Id, + trigger.Id, + trigger.GetType().Name, + trigger.UserId, + trigger.UserDisplayName); return; } @@ -431,10 +432,10 @@ private void UpdatePlannedJobRun(JobRun plannedNextRun, JobTriggerBase trigger, if (utcNow.AddSeconds(_schedulerConfiguration.AllowChangesBeforeStartInSec) >= calculatedNextRun) { _logger.LogWarning( - "The planned start date '{startTime}' has changed to '{nextRunStart}'. This change was done too close (less than {changeWindowSecs} seconds) to the next planned run and cannot be adjusted", - plannedNextRun.PlannedStartDateTimeUtc, - calculatedNextRun, - _schedulerConfiguration.AllowChangesBeforeStartInSec); + "The planned start date '{startTime}' has changed to '{nextRunStart}'. This change was done too close (less than {changeWindowSecs} seconds) to the next planned run and cannot be adjusted", + plannedNextRun.PlannedStartDateTimeUtc, + calculatedNextRun, + _schedulerConfiguration.AllowChangesBeforeStartInSec); return; } diff --git a/source/Jobbr.Server/Storage/JobbrRepository.cs b/source/Jobbr.Server/Storage/JobbrRepository.cs index 64f80a7..a760fa7 100644 --- a/source/Jobbr.Server/Storage/JobbrRepository.cs +++ b/source/Jobbr.Server/Storage/JobbrRepository.cs @@ -98,7 +98,7 @@ public PagedResult GetActiveTriggers(int page = 1, int pageSize } catch (Exception e) { - _logger.LogCritical("Cannot read active triggers from storage provider due to an exception. Returning empty list. Exception: {e}", e); + _logger.LogCritical(e, "Cannot read active triggers from storage provider due to an exception. Returning empty list."); return new PagedResult { diff --git a/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs b/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs index 97df34d..c254faa 100644 --- a/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs +++ b/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs @@ -98,7 +98,7 @@ public void ValidatorForSettings_WhenCalled_SettingsIsPassedThrough() } [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] + [ExpectedException(typeof(Exception))] public void ValidatorForSettings_ValidationFails_PreventsStart() { var builder = new JobbrBuilder(new NullLoggerFactory()); @@ -113,7 +113,7 @@ public void ValidatorForSettings_ValidationFails_PreventsStart() } [TestMethod] - [ExpectedException(typeof(ArgumentNullException))] + [ExpectedException(typeof(Exception))] public void ValidatorForSettings_ThrowsException_PreventsStart() { var builder = new JobbrBuilder(new NullLoggerFactory()); diff --git a/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs b/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs index 101974e..0bf7a05 100644 --- a/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs +++ b/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs @@ -6,7 +6,6 @@ using Jobbr.Server.Builder; using Jobbr.Tests.Infrastructure; using Microsoft.Extensions.Logging; -using Microsoft.Extensions.Logging.Abstractions; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Jobbr.Tests.Integration.Startup @@ -37,12 +36,19 @@ public void CreateJobber_WithConsoleCapturer_CaptureMessagesFromConsole() { using (var capture = new ConsoleCapturer()) { - var builder = new JobbrBuilder(new NullLoggerFactory()); + var loggerFactory = LoggerFactory.Create(builder => + { + _ = builder.AddConsole(); + }); + + var builder = new JobbrBuilder(loggerFactory); builder.Create(); var allLogEntries = capture.GetLines(); Assert.IsTrue(allLogEntries.Any()); + + loggerFactory.Dispose(); } } diff --git a/source/Jobbr.Tests/Jobbr.Tests.csproj b/source/Jobbr.Tests/Jobbr.Tests.csproj index 5392a0b..c7f2ac6 100644 --- a/source/Jobbr.Tests/Jobbr.Tests.csproj +++ b/source/Jobbr.Tests/Jobbr.Tests.csproj @@ -31,9 +31,6 @@ - - all - diff --git a/source/Jobbr.Tests/Registration/BuilderTests.cs b/source/Jobbr.Tests/Registration/BuilderTests.cs index bbe57ef..0264197 100644 --- a/source/Jobbr.Tests/Registration/BuilderTests.cs +++ b/source/Jobbr.Tests/Registration/BuilderTests.cs @@ -104,7 +104,6 @@ public void ShouldDeleteJobsAndTriggers_WhenSingleSourceOfTruthIsActivated() // Assert Assert.IsFalse(triggerForNonExistingJob.IsActive); Assert.IsTrue(triggerForNonExistingJob.Deleted); - _loggerFactory.Dispose(); } [TestMethod] From e884f7676782587c5f3eb7b81a6fb1ba94662308 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Thu, 8 Dec 2022 09:54:03 +0100 Subject: [PATCH 15/41] Mock ILoggerFactory in setup validation tests --- .../Integration/Startup/ConsoleCapturer.cs | 46 ---- .../Startup/SetupValidationTests.cs | 239 +++++++----------- 2 files changed, 92 insertions(+), 193 deletions(-) delete mode 100644 source/Jobbr.Tests/Integration/Startup/ConsoleCapturer.cs diff --git a/source/Jobbr.Tests/Integration/Startup/ConsoleCapturer.cs b/source/Jobbr.Tests/Integration/Startup/ConsoleCapturer.cs deleted file mode 100644 index 79e9d4d..0000000 --- a/source/Jobbr.Tests/Integration/Startup/ConsoleCapturer.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; - -namespace Jobbr.Tests.Integration.Startup -{ - public class ConsoleCapturer : TextWriter - { - private readonly TextWriter _consoleWriter; - private readonly StringBuilder _capture; - - public ConsoleCapturer() - { - _consoleWriter = Console.Out; - _capture = new StringBuilder(); - - Console.SetOut(this); - } - - public IEnumerable GetLines() - { - return _capture.ToString().Split(new[] { Environment.NewLine }, StringSplitOptions.None); - } - - public IEnumerable GetLines(params string[] needles) - { - return GetLines().Where(l => needles.Any(l.Contains)); - } - - public override Encoding Encoding => Encoding.UTF8; - - public override void Write(char value) - { - _consoleWriter.Write(value); - _capture.Append(value); - } - - protected override void Dispose(bool disposing) - { - Console.SetOut(_consoleWriter); - base.Dispose(disposing); - } - } -} \ No newline at end of file diff --git a/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs b/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs index 0bf7a05..0c404dc 100644 --- a/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs +++ b/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using Jobbr.ComponentModel.ArtefactStorage; using Jobbr.ComponentModel.Execution; using Jobbr.ComponentModel.JobStorage; @@ -7,193 +6,139 @@ using Jobbr.Tests.Infrastructure; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; namespace Jobbr.Tests.Integration.Startup { /// - /// Tests that makes sure that the builder issues warnings if not all required components are registered + /// Tests that makes sure that the builder issues warnings if not all required components are registered. /// [TestClass] public class SetupValidationTests { - [TestMethod] - public void ConsoleCapturer_WhenActive_ContainsConsoleOut() - { - using (var capture = new ConsoleCapturer()) - { - Console.WriteLine("Hello World"); + private Mock _loggerFactoryMock; + private Mock> _loggerMock; - var allLogEntries = capture.GetLines().ToList(); + [TestInitialize] + public void Initialize() + { + _loggerMock = new Mock>(); + _loggerMock.Setup(m => m.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>())); - Assert.IsTrue(allLogEntries.Any()); - Assert.AreEqual("Hello World", allLogEntries[0]); - Assert.AreEqual(2, allLogEntries.Count); - } + _loggerFactoryMock = new Mock(); + _loggerFactoryMock.Setup(m => m.CreateLogger(It.IsAny())).Returns(() => _loggerMock.Object); } [TestMethod] - public void CreateJobber_WithConsoleCapturer_CaptureMessagesFromConsole() + public void CreateJobber_LogsProcess() { - using (var capture = new ConsoleCapturer()) - { - var loggerFactory = LoggerFactory.Create(builder => - { - _ = builder.AddConsole(); - }); - - var builder = new JobbrBuilder(loggerFactory); - - builder.Create(); + // Arrange + var builder = new JobbrBuilder(_loggerFactoryMock.Object); - var allLogEntries = capture.GetLines(); - Assert.IsTrue(allLogEntries.Any()); + // Act + builder.Create(); - loggerFactory.Dispose(); - } + // Assert + _loggerMock.Verify(m => m.Log(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>()), Times.AtLeastOnce); } [TestMethod] public void CreateJobbr_WithNoStorageProvider_IssuesError() { - using (var capture = new ConsoleCapturer()) - { - var loggerFactory = LoggerFactory.Create(builder => - { - _ = builder.AddConsole(); - }); - - var builder = new JobbrBuilder(loggerFactory); - - // Register only Artefacts and Executor - builder.Register(typeof(PseudoArtefactsStorageProvider)); - builder.Register(typeof(PseudoExecutor)); - - builder.Create(); - - var storageWarnLogs = capture.GetLines("ERROR", "JobStorageProvider").ToList(); - - Assert.IsTrue(storageWarnLogs.Any()); - - Assert.AreEqual(1, storageWarnLogs.Count); - - loggerFactory.Dispose(); - } + // Arrange + var builder = new JobbrBuilder(_loggerFactoryMock.Object); + builder.Register(typeof(PseudoArtefactsStorageProvider)); + builder.Register(typeof(PseudoExecutor)); + + // Act + builder.Create(); + + // Assert + _loggerMock.Verify(m => m.Log( + LogLevel.Error, + It.IsAny(), + It.Is((v, _) => v.ToString().Contains("There was no JobStorageProvider registered. Will continue building with an in-memory version, which does not support production scenarios.")), + It.IsAny(), + It.IsAny>()), + Times.Once); } [TestMethod] public void CreateJobbr_WithNoArtefactsProvider_IssuesWarn() { - using (var capture = new ConsoleCapturer()) - { - var loggerFactory = LoggerFactory.Create(builder => - { - _ = builder.AddConsole(); - }); - - var builder = new JobbrBuilder(loggerFactory); - - // Register only Executor and JobStorage - builder.Register(typeof(PseudoExecutor)); - builder.Register(typeof(PseudoJobStorageProvider)); - - builder.Create(); - - var artefactsWarnings = capture.GetLines("warn", "Artefacts").ToList(); - - Assert.IsTrue(artefactsWarnings.Any()); - Assert.AreEqual(2, artefactsWarnings.Count); - - loggerFactory.Dispose(); - } + // Arrange + var builder = new JobbrBuilder(_loggerFactoryMock.Object); + builder.Register(typeof(PseudoExecutor)); + builder.Register(typeof(PseudoJobStorageProvider)); + + // Act + builder.Create(); + + // Assert + _loggerMock.Verify(m => m.Log( + LogLevel.Warning, + It.IsAny(), + It.Is((v, _) => v.ToString().Contains("There was no ArtefactsStorageProvider registered. Adding a default InMemoryArtefactStorage, which stores artefacts in memory. Please register a proper ArtefactStorage for production use.")), + It.IsAny(), + It.IsAny>()), + Times.Once); } [TestMethod] public void CreateJobbr_WithNoExecutor_IssuesError() { - using (var capture = new ConsoleCapturer()) - { - var loggerFactory = LoggerFactory.Create(builder => - { - _ = builder.AddConsole(); - }); - - var builder = new JobbrBuilder(loggerFactory); - - // Register only Artefacts and JoStorage - builder.Register(typeof(PseudoArtefactsStorageProvider)); - builder.Register(typeof(PseudoJobStorageProvider)); - - builder.Create(); - - var artefactsWarnings = capture.GetLines("error", "Executor").ToList(); - - Assert.IsTrue(artefactsWarnings.Any()); - Assert.AreEqual(1, artefactsWarnings.Count); - - loggerFactory.Dispose(); - } + // Arrange + var builder = new JobbrBuilder(_loggerFactoryMock.Object); + builder.Register(typeof(PseudoArtefactsStorageProvider)); + builder.Register(typeof(PseudoJobStorageProvider)); + + // Act + builder.Create(); + + // Assert + _loggerMock.Verify(m => m.Log( + LogLevel.Error, + It.IsAny(), + It.Is((v, _) => v.ToString().Contains("There was no JobExecutor registered. Adding a Non-Operational JobExecutor")), + It.IsAny(), + It.IsAny>()), + Times.Once); } [TestMethod] public void CreateJobbr_WithAllRequiredComponents_NoErrorNoWarn() { - using (var capture = new ConsoleCapturer()) - { - var loggerFactory = LoggerFactory.Create(builder => - { - _ = builder.AddConsole(); - }); - - var builder = new JobbrBuilder(loggerFactory); - - // Register only Artefacts and JoStorage - builder.Register(typeof(PseudoArtefactsStorageProvider)); - builder.Register(typeof(PseudoJobStorageProvider)); - builder.Register(typeof(PseudoExecutor)); - - builder.Create(); - - var errors = capture.GetLines("ERROR").ToList(); - var warnings = capture.GetLines("WARN").ToList(); - - Assert.IsFalse(errors.Any()); - Assert.IsFalse(warnings.Any()); - - loggerFactory.Dispose(); - } + // Arrange + var builder = new JobbrBuilder(_loggerFactoryMock.Object); + builder.Register(typeof(PseudoArtefactsStorageProvider)); + builder.Register(typeof(PseudoJobStorageProvider)); + builder.Register(typeof(PseudoExecutor)); + + // Act + builder.Create(); + + // Assert + _loggerMock.Verify(m => m.Log(LogLevel.Error, It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>()), Times.Never); + _loggerMock.Verify(m => m.Log(LogLevel.Warning, It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>()), Times.Never); } [TestMethod] public void StartJobbr_WithAllRequiredComponents_NoErrorNoWarn() { - using (var capture = new ConsoleCapturer()) - { - var loggerFactory = LoggerFactory.Create(builder => - { - _ = builder.AddConsole(); - }); - - var builder = new JobbrBuilder(loggerFactory); - - // Register only Artefacts and JoStorage - builder.Register(typeof(PseudoArtefactsStorageProvider)); - builder.Register(typeof(PseudoJobStorageProvider)); - builder.Register(typeof(PseudoExecutor)); - - var server = builder.Create(); - - server.Start(20000); - - var errors = capture.GetLines("ERROR").ToList(); - var warnings = capture.GetLines("WARN").ToList(); - var fatals = capture.GetLines("FATAL").ToList(); - - Assert.IsFalse(fatals.Any(), "Got too many fatals: \n\n * " + string.Join("\n * ", fatals)); - Assert.IsFalse(errors.Any(), "Got too many errors: \n\n * " + string.Join("\n * ", errors)); - Assert.IsFalse(warnings.Any(), "Got too many warnings: \n\n * " + string.Join("\n * ", warnings)); - - loggerFactory.Dispose(); - } + // Arrange + var builder = new JobbrBuilder(_loggerFactoryMock.Object); + builder.Register(typeof(PseudoArtefactsStorageProvider)); + builder.Register(typeof(PseudoJobStorageProvider)); + builder.Register(typeof(PseudoExecutor)); + + // Act + var server = builder.Create(); + + server.Start(20000); + + // Assert + _loggerMock.Verify(m => m.Log(LogLevel.Error, It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>()), Times.Never); + _loggerMock.Verify(m => m.Log(LogLevel.Warning, It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny>()), Times.Never); } } } \ No newline at end of file From e95efc84d226f61021f6362062bccec12a1128f9 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Thu, 8 Dec 2022 10:48:47 +0100 Subject: [PATCH 16/41] Add autogeneration tag back to TinyMessenger file --- source/Jobbr.Server/TinyMessenger.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/Jobbr.Server/TinyMessenger.cs b/source/Jobbr.Server/TinyMessenger.cs index 4025d8c..4e13426 100644 --- a/source/Jobbr.Server/TinyMessenger.cs +++ b/source/Jobbr.Server/TinyMessenger.cs @@ -1,4 +1,5 @@ -//=============================================================================== +// +//=============================================================================== // TinyIoC - TinyMessenger // // A simple messenger/event aggregator. From 3476c10bd0713e1d11c841760dfe914756e26d54 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Fri, 9 Dec 2022 12:12:09 +0100 Subject: [PATCH 17/41] Add dependencies to .nuspec --- source/Jobbr.Server.nuspec | 7 +++++++ source/Jobbr.Server/Jobbr.Server.csproj | 3 +++ source/Jobbr.Tests/PackagingTests.cs | 18 +++++++++++++++++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/source/Jobbr.Server.nuspec b/source/Jobbr.Server.nuspec index ea9dc8e..fbb3241 100644 --- a/source/Jobbr.Server.nuspec +++ b/source/Jobbr.Server.nuspec @@ -17,6 +17,13 @@ + + + + + + + diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index e15918f..3b3876b 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -6,6 +6,9 @@ Zuehlke Technology Group Jobbr.Server Copyright © Zuehlke Technology Group 2022 + GPL-3.0-only + images\icon.png + https://github.com/jobbrIO/jobbr-server ..\JobbrRuleSet.ruleset bin\$(Configuration)\ diff --git a/source/Jobbr.Tests/PackagingTests.cs b/source/Jobbr.Tests/PackagingTests.cs index c603783..b387772 100644 --- a/source/Jobbr.Tests/PackagingTests.cs +++ b/source/Jobbr.Tests/PackagingTests.cs @@ -17,7 +17,23 @@ public void Feature_NuSpec_IsCompliant() asserter.Add(new PackageExistsInBothRule("Jobbr.ComponentModel.Management")); asserter.Add(new PackageExistsInBothRule("Jobbr.ComponentModel.Registration")); - asserter.Add(new VersionIsIncludedInRange("Jobbr.ComponentModel.*")); + asserter.Add(new PackageExistsInBothRule("AutoMapper")); + asserter.Add(new PackageExistsInBothRule("Microsoft.Extensions.Configuration.Abstractions")); + asserter.Add(new PackageExistsInBothRule("Microsoft.Extensions.DependencyInjection")); + asserter.Add(new PackageExistsInBothRule("Microsoft.Extensions.Logging.Abstractions")); + asserter.Add(new PackageExistsInBothRule("NCrontab")); + asserter.Add(new PackageExistsInBothRule("SimpleInjector")); + asserter.Add(new PackageExistsInBothRule("TinyMessenger")); + + asserter.Add(new VersionIsIncludedInRange("Jobbr.ComponentModel.*")); + asserter.Add(new VersionIsIncludedInRange("AutoMapper")); + asserter.Add(new VersionIsIncludedInRange("Microsoft.Extensions.Configuration.Abstractions")); + asserter.Add(new VersionIsIncludedInRange("Microsoft.Extensions.DependencyInjection")); + asserter.Add(new VersionIsIncludedInRange("Microsoft.Extensions.Logging.Abstractions")); + asserter.Add(new VersionIsIncludedInRange("NCrontab")); + asserter.Add(new VersionIsIncludedInRange("SimpleInjector")); + asserter.Add(new VersionIsIncludedInRange("TinyMessenger")); + asserter.Add(new NoMajorChangesInNuSpec("Jobbr.*")); var result = asserter.Validate(); From ee4266e4f258bbcd78395fb57dc2732474cd1c92 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Mon, 12 Dec 2022 14:31:46 +0100 Subject: [PATCH 18/41] Upgrade ComponentModel NuGets to .NET 6 RCs --- source/Jobbr.Server.nuspec | 10 ++++----- source/Jobbr.Server/Builder/JobbrBuilder.cs | 22 +++++++++---------- source/Jobbr.Server/Jobbr.Server.csproj | 10 ++++----- .../Integration/JobbrServerTestBase.cs | 2 +- .../Startup/BadEnvironmentTests.cs | 4 ++-- .../Startup/ConfigurationValidationTests.cs | 8 +++---- source/Jobbr.Tests/Jobbr.Tests.csproj | 10 ++++----- .../Jobbr.Tests/Registration/BuilderTests.cs | 4 ++-- 8 files changed, 35 insertions(+), 35 deletions(-) diff --git a/source/Jobbr.Server.nuspec b/source/Jobbr.Server.nuspec index fbb3241..6ae00fb 100644 --- a/source/Jobbr.Server.nuspec +++ b/source/Jobbr.Server.nuspec @@ -12,11 +12,11 @@ Copyright 2022 images\icon.png - - - - - + + + + + diff --git a/source/Jobbr.Server/Builder/JobbrBuilder.cs b/source/Jobbr.Server/Builder/JobbrBuilder.cs index ff911ac..466cf79 100644 --- a/source/Jobbr.Server/Builder/JobbrBuilder.cs +++ b/source/Jobbr.Server/Builder/JobbrBuilder.cs @@ -94,33 +94,33 @@ public void Register(Type type) } /// - /// Registers given instance to given service type. + /// Appends given type to a collection of service type registrations. /// /// Service type. - /// Instance to register. - public void Add(object instance) + /// Type to register. + public void RegisterForCollection(Type type) { - _dependencyContainer.RegisterInstance(typeof(T), instance); + _dependencyContainer.Collection.Append(typeof(T), type); } /// - /// Appends given instance to a collection of service type registrations. + /// Registers given instance to given service type. /// /// Service type. /// Instance to register. - public void AppendInstanceToCollection(object instance) + public void Add(object instance) { - _dependencyContainer.Collection.AppendInstance(typeof(T), instance); + _dependencyContainer.RegisterInstance(typeof(T), instance); } /// - /// Appends given type to a collection of service type registrations. + /// Appends given instance to a collection of service type registrations. /// /// Service type. - /// Type to register. - public void AppendTypeToCollection(Type type) + /// Instance to register. + public void AddForCollection(object instance) { - _dependencyContainer.Collection.Append(typeof(T), type); + _dependencyContainer.Collection.AppendInstance(typeof(T), instance); } private void RegisterLogging(ILoggerFactory loggerFactory) diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index 3b3876b..3fb560d 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -38,10 +38,10 @@ all - - - - - + + + + + \ No newline at end of file diff --git a/source/Jobbr.Tests/Integration/JobbrServerTestBase.cs b/source/Jobbr.Tests/Integration/JobbrServerTestBase.cs index c0c0c48..5a5410f 100644 --- a/source/Jobbr.Tests/Integration/JobbrServerTestBase.cs +++ b/source/Jobbr.Tests/Integration/JobbrServerTestBase.cs @@ -48,7 +48,7 @@ protected static JobbrServer GivenAServerInstance() { var builder = new JobbrBuilder(new NullLoggerFactory()); - builder.AppendTypeToCollection(typeof(ExposeAllServicesComponent)); + builder.RegisterForCollection(typeof(ExposeAllServicesComponent)); var server = builder.Create(); return server; diff --git a/source/Jobbr.Tests/Integration/Startup/BadEnvironmentTests.cs b/source/Jobbr.Tests/Integration/Startup/BadEnvironmentTests.cs index b16c5da..08dc2aa 100644 --- a/source/Jobbr.Tests/Integration/Startup/BadEnvironmentTests.cs +++ b/source/Jobbr.Tests/Integration/Startup/BadEnvironmentTests.cs @@ -37,7 +37,7 @@ public void StartingJobbr_ComponentFails_IsInErrorState() { var nullLoggerFactory = new NullLoggerFactory(); var builder = new JobbrBuilder(nullLoggerFactory); - builder.AppendTypeToCollection(typeof(FaultyComponent)); + builder.RegisterForCollection(typeof(FaultyComponent)); var jobbr = builder.Create(); @@ -59,7 +59,7 @@ public void StartingJobbr_ComponentFails_IsInErrorState() public void StartingJobbr_ComponentFails_ExceptionIsThrown() { var builder = new JobbrBuilder(new NullLoggerFactory()); - builder.AppendTypeToCollection(typeof(FaultyComponent)); + builder.RegisterForCollection(typeof(FaultyComponent)); var jobbr = builder.Create(); diff --git a/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs b/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs index c254faa..3192dbd 100644 --- a/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs +++ b/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs @@ -68,7 +68,7 @@ public void ValidatorForSettings_WhenRegistered_IsCalled() builder.Add(new DemoSettings()); var isCalled = false; - builder.AppendInstanceToCollection(new DemoComponentValidator(s => isCalled = true)); + builder.AddForCollection(new DemoComponentValidator(s => isCalled = true)); var jobbr = builder.Create(); @@ -87,7 +87,7 @@ public void ValidatorForSettings_WhenCalled_SettingsIsPassedThrough() builder.Add(demoSettings); - builder.AppendInstanceToCollection(new DemoComponentValidator(s => settingsToValidate = s)); + builder.AddForCollection(new DemoComponentValidator(s => settingsToValidate = s)); var jobbr = builder.Create(); @@ -105,7 +105,7 @@ public void ValidatorForSettings_ValidationFails_PreventsStart() builder.Add(new DemoSettings()); - builder.AppendInstanceToCollection(new DemoComponentValidator(validationShouldFail: true, throwException: false)); + builder.AddForCollection(new DemoComponentValidator(validationShouldFail: true, throwException: false)); var jobbr = builder.Create(); @@ -120,7 +120,7 @@ public void ValidatorForSettings_ThrowsException_PreventsStart() builder.Add(new DemoSettings()); - builder.AppendInstanceToCollection(new DemoComponentValidator(validationShouldFail: false, throwException: true)); + builder.AddForCollection(new DemoComponentValidator(validationShouldFail: false, throwException: true)); var jobbr = builder.Create(); diff --git a/source/Jobbr.Tests/Jobbr.Tests.csproj b/source/Jobbr.Tests/Jobbr.Tests.csproj index c7f2ac6..5633007 100644 --- a/source/Jobbr.Tests/Jobbr.Tests.csproj +++ b/source/Jobbr.Tests/Jobbr.Tests.csproj @@ -31,11 +31,11 @@ - - - - - + + + + + diff --git a/source/Jobbr.Tests/Registration/BuilderTests.cs b/source/Jobbr.Tests/Registration/BuilderTests.cs index 0264197..a382213 100644 --- a/source/Jobbr.Tests/Registration/BuilderTests.cs +++ b/source/Jobbr.Tests/Registration/BuilderTests.cs @@ -40,7 +40,7 @@ public void RegisterCustomArtefactStorageProvider_AfterCreation_CorrectTypeIsAct var builder = new JobbrBuilder(_loggerFactory); builder.Register(typeof(CustomArtefactStorageAdapter)); - builder.AppendTypeToCollection(typeof(ExposeAllServicesComponent)); + builder.RegisterForCollection(typeof(ExposeAllServicesComponent)); // Act builder.Create(); @@ -58,7 +58,7 @@ public void RegisterCustomJobStorageProvider_AfterCreation_CorrectTypeIsActivate var builder = new JobbrBuilder(_loggerFactory); builder.Register(typeof(CustomJobStorageProvider)); - builder.AppendTypeToCollection(typeof(ExposeAllServicesComponent)); + builder.RegisterForCollection(typeof(ExposeAllServicesComponent)); // Act builder.Create(); From 1b9435b242e8da205e358beb3c670b2ee54faeb6 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Mon, 12 Dec 2022 15:39:27 +0100 Subject: [PATCH 19/41] Widen nuspec version limits to allow RC versions of 3.0 --- source/Jobbr.Server.nuspec | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/Jobbr.Server.nuspec b/source/Jobbr.Server.nuspec index 6ae00fb..5c5f95f 100644 --- a/source/Jobbr.Server.nuspec +++ b/source/Jobbr.Server.nuspec @@ -12,11 +12,11 @@ Copyright 2022 images\icon.png - - - - - + + + + + From d8d38a780fbb68afa8dd6171eab1296aa9f0c779 Mon Sep 17 00:00:00 2001 From: Loris <120105457+Moodiness@users.noreply.github.com> Date: Wed, 14 Dec 2022 08:26:02 +0100 Subject: [PATCH 20/41] feature/unit tests architecture (#88) * add new project for unit tests that uses Shouldly for assertions * rename existing integration test project --- .../JobRunService/ProgressChannelTests.cs | 2 +- .../Scheduler/ManualTimeProvider.cs | 2 +- .../Components/Scheduler/PeriodicTimerMock.cs | 2 +- .../Components/Scheduler/PlanningTests.cs | 2 +- .../Components/Scheduler/SchedulerTests.cs | 2 +- .../Components/Scheduler/TestBase.cs | 2 +- .../Infrastructure/Extensions.cs | 2 +- .../FaultyJobStorageProvider.cs | 2 +- .../PseudoArtefactsStorageProvider.cs | 2 +- .../Infrastructure/PseudoExecutor.cs | 2 +- .../PseudoJobStorageProvider.cs | 2 +- .../Execution/JobRunExecutionTestBase.cs | 2 +- .../JobRunInformationServiceTests.cs | 2 +- .../Execution/ProgressChannelTests.cs | 2 +- .../Integration/ExposeAllServicesComponent.cs | 2 +- .../Integration/JobRunEnumMappingTests.cs | 2 +- .../Integration/JobbrServerTestBase.cs | 2 +- .../Management/JobManagementTests.cs | 2 +- .../Management/JobQueryServiceTests.cs | 2 +- .../Integration/Scheduler/SchedulerTests.cs | 2 +- .../Startup/BadEnvironmentTests.cs | 5 +- .../Startup/ConfigurationValidationTests.cs | 2 +- .../Startup/SetupValidationTests.cs | 4 +- .../Jobbr.Server.IntegrationTests.csproj} | 8 +- .../PackagingTests.cs | 2 +- .../Registration/BuilderTests.cs | 4 +- .../Registration/TriggerExtensionsTests.cs | 2 +- .../WaitFor.cs | 2 +- .../app.config | 0 .../Core/JobServiceTests.cs | 46 +++++++ .../Jobbr.Server.UnitTests.csproj | 36 ++++++ .../Storage/ExtensionMethodsTests.cs | 114 ++++++++++++++++++ source/Jobbr.Server.sln | 8 +- source/Jobbr.Server/Jobbr.Server.csproj | 6 +- 34 files changed, 244 insertions(+), 35 deletions(-) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Components/JobRunService/ProgressChannelTests.cs (98%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Components/Scheduler/ManualTimeProvider.cs (91%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Components/Scheduler/PeriodicTimerMock.cs (87%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Components/Scheduler/PlanningTests.cs (99%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Components/Scheduler/SchedulerTests.cs (99%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Components/Scheduler/TestBase.cs (96%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Infrastructure/Extensions.cs (92%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Infrastructure/FaultyJobStorageProvider.cs (99%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Infrastructure/PseudoArtefactsStorageProvider.cs (90%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Infrastructure/PseudoExecutor.cs (90%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Infrastructure/PseudoJobStorageProvider.cs (99%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Integration/Execution/JobRunExecutionTestBase.cs (96%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Integration/Execution/JobRunInformationServiceTests.cs (97%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Integration/Execution/ProgressChannelTests.cs (98%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Integration/ExposeAllServicesComponent.cs (97%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Integration/JobRunEnumMappingTests.cs (99%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Integration/JobbrServerTestBase.cs (97%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Integration/Management/JobManagementTests.cs (98%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Integration/Management/JobQueryServiceTests.cs (99%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Integration/Scheduler/SchedulerTests.cs (99%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Integration/Startup/BadEnvironmentTests.cs (96%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Integration/Startup/ConfigurationValidationTests.cs (98%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Integration/Startup/SetupValidationTests.cs (98%) rename source/{Jobbr.Tests/Jobbr.Tests.csproj => Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj} (90%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/PackagingTests.cs (98%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Registration/BuilderTests.cs (99%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/Registration/TriggerExtensionsTests.cs (99%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/WaitFor.cs (97%) rename source/{Jobbr.Tests => Jobbr.Server.IntegrationTests}/app.config (100%) create mode 100644 source/Jobbr.Server.UnitTests/Core/JobServiceTests.cs create mode 100644 source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj create mode 100644 source/Jobbr.Server.UnitTests/Storage/ExtensionMethodsTests.cs diff --git a/source/Jobbr.Tests/Components/JobRunService/ProgressChannelTests.cs b/source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressChannelTests.cs similarity index 98% rename from source/Jobbr.Tests/Components/JobRunService/ProgressChannelTests.cs rename to source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressChannelTests.cs index 275a832..4663ae3 100644 --- a/source/Jobbr.Tests/Components/JobRunService/ProgressChannelTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressChannelTests.cs @@ -8,7 +8,7 @@ using TinyMessenger; using JobRunStates = Jobbr.Server.Core.Models.JobRunStates; -namespace Jobbr.Tests.Components.JobRunService +namespace Jobbr.Server.IntegrationTests.Components.JobRunService { [TestClass] public class ProgressUpdateTests diff --git a/source/Jobbr.Tests/Components/Scheduler/ManualTimeProvider.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/ManualTimeProvider.cs similarity index 91% rename from source/Jobbr.Tests/Components/Scheduler/ManualTimeProvider.cs rename to source/Jobbr.Server.IntegrationTests/Components/Scheduler/ManualTimeProvider.cs index b52eb90..3edd157 100644 --- a/source/Jobbr.Tests/Components/Scheduler/ManualTimeProvider.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/ManualTimeProvider.cs @@ -1,7 +1,7 @@ using System; using Jobbr.Server.Scheduling; -namespace Jobbr.Tests.Components.Scheduler +namespace Jobbr.Server.IntegrationTests.Components.Scheduler { public class ManualTimeProvider : IDateTimeProvider { diff --git a/source/Jobbr.Tests/Components/Scheduler/PeriodicTimerMock.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PeriodicTimerMock.cs similarity index 87% rename from source/Jobbr.Tests/Components/Scheduler/PeriodicTimerMock.cs rename to source/Jobbr.Server.IntegrationTests/Components/Scheduler/PeriodicTimerMock.cs index 884799f..d3728fc 100644 --- a/source/Jobbr.Tests/Components/Scheduler/PeriodicTimerMock.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PeriodicTimerMock.cs @@ -1,7 +1,7 @@ using System; using Jobbr.Server.Scheduling; -namespace Jobbr.Tests.Components.Scheduler +namespace Jobbr.Server.IntegrationTests.Components.Scheduler { public class PeriodicTimerMock : IPeriodicTimer { diff --git a/source/Jobbr.Tests/Components/Scheduler/PlanningTests.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PlanningTests.cs similarity index 99% rename from source/Jobbr.Tests/Components/Scheduler/PlanningTests.cs rename to source/Jobbr.Server.IntegrationTests/Components/Scheduler/PlanningTests.cs index d440fbf..44106d3 100644 --- a/source/Jobbr.Tests/Components/Scheduler/PlanningTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PlanningTests.cs @@ -4,7 +4,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using JobRunStates = Jobbr.ComponentModel.JobStorage.Model.JobRunStates; -namespace Jobbr.Tests.Components.Scheduler +namespace Jobbr.Server.IntegrationTests.Components.Scheduler { [TestClass] public class PlanningTests : TestBase diff --git a/source/Jobbr.Tests/Components/Scheduler/SchedulerTests.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/SchedulerTests.cs similarity index 99% rename from source/Jobbr.Tests/Components/Scheduler/SchedulerTests.cs rename to source/Jobbr.Server.IntegrationTests/Components/Scheduler/SchedulerTests.cs index 7275884..ba3ed2d 100644 --- a/source/Jobbr.Tests/Components/Scheduler/SchedulerTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/SchedulerTests.cs @@ -3,7 +3,7 @@ using Jobbr.ComponentModel.JobStorage.Model; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jobbr.Tests.Components.Scheduler +namespace Jobbr.Server.IntegrationTests.Components.Scheduler { [TestClass] public class SchedulerTests : TestBase diff --git a/source/Jobbr.Tests/Components/Scheduler/TestBase.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/TestBase.cs similarity index 96% rename from source/Jobbr.Tests/Components/Scheduler/TestBase.cs rename to source/Jobbr.Server.IntegrationTests/Components/Scheduler/TestBase.cs index 3e80a36..e664ae5 100644 --- a/source/Jobbr.Tests/Components/Scheduler/TestBase.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/TestBase.cs @@ -8,7 +8,7 @@ using Microsoft.Extensions.Logging.Abstractions; using Moq; -namespace Jobbr.Tests.Components.Scheduler +namespace Jobbr.Server.IntegrationTests.Components.Scheduler { public class TestBase { diff --git a/source/Jobbr.Tests/Infrastructure/Extensions.cs b/source/Jobbr.Server.IntegrationTests/Infrastructure/Extensions.cs similarity index 92% rename from source/Jobbr.Tests/Infrastructure/Extensions.cs rename to source/Jobbr.Server.IntegrationTests/Infrastructure/Extensions.cs index 4802230..92e18ab 100644 --- a/source/Jobbr.Tests/Infrastructure/Extensions.cs +++ b/source/Jobbr.Server.IntegrationTests/Infrastructure/Extensions.cs @@ -1,7 +1,7 @@ using System.IO; using System.Runtime.Serialization.Formatters.Binary; -namespace Jobbr.Tests.Infrastructure +namespace Jobbr.Server.IntegrationTests.Infrastructure { public static class ExtensionMethods { diff --git a/source/Jobbr.Tests/Infrastructure/FaultyJobStorageProvider.cs b/source/Jobbr.Server.IntegrationTests/Infrastructure/FaultyJobStorageProvider.cs similarity index 99% rename from source/Jobbr.Tests/Infrastructure/FaultyJobStorageProvider.cs rename to source/Jobbr.Server.IntegrationTests/Infrastructure/FaultyJobStorageProvider.cs index 9a40b16..9a8f6dc 100644 --- a/source/Jobbr.Tests/Infrastructure/FaultyJobStorageProvider.cs +++ b/source/Jobbr.Server.IntegrationTests/Infrastructure/FaultyJobStorageProvider.cs @@ -4,7 +4,7 @@ using Jobbr.ComponentModel.JobStorage.Model; using Jobbr.Server.Storage; -namespace Jobbr.Tests.Infrastructure +namespace Jobbr.Server.IntegrationTests.Infrastructure { public class FaultyJobStorageProvider : IJobStorageProvider { diff --git a/source/Jobbr.Tests/Infrastructure/PseudoArtefactsStorageProvider.cs b/source/Jobbr.Server.IntegrationTests/Infrastructure/PseudoArtefactsStorageProvider.cs similarity index 90% rename from source/Jobbr.Tests/Infrastructure/PseudoArtefactsStorageProvider.cs rename to source/Jobbr.Server.IntegrationTests/Infrastructure/PseudoArtefactsStorageProvider.cs index 78c0f0a..75971ae 100644 --- a/source/Jobbr.Tests/Infrastructure/PseudoArtefactsStorageProvider.cs +++ b/source/Jobbr.Server.IntegrationTests/Infrastructure/PseudoArtefactsStorageProvider.cs @@ -3,7 +3,7 @@ using Jobbr.ComponentModel.ArtefactStorage; using Jobbr.ComponentModel.ArtefactStorage.Model; -namespace Jobbr.Tests.Infrastructure +namespace Jobbr.Server.IntegrationTests.Infrastructure { public class PseudoArtefactsStorageProvider : IArtefactsStorageProvider { diff --git a/source/Jobbr.Tests/Infrastructure/PseudoExecutor.cs b/source/Jobbr.Server.IntegrationTests/Infrastructure/PseudoExecutor.cs similarity index 90% rename from source/Jobbr.Tests/Infrastructure/PseudoExecutor.cs rename to source/Jobbr.Server.IntegrationTests/Infrastructure/PseudoExecutor.cs index 7a0bc4b..7fec1c2 100644 --- a/source/Jobbr.Tests/Infrastructure/PseudoExecutor.cs +++ b/source/Jobbr.Server.IntegrationTests/Infrastructure/PseudoExecutor.cs @@ -2,7 +2,7 @@ using Jobbr.ComponentModel.Execution; using Jobbr.ComponentModel.Execution.Model; -namespace Jobbr.Tests.Infrastructure +namespace Jobbr.Server.IntegrationTests.Infrastructure { public class PseudoExecutor : IJobExecutor { diff --git a/source/Jobbr.Tests/Infrastructure/PseudoJobStorageProvider.cs b/source/Jobbr.Server.IntegrationTests/Infrastructure/PseudoJobStorageProvider.cs similarity index 99% rename from source/Jobbr.Tests/Infrastructure/PseudoJobStorageProvider.cs rename to source/Jobbr.Server.IntegrationTests/Infrastructure/PseudoJobStorageProvider.cs index 0131161..3a577b1 100644 --- a/source/Jobbr.Tests/Infrastructure/PseudoJobStorageProvider.cs +++ b/source/Jobbr.Server.IntegrationTests/Infrastructure/PseudoJobStorageProvider.cs @@ -3,7 +3,7 @@ using Jobbr.ComponentModel.JobStorage; using Jobbr.ComponentModel.JobStorage.Model; -namespace Jobbr.Tests.Infrastructure +namespace Jobbr.Server.IntegrationTests.Infrastructure { public class PseudoJobStorageProvider : IJobStorageProvider { diff --git a/source/Jobbr.Tests/Integration/Execution/JobRunExecutionTestBase.cs b/source/Jobbr.Server.IntegrationTests/Integration/Execution/JobRunExecutionTestBase.cs similarity index 96% rename from source/Jobbr.Tests/Integration/Execution/JobRunExecutionTestBase.cs rename to source/Jobbr.Server.IntegrationTests/Integration/Execution/JobRunExecutionTestBase.cs index c550738..f98b7f0 100644 --- a/source/Jobbr.Tests/Integration/Execution/JobRunExecutionTestBase.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Execution/JobRunExecutionTestBase.cs @@ -3,7 +3,7 @@ using InstantTrigger = Jobbr.ComponentModel.Management.Model.InstantTrigger; using Job = Jobbr.ComponentModel.Management.Model.Job; -namespace Jobbr.Tests.Integration.Execution +namespace Jobbr.Server.IntegrationTests.Integration.Execution { public class JobRunExecutionTestBase : RunningJobbrServerTestBase { diff --git a/source/Jobbr.Tests/Integration/Execution/JobRunInformationServiceTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Execution/JobRunInformationServiceTests.cs similarity index 97% rename from source/Jobbr.Tests/Integration/Execution/JobRunInformationServiceTests.cs rename to source/Jobbr.Server.IntegrationTests/Integration/Execution/JobRunInformationServiceTests.cs index 4a35e5a..0126f5d 100644 --- a/source/Jobbr.Tests/Integration/Execution/JobRunInformationServiceTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Execution/JobRunInformationServiceTests.cs @@ -1,6 +1,6 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jobbr.Tests.Integration.Execution +namespace Jobbr.Server.IntegrationTests.Integration.Execution { [TestClass] public class JobRunInformationServiceTests : JobRunExecutionTestBase diff --git a/source/Jobbr.Tests/Integration/Execution/ProgressChannelTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Execution/ProgressChannelTests.cs similarity index 98% rename from source/Jobbr.Tests/Integration/Execution/ProgressChannelTests.cs rename to source/Jobbr.Server.IntegrationTests/Integration/Execution/ProgressChannelTests.cs index 9f93c72..b90d90f 100644 --- a/source/Jobbr.Tests/Integration/Execution/ProgressChannelTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Execution/ProgressChannelTests.cs @@ -3,7 +3,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using JobRunStates = Jobbr.ComponentModel.Execution.Model.JobRunStates; -namespace Jobbr.Tests.Integration.Execution +namespace Jobbr.Server.IntegrationTests.Integration.Execution { [TestClass] public class ProgressChannelTests : JobRunExecutionTestBase diff --git a/source/Jobbr.Tests/Integration/ExposeAllServicesComponent.cs b/source/Jobbr.Server.IntegrationTests/Integration/ExposeAllServicesComponent.cs similarity index 97% rename from source/Jobbr.Tests/Integration/ExposeAllServicesComponent.cs rename to source/Jobbr.Server.IntegrationTests/Integration/ExposeAllServicesComponent.cs index 601a66b..5f4ed56 100644 --- a/source/Jobbr.Tests/Integration/ExposeAllServicesComponent.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/ExposeAllServicesComponent.cs @@ -5,7 +5,7 @@ using Jobbr.ComponentModel.Management; using Jobbr.ComponentModel.Registration; -namespace Jobbr.Tests.Integration +namespace Jobbr.Server.IntegrationTests.Integration { /// /// This component consumes all services provided by a standard JobbrServer instance and makes them available by separate properties diff --git a/source/Jobbr.Tests/Integration/JobRunEnumMappingTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/JobRunEnumMappingTests.cs similarity index 99% rename from source/Jobbr.Tests/Integration/JobRunEnumMappingTests.cs rename to source/Jobbr.Server.IntegrationTests/Integration/JobRunEnumMappingTests.cs index cf8d945..7f017b3 100644 --- a/source/Jobbr.Tests/Integration/JobRunEnumMappingTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/JobRunEnumMappingTests.cs @@ -4,7 +4,7 @@ using System.Reflection; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jobbr.Tests.Integration +namespace Jobbr.Server.IntegrationTests.Integration { /// /// Tests that confirm that all members if JobRunStates do have same values if their name are equal diff --git a/source/Jobbr.Tests/Integration/JobbrServerTestBase.cs b/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs similarity index 97% rename from source/Jobbr.Tests/Integration/JobbrServerTestBase.cs rename to source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs index 5a5410f..8f741fd 100644 --- a/source/Jobbr.Tests/Integration/JobbrServerTestBase.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs @@ -5,7 +5,7 @@ using Microsoft.Extensions.Logging.Abstractions; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jobbr.Tests.Integration +namespace Jobbr.Server.IntegrationTests.Integration { public abstract class JobbrServerTestBase { diff --git a/source/Jobbr.Tests/Integration/Management/JobManagementTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Management/JobManagementTests.cs similarity index 98% rename from source/Jobbr.Tests/Integration/Management/JobManagementTests.cs rename to source/Jobbr.Server.IntegrationTests/Integration/Management/JobManagementTests.cs index fd29b05..872ab34 100644 --- a/source/Jobbr.Tests/Integration/Management/JobManagementTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Management/JobManagementTests.cs @@ -3,7 +3,7 @@ using Jobbr.ComponentModel.JobStorage.Model; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jobbr.Tests.Integration.Management +namespace Jobbr.Server.IntegrationTests.Integration.Management { [TestClass] public class JobManagementTests : InitializedJobbrServerTestBase diff --git a/source/Jobbr.Tests/Integration/Management/JobQueryServiceTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Management/JobQueryServiceTests.cs similarity index 99% rename from source/Jobbr.Tests/Integration/Management/JobQueryServiceTests.cs rename to source/Jobbr.Server.IntegrationTests/Integration/Management/JobQueryServiceTests.cs index 4b256d8..c0d199f 100644 --- a/source/Jobbr.Tests/Integration/Management/JobQueryServiceTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Management/JobQueryServiceTests.cs @@ -4,7 +4,7 @@ using Jobbr.ComponentModel.Management; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jobbr.Tests.Integration.Management +namespace Jobbr.Server.IntegrationTests.Integration.Management { [TestClass] public class JobQueryServiceTests : InitializedJobbrServerTestBase diff --git a/source/Jobbr.Tests/Integration/Scheduler/SchedulerTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Scheduler/SchedulerTests.cs similarity index 99% rename from source/Jobbr.Tests/Integration/Scheduler/SchedulerTests.cs rename to source/Jobbr.Server.IntegrationTests/Integration/Scheduler/SchedulerTests.cs index 28d1cc3..6f409ea 100644 --- a/source/Jobbr.Tests/Integration/Scheduler/SchedulerTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Scheduler/SchedulerTests.cs @@ -5,7 +5,7 @@ using Job = Jobbr.ComponentModel.JobStorage.Model.Job; using JobRunStates = Jobbr.ComponentModel.JobStorage.Model.JobRunStates; -namespace Jobbr.Tests.Integration.Scheduler +namespace Jobbr.Server.IntegrationTests.Integration.Scheduler { [TestClass] public class SchedulerTests : RunningJobbrServerTestBase diff --git a/source/Jobbr.Tests/Integration/Startup/BadEnvironmentTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Startup/BadEnvironmentTests.cs similarity index 96% rename from source/Jobbr.Tests/Integration/Startup/BadEnvironmentTests.cs rename to source/Jobbr.Server.IntegrationTests/Integration/Startup/BadEnvironmentTests.cs index 08dc2aa..6ebd610 100644 --- a/source/Jobbr.Tests/Integration/Startup/BadEnvironmentTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Startup/BadEnvironmentTests.cs @@ -2,13 +2,12 @@ using System.Threading; using Jobbr.ComponentModel.JobStorage; using Jobbr.ComponentModel.Registration; -using Jobbr.Server; using Jobbr.Server.Builder; -using Jobbr.Tests.Infrastructure; +using Jobbr.Server.IntegrationTests.Infrastructure; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jobbr.Tests.Integration.Startup +namespace Jobbr.Server.IntegrationTests.Integration.Startup { [TestClass] public class BadEnvironmentTests diff --git a/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Startup/ConfigurationValidationTests.cs similarity index 98% rename from source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs rename to source/Jobbr.Server.IntegrationTests/Integration/Startup/ConfigurationValidationTests.cs index 3192dbd..92367c5 100644 --- a/source/Jobbr.Tests/Integration/Startup/ConfigurationValidationTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Startup/ConfigurationValidationTests.cs @@ -4,7 +4,7 @@ using Microsoft.Extensions.Logging.Abstractions; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jobbr.Tests.Integration.Startup +namespace Jobbr.Server.IntegrationTests.Integration.Startup { [TestClass] public class ConfigurationValidationTests diff --git a/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Startup/SetupValidationTests.cs similarity index 98% rename from source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs rename to source/Jobbr.Server.IntegrationTests/Integration/Startup/SetupValidationTests.cs index 0c404dc..3650f98 100644 --- a/source/Jobbr.Tests/Integration/Startup/SetupValidationTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Startup/SetupValidationTests.cs @@ -3,12 +3,12 @@ using Jobbr.ComponentModel.Execution; using Jobbr.ComponentModel.JobStorage; using Jobbr.Server.Builder; -using Jobbr.Tests.Infrastructure; +using Jobbr.Server.IntegrationTests.Infrastructure; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; -namespace Jobbr.Tests.Integration.Startup +namespace Jobbr.Server.IntegrationTests.Integration.Startup { /// /// Tests that makes sure that the builder issues warnings if not all required components are registered. diff --git a/source/Jobbr.Tests/Jobbr.Tests.csproj b/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj similarity index 90% rename from source/Jobbr.Tests/Jobbr.Tests.csproj rename to source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj index 5633007..0cf7af5 100644 --- a/source/Jobbr.Tests/Jobbr.Tests.csproj +++ b/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj @@ -7,9 +7,9 @@ $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages False UnitTest - Jobbr.Tests + Jobbr.Server.IntegrationTests Zuehlke Technology Group - Jobbr.Tests + Jobbr.Server.IntegrationTests Copyright © Zuehlke Technology Group 2015 1.0.0.0-pre bin\$(Configuration)\ @@ -30,6 +30,10 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/source/Jobbr.Tests/PackagingTests.cs b/source/Jobbr.Server.IntegrationTests/PackagingTests.cs similarity index 98% rename from source/Jobbr.Tests/PackagingTests.cs rename to source/Jobbr.Server.IntegrationTests/PackagingTests.cs index b387772..378e8c0 100644 --- a/source/Jobbr.Tests/PackagingTests.cs +++ b/source/Jobbr.Server.IntegrationTests/PackagingTests.cs @@ -1,7 +1,7 @@ using Jobbr.DevSupport.ReferencedVersionAsserter; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jobbr.Tests +namespace Jobbr.Server.IntegrationTests { [TestClass] public class PackagingTests diff --git a/source/Jobbr.Tests/Registration/BuilderTests.cs b/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs similarity index 99% rename from source/Jobbr.Tests/Registration/BuilderTests.cs rename to source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs index a382213..02bf873 100644 --- a/source/Jobbr.Tests/Registration/BuilderTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs @@ -8,13 +8,13 @@ using Jobbr.ComponentModel.JobStorage.Model; using Jobbr.ComponentModel.Registration; using Jobbr.Server.Builder; +using Jobbr.Server.IntegrationTests.Integration; using Jobbr.Server.JobRegistry; -using Jobbr.Tests.Integration; using Microsoft.Extensions.Logging; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; -namespace Jobbr.Tests.Registration +namespace Jobbr.Server.IntegrationTests.Registration { [TestClass] public class BuilderTests diff --git a/source/Jobbr.Tests/Registration/TriggerExtensionsTests.cs b/source/Jobbr.Server.IntegrationTests/Registration/TriggerExtensionsTests.cs similarity index 99% rename from source/Jobbr.Tests/Registration/TriggerExtensionsTests.cs rename to source/Jobbr.Server.IntegrationTests/Registration/TriggerExtensionsTests.cs index 4744116..df0ce0a 100644 --- a/source/Jobbr.Tests/Registration/TriggerExtensionsTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Registration/TriggerExtensionsTests.cs @@ -3,7 +3,7 @@ using Jobbr.Server.JobRegistry; using Microsoft.VisualStudio.TestTools.UnitTesting; -namespace Jobbr.Tests.Registration +namespace Jobbr.Server.IntegrationTests.Registration { [TestClass] public class TriggerExtensionsTests diff --git a/source/Jobbr.Tests/WaitFor.cs b/source/Jobbr.Server.IntegrationTests/WaitFor.cs similarity index 97% rename from source/Jobbr.Tests/WaitFor.cs rename to source/Jobbr.Server.IntegrationTests/WaitFor.cs index e106cc9..5991faa 100644 --- a/source/Jobbr.Tests/WaitFor.cs +++ b/source/Jobbr.Server.IntegrationTests/WaitFor.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Threading; -namespace Jobbr.Tests +namespace Jobbr.Server.IntegrationTests { public static class WaitFor { diff --git a/source/Jobbr.Tests/app.config b/source/Jobbr.Server.IntegrationTests/app.config similarity index 100% rename from source/Jobbr.Tests/app.config rename to source/Jobbr.Server.IntegrationTests/app.config diff --git a/source/Jobbr.Server.UnitTests/Core/JobServiceTests.cs b/source/Jobbr.Server.UnitTests/Core/JobServiceTests.cs new file mode 100644 index 0000000..da42f4f --- /dev/null +++ b/source/Jobbr.Server.UnitTests/Core/JobServiceTests.cs @@ -0,0 +1,46 @@ +using AutoMapper; +using Jobbr.ComponentModel.JobStorage.Model; +using Jobbr.Server.Core; +using Jobbr.Server.Core.Models; +using Jobbr.Server.Storage; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Shouldly; + +namespace Jobbr.Server.UnitTests.Core +{ + [TestClass] + public class JobServiceTests + { + private readonly IJobService _service; + private readonly Mock _repositoryMock; + + public JobServiceTests() + { + var config = new MapperConfiguration(cfg => cfg.AddProfile()); + + var mapper = config.CreateMapper(); + + _repositoryMock = new Mock(); + + _service = new JobService(_repositoryMock.Object, mapper); + } + + [TestMethod] + public void Add_ShouldAddOrUpdateModelId() + { + // Arrange + JobModel model = new JobModel { Title = "Test" }; + var jobId = 155L; + _repositoryMock.Setup(rep => rep.AddJob(It.IsAny())).Callback(job => job.Id = jobId); + + // Act + var result = _service.Add(model); + + // Assert + result.ShouldNotBeNull(); + result.Title.ShouldBe("Test"); + result.Id.ShouldBe(jobId); + } + } +} diff --git a/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj b/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj new file mode 100644 index 0000000..8a097a5 --- /dev/null +++ b/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj @@ -0,0 +1,36 @@ + + + net6.0 + Jobbr.Server.UnitTests + Zuehlke Technology Group + Copyright © Zuehlke Technology Group 2022 + Jobbr.Server.UnitTests + 1.0.0.0-pre + bin\$(Configuration)\ + ..\JobbrRuleSet.ruleset + + + full + + + full + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/source/Jobbr.Server.UnitTests/Storage/ExtensionMethodsTests.cs b/source/Jobbr.Server.UnitTests/Storage/ExtensionMethodsTests.cs new file mode 100644 index 0000000..dfc67fe --- /dev/null +++ b/source/Jobbr.Server.UnitTests/Storage/ExtensionMethodsTests.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Runtime.Serialization; +using Jobbr.Server.Storage; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Shouldly; + +namespace Jobbr.Server.UnitTests.Storage +{ + [TestClass] + public class ExtensionMethodsTests + { + [TestMethod] + public void CloneNullObject_ShouldNotThrow() + { + // Arrange + object? data = null; + + // Act + var dataClone = ExtensionMethods.Clone(data); + + // Assert + dataClone.ShouldBeNull(); + } + + [TestMethod] + public void CloneObject_ShouldCreateDeepClone() + { + // Arrange + var data = new TestClass("reference", 5); + + // Act + var dataClone = ExtensionMethods.Clone(data); + + // Assert + dataClone.ShouldNotBeNull(); + dataClone.Key.ShouldBe(data.Key); + dataClone.Value.ShouldBe(data.Value); + dataClone.ShouldNotBe(data); + } + + [TestMethod] + [DataRow(1)] + [DataRow(1.45)] + [DataRow("test")] + public void CloneValueTypes_ShouldReturnCopy(object value) + { + // Act + var clone = ExtensionMethods.Clone(value); + + // Assert + clone.ShouldBe(value); + } + + [TestMethod] + public void CloneList_ShouldDeepCloneAllEntries() + { + var data = new List + { + new TestClass("value-1", 1), + new TestClass("value-2", 2), + new TestClass("value-3", 3), + }; + + // Act + var dataClone = ExtensionMethods.Clone(data); + + // Assert + dataClone.ShouldNotBeNull(); + dataClone.Count.ShouldBe(data.Count); + dataClone.ShouldNotBeEmpty(); + dataClone.ShouldNotBe(data); + dataClone.ShouldBe(data, comparer: new TestClassValueComparer()); + } + + [TestMethod] + public void CloneObject_NoSerializableFlag_ThrowsSerializationException() + { + // Arrange + var data = new { Key = "reference", Value = 2 }; + + // Act & Arrange + Should.Throw(() => ExtensionMethods.Clone(data)); + } + + [Serializable] + private class TestClass + { + public TestClass(string key, int value) + { + Key = key; + Value = value; + } + + public string Key { get; set; } + + public int Value { get; set; } + } + + private class TestClassValueComparer : IEqualityComparer + { + public bool Equals(TestClass? x, TestClass? y) + { + return x is not null && y is not null && x.Value == y.Value && x.Key == y.Key; + } + + public int GetHashCode([DisallowNull] TestClass obj) + { + return HashCode.Combine(obj.Key, obj.Value); + } + } + } +} diff --git a/source/Jobbr.Server.sln b/source/Jobbr.Server.sln index 705636b..f7d31c4 100644 --- a/source/Jobbr.Server.sln +++ b/source/Jobbr.Server.sln @@ -12,7 +12,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SolutionFiles", "SolutionFi EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jobbr.Server", "Jobbr.Server\Jobbr.Server.csproj", "{A45F729D-8629-4C7A-96B8-29EAA8D52919}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jobbr.Tests", "Jobbr.Tests\Jobbr.Tests.csproj", "{304D07A5-D6D1-4F48-819E-5D28ED8755AC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jobbr.Server.IntegrationTests", "Jobbr.Server.IntegrationTests\Jobbr.Server.IntegrationTests.csproj", "{304D07A5-D6D1-4F48-819E-5D28ED8755AC}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{13B2F939-2E3C-4145-A00B-6B6D42680598}" ProjectSection(SolutionItems) = preProject @@ -31,6 +31,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution .editorconfig = .editorconfig EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jobbr.Server.UnitTests", "Jobbr.Server.UnitTests\Jobbr.Server.UnitTests.csproj", "{73B0ED2D-F2BE-4EF2-B10E-BA16CCF392EA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -49,6 +51,10 @@ Global {D7C78DBD-D440-4D0C-B9A9-AD8B7473364A}.Debug|Any CPU.Build.0 = Debug|Any CPU {D7C78DBD-D440-4D0C-B9A9-AD8B7473364A}.Release|Any CPU.ActiveCfg = Release|Any CPU {D7C78DBD-D440-4D0C-B9A9-AD8B7473364A}.Release|Any CPU.Build.0 = Release|Any CPU + {73B0ED2D-F2BE-4EF2-B10E-BA16CCF392EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {73B0ED2D-F2BE-4EF2-B10E-BA16CCF392EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {73B0ED2D-F2BE-4EF2-B10E-BA16CCF392EA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {73B0ED2D-F2BE-4EF2-B10E-BA16CCF392EA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index 3fb560d..537457c 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -1,7 +1,7 @@  {A45F729D-8629-4C7A-96B8-29EAA8D52919} - net6.0 + net6.0 Jobber.Server Zuehlke Technology Group Jobbr.Server @@ -44,4 +44,8 @@ + + + + \ No newline at end of file From 7ff813aa9fff94a3846a6d23f527ca25aa679571 Mon Sep 17 00:00:00 2001 From: Loris <120105457+Moodiness@users.noreply.github.com> Date: Thu, 15 Dec 2022 14:25:33 +0100 Subject: [PATCH 21/41] Feature/unit testing server core (#89) add unit tests for the Jobbr.Server.Core namespace * JobRunServiceTests * JobServiceTests * TriggerServiceTests --- .../Core/JobRunServiceTests.cs | 211 ++++++++++++++ .../Core/JobServiceTests.cs | 20 +- .../Core/TriggerServiceTests.cs | 220 +++++++++++++++ .../Jobbr.Server.UnitTests.csproj | 62 ++--- .../Jobbr.Server.UnitTests.ruleset | 262 ++++++++++++++++++ .../ShouldDateTimeExtensions.cs | 33 +++ 6 files changed, 775 insertions(+), 33 deletions(-) create mode 100644 source/Jobbr.Server.UnitTests/Core/JobRunServiceTests.cs create mode 100644 source/Jobbr.Server.UnitTests/Core/TriggerServiceTests.cs create mode 100644 source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.ruleset create mode 100644 source/Jobbr.Server.UnitTests/ShouldDateTimeExtensions.cs diff --git a/source/Jobbr.Server.UnitTests/Core/JobRunServiceTests.cs b/source/Jobbr.Server.UnitTests/Core/JobRunServiceTests.cs new file mode 100644 index 0000000..be99997 --- /dev/null +++ b/source/Jobbr.Server.UnitTests/Core/JobRunServiceTests.cs @@ -0,0 +1,211 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using AutoMapper; +using Jobbr.ComponentModel.ArtefactStorage; +using Jobbr.Server.Core; +using Jobbr.Server.Core.Messaging; +using Jobbr.Server.Core.Models; +using Jobbr.Server.Storage; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Shouldly; +using TinyMessenger; + +namespace Jobbr.Server.UnitTests.Core +{ + [TestClass] + public class JobRunServiceTests + { + private readonly IJobRunService _service; + private readonly Mock _repositoryMock; + private readonly Mock _messengerHubMock; + private readonly Mock _storageProviderMock; + + public JobRunServiceTests() + { + var profiles = new List { new ModelToStorageMappingProfile(), new StorageToModelMappingProfile() }; + var config = new MapperConfiguration(cfg => cfg.AddProfiles(profiles)); + var mapper = config.CreateMapper(); + + _repositoryMock = new Mock(); + _messengerHubMock = new Mock(); + _storageProviderMock = new Mock(); + + _service = new JobRunService(NullLoggerFactory.Instance, _messengerHubMock.Object, _repositoryMock.Object, _storageProviderMock.Object, mapper); + } + + [TestMethod] + public void UpdateProgess_ShouldCallRepository() + { + // Arrange + var jobRunId = 1L; + var progress = 2D; + + // Act + _service.UpdateProgress(jobRunId, progress); + + // Assert + _repositoryMock.Verify(rep => rep.UpdateJobRunProgress(It.Is(x => x == jobRunId), It.Is(x => x == progress)), Times.Once()); + } + + [TestMethod] + public void UpdateState_Started_ShouldSetActualStartDateTimeUtc() + { + // Arrange + var state = JobRunStates.Started; + var jobRun = new ComponentModel.JobStorage.Model.JobRun(); + _repositoryMock.Setup(rep => rep.GetJobRunById(It.IsAny())).Returns(jobRun); + + // Act + _service.UpdateState(1, state); + + // Assert + jobRun.ActualStartDateTimeUtc.ShouldNotBeNull(); + jobRun.ActualStartDateTimeUtc.Value.ShouldBeUtcNowWithTolerance(); + } + + [TestMethod] + [DataRow(JobRunStates.Null)] + [DataRow(JobRunStates.Scheduled)] + [DataRow(JobRunStates.Collecting)] + [DataRow(JobRunStates.Completed)] + public void UpdateState_AllExceptStarted_ShouldNotChangeActualStartDateTimeUtc(JobRunStates state) + { + // Arrange + var actualStartDateTimeUtc = new DateTime(2022, 12, 14, 1, 0, 15); + var jobRun = new ComponentModel.JobStorage.Model.JobRun { ActualStartDateTimeUtc = actualStartDateTimeUtc }; + _repositoryMock.Setup(rep => rep.GetJobRunById(It.IsAny())).Returns(jobRun); + + // Act + _service.UpdateState(1, state); + + // Assert + jobRun.ActualStartDateTimeUtc.ShouldBe(actualStartDateTimeUtc); + } + + [TestMethod] + [DataRow(JobRunStates.Completed, true)] + [DataRow(JobRunStates.Failed, false)] + public void UpdateState_AnyEnd_ShouldCallMessengerHubPublish(JobRunStates state, bool isSuccessful) + { + // Arrange + var jobRunId = 1; + _repositoryMock.Setup(rep => rep.GetJobRunById(It.IsAny())).Returns(new ComponentModel.JobStorage.Model.JobRun()); + + // Act + _service.UpdateState(jobRunId, state); + + // Assert + _messengerHubMock.Verify(hub => hub.Publish(It.Is(message => message.Id == jobRunId && message.IsSuccessful == isSuccessful)), Times.Once()); + } + + [TestMethod] + [DataRow(JobRunStates.Completed)] + [DataRow(JobRunStates.Failed)] + public void UpdateState_AnyEndState_ShoudSetActualEndDateTimeUtc(JobRunStates state) + { + // Arrange + var jobRun = new ComponentModel.JobStorage.Model.JobRun(); + _repositoryMock.Setup(rep => rep.GetJobRunById(It.IsAny())).Returns(jobRun); + + // Act + _service.UpdateState(1, state); + + // Assert + jobRun.ActualEndDateTimeUtc.ShouldNotBeNull(); + jobRun.ActualEndDateTimeUtc.Value.ShouldBeUtcNowWithTolerance(); + } + + [TestMethod] + public void GetArtefactsByJobRunId_ShouldReturnList() + { + // Arrange + var numberOfArtefacts = 3; + var artefacts = Enumerable.Repeat(new ComponentModel.ArtefactStorage.Model.JobbrArtefact(), numberOfArtefacts).ToList(); + _storageProviderMock.Setup(provider => provider.GetArtefacts(It.IsAny())).Returns(artefacts); + + // Act + var result = _service.GetArtefactsByJobRunId(1); + + // Assert + result.ShouldNotBeNull(); + result.ShouldNotBeEmpty(); + result.Count.ShouldBe(numberOfArtefacts); + } + + [TestMethod] + public void GetArtefactsByJobRunId_WithException_ShouldReturnList() + { + // Arrange + _storageProviderMock.Setup(provider => provider.GetArtefacts(It.IsAny())).Throws(); + + // Act + var result = _service.GetArtefactsByJobRunId(1); + + // Assert + result.ShouldNotBeNull(); + result.ShouldBeEmpty(); + } + + [TestMethod] + public void GetArtefactAsStream_ShouldReturnStream() + { + // Arrange + var stream = new MemoryStream(); + _storageProviderMock.Setup(provider => provider.Load(It.IsAny(), It.IsAny())).Returns(stream); + + // Act + var result = _service.GetArtefactAsStream(1, "filename"); + + // Assert + result.ShouldNotBeNull(); + } + + [TestMethod] + public void GetArtefactAsStream_WithException_ShouldReturnNull() + { + // Arrange + _storageProviderMock.Setup(provider => provider.Load(It.IsAny(), It.IsAny())).Throws(); + + // Act + var result = _service.GetArtefactAsStream(1, "filename"); + + // Assert + result.ShouldBeNull(); + } + + + [TestMethod] + public void UpdatePid_ExistingJobRun_ShouldSetToProccessId() + { + // Arrange + var proccessId = 2; + var jobRun = new ComponentModel.JobStorage.Model.JobRun(); + _repositoryMock.Setup(rep => rep.GetJobRunById(It.IsAny())).Returns(jobRun); + + // Act + _service.UpdatePid(1, proccessId); + + // Assert + jobRun.Pid.ShouldNotBeNull(); + jobRun.Pid.ShouldBe(proccessId); + } + + [TestMethod] + public void Delete_ExistingJobRun_ShouldSetDeleted() + { + // Arrange + var jobRun = new ComponentModel.JobStorage.Model.JobRun(); + _repositoryMock.Setup(rep => rep.GetJobRunById(It.IsAny())).Returns(jobRun); + + // Act + _service.Delete(1); + + // Assert + jobRun.Deleted.ShouldBeTrue(); + } + } +} diff --git a/source/Jobbr.Server.UnitTests/Core/JobServiceTests.cs b/source/Jobbr.Server.UnitTests/Core/JobServiceTests.cs index da42f4f..431f65e 100644 --- a/source/Jobbr.Server.UnitTests/Core/JobServiceTests.cs +++ b/source/Jobbr.Server.UnitTests/Core/JobServiceTests.cs @@ -27,10 +27,10 @@ public JobServiceTests() } [TestMethod] - public void Add_ShouldAddOrUpdateModelId() + public void Add_NewJob_ShouldAddOrUpdateId() { // Arrange - JobModel model = new JobModel { Title = "Test" }; + var model = new JobModel { Title = "Test" }; var jobId = 155L; _repositoryMock.Setup(rep => rep.AddJob(It.IsAny())).Callback(job => job.Id = jobId); @@ -42,5 +42,21 @@ public void Add_ShouldAddOrUpdateModelId() result.Title.ShouldBe("Test"); result.Id.ShouldBe(jobId); } + + [TestMethod] + public void Delete_ExistingJob_ShouldSetDeleted() + { + // Arrange + var jobId = 2L; + var job = new Job { Id = jobId, Deleted = false }; + _repositoryMock.Setup(rep => rep.GetJob(It.IsAny())).Returns(job); + + // Act + _service.Delete(jobId); + + // Assert + job.Id.ShouldBe(jobId); + job.Deleted.ShouldBeTrue(); + } } } diff --git a/source/Jobbr.Server.UnitTests/Core/TriggerServiceTests.cs b/source/Jobbr.Server.UnitTests/Core/TriggerServiceTests.cs new file mode 100644 index 0000000..7f74ec5 --- /dev/null +++ b/source/Jobbr.Server.UnitTests/Core/TriggerServiceTests.cs @@ -0,0 +1,220 @@ +using AutoMapper; +using Jobbr.ComponentModel.JobStorage.Model; +using Jobbr.Server.Core; +using Jobbr.Server.Core.Messaging; +using Jobbr.Server.Core.Models; +using Jobbr.Server.Storage; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Shouldly; +using TinyMessenger; + +namespace Jobbr.Server.UnitTests.Core +{ + [TestClass] + public class TriggerServiceTests + { + private readonly ITriggerService _service; + private readonly Mock _repositoryMock; + private readonly Mock _messengerHubMock; + + public TriggerServiceTests() + { + _repositoryMock = new Mock(); + _messengerHubMock = new Mock(); + + var config = new MapperConfiguration(cfg => cfg.AddProfile()); + var mapper = config.CreateMapper(); + + _service = new TriggerService(NullLoggerFactory.Instance, _repositoryMock.Object, _messengerHubMock.Object, mapper); + } + + [TestMethod] + public void Add_RecurringTrigger_ShouldSetModelKeys() + { + // Arrange + var triggerModel = new RecurringTriggerModel { Id = 1, JobId = 2 }; + _repositoryMock + .Setup(rep => rep.SaveAddTrigger(It.IsAny(), It.IsAny())) + .Callback((id, trigger) => + { + trigger.Id = 3; + trigger.JobId = 4; + }); + + // Act + _service.Add(1, triggerModel); + + // Assert + triggerModel.Id.ShouldBe(3); + triggerModel.JobId.ShouldBe(4); + } + + [TestMethod] + public void Add_RecurringTrigger_ShouldCallMessengerHubPublish() + { + // Arrange + var model = new RecurringTriggerModel { Id = 1, JobId = 2 }; + + // Act + _service.Add(1L, model); + + // Assert + _messengerHubMock.Verify(hub => hub.PublishAsync(It.Is(message => message.TriggerId == 1 && message.JobId == 2)), Times.Once()); + } + + [TestMethod] + public void Add_ScheduledTrigger_ShouldSetModelKeys() + { + // Arrange + var triggerModel = new ScheduledTriggerModel { Id = 1, JobId = 2 }; + _repositoryMock + .Setup(rep => rep.SaveAddTrigger(It.IsAny(), It.IsAny())) + .Callback((id, trigger) => + { + trigger.Id = 3; + trigger.JobId = 4; + }); + + // Act + _service.Add(1, triggerModel); + + // Assert + triggerModel.Id.ShouldBe(3); + triggerModel.JobId.ShouldBe(4); + } + + [TestMethod] + public void Add_ScheduledTrigger_ShouldCallMessengerHubPublish() + { + // Arrange + var model = new ScheduledTriggerModel { Id = 1, JobId = 2 }; + + // Act + _service.Add(1L, model); + + // Assert + _messengerHubMock.Verify(hub => hub.PublishAsync(It.Is(message => message.TriggerId == 1 && message.JobId == 2)), Times.Once()); + } + + [TestMethod] + public void Add_InstantTrigger_ShouldSetModelKeys() + { + // Arrange + var triggerModel = new InstantTriggerModel { Id = 1, JobId = 2 }; + _repositoryMock + .Setup(rep => rep.SaveAddTrigger(It.IsAny(), It.IsAny())) + .Callback((id, trigger) => + { + trigger.Id = 3; + trigger.JobId = 4; + }); + + // Act + _service.Add(1, triggerModel); + + // Assert + triggerModel.Id.ShouldBe(3); + triggerModel.JobId.ShouldBe(4); + } + + [TestMethod] + public void Add_InstantTrigger_ShouldCallMessengerHubPublish() + { + // Arrange + var model = new InstantTriggerModel { Id = 1, JobId = 2 }; + + // Act + _service.Add(1L, model); + + // Assert + _messengerHubMock.Verify(hub => hub.PublishAsync(It.Is(message => message.TriggerId == 1 && message.JobId == 2)), Times.Once()); + } + + [TestMethod] + public void Disable_AnyTrigger_ShouldCallRepository() + { + // Arrange + var jobId = 1L; + var triggerId = 2L; + + // Act + _service.Disable(jobId, triggerId); + + // Assert + _repositoryMock.Verify(rep => rep.DisableTrigger(It.Is(x => x == jobId), It.Is(x => x == triggerId)), Times.Once()); + } + + + [TestMethod] + public void Disable_AnyTrigger_ShouldCallMessengerHubPublish() + { + // Arrange + var jobId = 1L; + var triggerId = 2L; + + // Act + _service.Disable(jobId, triggerId); + + // Assert + _messengerHubMock.Verify(hub => hub.PublishAsync(It.Is(message => message.TriggerId == triggerId && message.JobId == jobId)), Times.Once()); + } + + [TestMethod] + public void Enable_AnyTrigger_ShouldCallRepository() + { + // Arrange + var jobId = 1L; + var triggerId = 2L; + + // Act + _service.Enable(jobId, triggerId); + + // Assert + _repositoryMock.Verify(rep => rep.EnableTrigger(It.Is(x => x == jobId), It.Is(x => x == triggerId)), Times.Once()); + } + + [TestMethod] + public void Enable_AnyTrigger_ShouldCallMessengerHubPublish() + { + // Arrange + var jobId = 1L; + var triggerId = 2L; + + // Act + _service.Enable(jobId, triggerId); + + // Assert + _messengerHubMock.Verify(hub => hub.PublishAsync(It.Is(message => message.TriggerId == triggerId && message.JobId == jobId)), Times.Once()); + } + + [TestMethod] + public void Delete_AnyTrigger_ShouldCallRepository() + { + // Arrange + var jobId = 1L; + var triggerId = 2L; + + // Act + _service.Delete(jobId, triggerId); + + // Assert + _repositoryMock.Verify(rep => rep.DeleteTrigger(It.Is(x => x == jobId), It.Is(x => x == triggerId)), Times.Once()); + } + + [TestMethod] + public void Delete_AnyTrigger_ShouldCallMessengerHubPublish() + { + // Arrange + var jobId = 1L; + var triggerId = 2L; + + // Act + _service.Delete(jobId, triggerId); + + // Assert + _messengerHubMock.Verify(hub => hub.PublishAsync(It.Is(message => message.TriggerId == triggerId && message.JobId == jobId)), Times.Once()); + } + } +} diff --git a/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj b/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj index 8a097a5..2946106 100644 --- a/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj +++ b/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj @@ -1,36 +1,36 @@  - - net6.0 - Jobbr.Server.UnitTests - Zuehlke Technology Group - Copyright © Zuehlke Technology Group 2022 - Jobbr.Server.UnitTests - 1.0.0.0-pre - bin\$(Configuration)\ - ..\JobbrRuleSet.ruleset - - - full - - - full - + + net6.0 + Jobbr.Server.UnitTests + Zuehlke Technology Group + Copyright © Zuehlke Technology Group 2022 + Jobbr.Server.UnitTests + 1.0.0.0-pre + bin\$(Configuration)\ + Jobbr.Server.UnitTests.ruleset + + + full + + + full + - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + - - - + + + diff --git a/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.ruleset b/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.ruleset new file mode 100644 index 0000000..72a18b4 --- /dev/null +++ b/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.ruleset @@ -0,0 +1,262 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/source/Jobbr.Server.UnitTests/ShouldDateTimeExtensions.cs b/source/Jobbr.Server.UnitTests/ShouldDateTimeExtensions.cs new file mode 100644 index 0000000..4b110f8 --- /dev/null +++ b/source/Jobbr.Server.UnitTests/ShouldDateTimeExtensions.cs @@ -0,0 +1,33 @@ +using System; +using Shouldly; + +namespace Jobbr.Server.UnitTests +{ + public static class ShouldDateTimeExtensions + { + private static readonly TimeSpan DefaultOffsetTolerance = TimeSpan.FromSeconds(1); + + /// + /// Compare to for equality with a tolerance of one second or throw a . + /// + /// The value to check against. + /// Custom error message to display when an error occurs. + public static DateTime ShouldBeUtcNowWithTolerance(this DateTime actual, string customMessage = null) + { + return actual.ShouldBeUtcNowWithTolerance(DefaultOffsetTolerance, customMessage); + } + + /// + /// Compares the actual with for equality within the given or throw a . + /// + /// The value to check against. + /// The allowed tolerance for the equality to be checked. + /// Custom error message to display when an error occurs. + public static DateTime ShouldBeUtcNowWithTolerance(this DateTime actual, TimeSpan tolerance, string customMessage = null) + { + var offset = DateTime.UtcNow - actual; + offset.ShouldBeLessThanOrEqualTo(tolerance, customMessage); + return actual; + } + } +} From f8af8e31c07ebbca91e5c83d5a6d5464fd868120 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Thu, 15 Dec 2022 17:18:12 +0100 Subject: [PATCH 22/41] Update Microsoft.Extensions.Logging.Abstractions to 7.0.0 --- .../Jobbr.Server.IntegrationTests.csproj | 6 +++--- source/Jobbr.Server.nuspec | 2 +- source/Jobbr.Server/Jobbr.Server.csproj | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj b/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj index 0cf7af5..38c0c8e 100644 --- a/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj +++ b/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj @@ -24,9 +24,9 @@ - - - + + + diff --git a/source/Jobbr.Server.nuspec b/source/Jobbr.Server.nuspec index 5c5f95f..53f4e82 100644 --- a/source/Jobbr.Server.nuspec +++ b/source/Jobbr.Server.nuspec @@ -20,7 +20,7 @@ - + diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index 537457c..a8a9f73 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -31,7 +31,7 @@ - + @@ -45,7 +45,7 @@ - - + + \ No newline at end of file From 50d40dc38a95130cb2ed388efc4c4f6d82e1f334 Mon Sep 17 00:00:00 2001 From: Loris <120105457+Moodiness@users.noreply.github.com> Date: Fri, 16 Dec 2022 16:47:28 +0100 Subject: [PATCH 23/41] Feature/unit tests storage (#91) add some unit tests to the Jobbr.Server.Storage namespace --- .../Core/JobRunServiceTests.cs | 3 +- .../Core/TriggerServiceTests.cs | 1 - .../Storage/ExtensionMethodsTests.cs | 4 +- .../Storage/InMemoryArtefactsStorageTests.cs | 153 +++++++ .../InMemoryJobStorageProviderTests.cs | 415 ++++++++++++++++++ .../Storage/JobbrRepositoryTests.cs | 232 ++++++++++ 6 files changed, 803 insertions(+), 5 deletions(-) create mode 100644 source/Jobbr.Server.UnitTests/Storage/InMemoryArtefactsStorageTests.cs create mode 100644 source/Jobbr.Server.UnitTests/Storage/InMemoryJobStorageProviderTests.cs create mode 100644 source/Jobbr.Server.UnitTests/Storage/JobbrRepositoryTests.cs diff --git a/source/Jobbr.Server.UnitTests/Core/JobRunServiceTests.cs b/source/Jobbr.Server.UnitTests/Core/JobRunServiceTests.cs index be99997..b93836c 100644 --- a/source/Jobbr.Server.UnitTests/Core/JobRunServiceTests.cs +++ b/source/Jobbr.Server.UnitTests/Core/JobRunServiceTests.cs @@ -124,7 +124,7 @@ public void GetArtefactsByJobRunId_ShouldReturnList() { // Arrange var numberOfArtefacts = 3; - var artefacts = Enumerable.Repeat(new ComponentModel.ArtefactStorage.Model.JobbrArtefact(), numberOfArtefacts).ToList(); + var artefacts = Enumerable.Range(0, numberOfArtefacts).Select(_ => new ComponentModel.ArtefactStorage.Model.JobbrArtefact()).ToList(); _storageProviderMock.Setup(provider => provider.GetArtefacts(It.IsAny())).Returns(artefacts); // Act @@ -177,7 +177,6 @@ public void GetArtefactAsStream_WithException_ShouldReturnNull() result.ShouldBeNull(); } - [TestMethod] public void UpdatePid_ExistingJobRun_ShouldSetToProccessId() { diff --git a/source/Jobbr.Server.UnitTests/Core/TriggerServiceTests.cs b/source/Jobbr.Server.UnitTests/Core/TriggerServiceTests.cs index 7f74ec5..19c2d7d 100644 --- a/source/Jobbr.Server.UnitTests/Core/TriggerServiceTests.cs +++ b/source/Jobbr.Server.UnitTests/Core/TriggerServiceTests.cs @@ -146,7 +146,6 @@ public void Disable_AnyTrigger_ShouldCallRepository() _repositoryMock.Verify(rep => rep.DisableTrigger(It.Is(x => x == jobId), It.Is(x => x == triggerId)), Times.Once()); } - [TestMethod] public void Disable_AnyTrigger_ShouldCallMessengerHubPublish() { diff --git a/source/Jobbr.Server.UnitTests/Storage/ExtensionMethodsTests.cs b/source/Jobbr.Server.UnitTests/Storage/ExtensionMethodsTests.cs index dfc67fe..2f0fe55 100644 --- a/source/Jobbr.Server.UnitTests/Storage/ExtensionMethodsTests.cs +++ b/source/Jobbr.Server.UnitTests/Storage/ExtensionMethodsTests.cs @@ -15,7 +15,7 @@ public class ExtensionMethodsTests public void CloneNullObject_ShouldNotThrow() { // Arrange - object? data = null; + object data = null; // Act var dataClone = ExtensionMethods.Clone(data); @@ -100,7 +100,7 @@ public TestClass(string key, int value) private class TestClassValueComparer : IEqualityComparer { - public bool Equals(TestClass? x, TestClass? y) + public bool Equals(TestClass x, TestClass y) { return x is not null && y is not null && x.Value == y.Value && x.Key == y.Key; } diff --git a/source/Jobbr.Server.UnitTests/Storage/InMemoryArtefactsStorageTests.cs b/source/Jobbr.Server.UnitTests/Storage/InMemoryArtefactsStorageTests.cs new file mode 100644 index 0000000..2872463 --- /dev/null +++ b/source/Jobbr.Server.UnitTests/Storage/InMemoryArtefactsStorageTests.cs @@ -0,0 +1,153 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; +using Jobbr.ComponentModel.ArtefactStorage; +using Jobbr.Server.Storage; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Shouldly; + +namespace Jobbr.Server.UnitTests.Storage +{ + [TestClass] + public class InMemoryArtefactsStorageTests + { + private readonly IArtefactsStorageProvider _provider; + + public InMemoryArtefactsStorageTests() + { + _provider = new InMemoryArtefactsStorage(); + } + + [TestMethod] + public void Save_EmptyStream_ShouldSaveAllByteArray() + { + // Arrange + var container = "container"; + var fileName = "filename.zip"; + using var stream = new MemoryStream(); + + // Act + _provider.Save(container, fileName, stream); + + // Assert + var artefacts = _provider.GetArtefacts(container); + artefacts.Count.ShouldBe(1); + artefacts.First().FileName.ShouldBe(fileName); + } + + [TestMethod] + public void Save_Stream_ShouldSaveAllByteArray() + { + // Arrange + var container = "container"; + var fileName = "filename.zip"; + var content = "Some content placeholder"; + using var inputStream = new MemoryStream(Encoding.UTF8.GetBytes(content)); + + // Act + _provider.Save(container, fileName, inputStream); + + // Assert + using var outputStream = _provider.Load(container, fileName) as MemoryStream; + var bytes = outputStream.ToArray(); + bytes.Length.ShouldBe(content.Length); + + var outputString = Encoding.UTF8.GetString(bytes); + outputString.ShouldBe(content); + } + + [Ignore("Save() initiates that the complete stream is saved.\n" + + "However, the passed stream may have already been read up to a certain point and was not reset which may lead to unwanted behavior.")] + [TestMethod] + public void Save_StreamWithOffset_ShouldSaveAllByteArray() + { + // Arrange + var container = "container"; + var fileName = "filename.zip"; + var content = "Some content placeholder"; + using var inputStream = new MemoryStream(Encoding.UTF8.GetBytes(content)); + inputStream.Position += 5; + + // Act + _provider.Save(container, fileName, inputStream); + + // Assert + using var outputStream = _provider.Load(container, fileName) as MemoryStream; + var bytes = outputStream.ToArray(); + bytes.Length.ShouldBe(content.Length); + + var outputString = Encoding.UTF8.GetString(bytes); + outputString.ShouldBe(content); + } + + [TestMethod] + public void Save_ClosedStream_ShouldSaveAllByteArray() + { + // Arrange + using var inputStream = new MemoryStream(); + inputStream.Close(); + + // Act & Assert + Should.Throw(() => _provider.Save("container", "filename.zip", inputStream)); + } + + [TestMethod] + public void GetArtefacts_WithMultipleContainers_ShouldReturnListOfContainerArtefacts() + { + // Arrange + var container = "container"; + var fileName = "filename.zip"; + using var stream = new MemoryStream(); + _provider.Save(container, fileName, stream); + _provider.Save("another-container", "another-filename.zip", stream); + + // Act + var result = _provider.GetArtefacts(container); + + // Assert + result.ShouldNotBeNull(); + result.Count.ShouldBe(1); + result.ShouldContain(file => file.FileName == fileName); + } + + [TestMethod] + public void GetArtefacts_MissingContainer_ShouldThrow() + { + // Act & Assert + Should.Throw(() => _provider.GetArtefacts("container"), "Container not found"); + } + + [TestMethod] + public void Load_ExistingFile_ShouldReturnStream() + { + // Arrange + var container = "container"; + var fileName = "filename.zip"; + var content = "Some content placeholder"; + using var inputStream = new MemoryStream(Encoding.UTF8.GetBytes(content)); + _provider.Save(container, fileName, inputStream); + + // Act + using var result = _provider.Load(container, fileName); + + // Assert + result.ShouldBeOfType(); + var outputContent = Encoding.UTF8.GetString(((MemoryStream)result).ToArray()); + outputContent.ShouldBe(content); + } + + [TestMethod] + public void Load_MissingFile_ShouldThrow() + { + // Arrange + var container = "container"; + var fileName = "filename.zip"; + using var stream = new MemoryStream(); + _provider.Save(container, "another-filename.zip", stream); + + // Act & Assert + Should.Throw(() => _provider.Load(container, fileName), $"File {fileName} not found"); + } + } +} diff --git a/source/Jobbr.Server.UnitTests/Storage/InMemoryJobStorageProviderTests.cs b/source/Jobbr.Server.UnitTests/Storage/InMemoryJobStorageProviderTests.cs new file mode 100644 index 0000000..1a5f50c --- /dev/null +++ b/source/Jobbr.Server.UnitTests/Storage/InMemoryJobStorageProviderTests.cs @@ -0,0 +1,415 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using Jobbr.ComponentModel.JobStorage; +using Jobbr.ComponentModel.JobStorage.Model; +using Jobbr.Server.Storage; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Shouldly; + +namespace Jobbr.Server.UnitTests.Storage +{ + [TestClass] + public class InMemoryJobStorageProviderTests + { + private readonly IJobStorageProvider _provider; + + public InMemoryJobStorageProviderTests() + { + _provider = new InMemoryJobStorageProvider(); + } + + [TestMethod] + public void AddJob_ShouldSetId() + { + // Arrange + var jobs = Enumerable.Range(0, 4).Select(_ => new Job()).ToList(); + + // Act + jobs.ForEach(job => _provider.AddJob(job)); + + // Assert + jobs.ShouldAllBe(job => job.Id != 0); + jobs.Select(job => job.Id).ShouldBeUnique(); + _provider.GetJobsCount().ShouldBe(jobs.Count); + } + + [Ignore("Job.UniqueName initiates that the name must be unique. However, this is currently not enforced in any way.")] + [TestMethod] + public void AddJob_NonUniqueName_ShouldThrow() + { + // Arrange + var identifier = "my-unique-identifier"; + _provider.AddJob(new Job { UniqueName = identifier }); + var job = new Job { UniqueName = identifier }; + + // Act & Assert + Should.Throw(() => _provider.AddJob(job)); + } + + [TestMethod] + public void AddTrigger_RecurringTrigger_ShouldSetIdAndJobId() + { + // Arrange + var jobId = 1; + var trigger = new RecurringTrigger(); + + // Act + _provider.AddTrigger(jobId, trigger); + + // Assert + trigger.JobId.ShouldBe(jobId); + trigger.Id.ShouldBe(1); + } + + [TestMethod] + public void AddTrigger_InstantTrigger_ShouldSetIdAndJobId() + { + // Arrange + var jobId = 1; + var trigger = new InstantTrigger(); + + // Act + _provider.AddTrigger(jobId, trigger); + + // Assert + trigger.JobId.ShouldBe(jobId); + trigger.Id.ShouldBe(1); + } + + [TestMethod] + public void AddTrigger_ScheduledTrigger_ShouldSetIdAndJobId() + { + // Arrange + var jobId = 1; + var trigger = new ScheduledTrigger(); + + // Act + _provider.AddTrigger(jobId, trigger); + + // Assert + trigger.JobId.ShouldBe(jobId); + trigger.Id.ShouldBe(1); + } + + [TestMethod] + public void AddJobRun_ShouldSetId() + { + // Arrange + var jobRun1 = new JobRun(); + var jobRun2 = new JobRun(); + + // Act + _provider.AddJobRun(jobRun1); + _provider.AddJobRun(jobRun2); + + // Assert + jobRun1.Id.ShouldBe(1); + jobRun2.Id.ShouldBe(2); + } + + [TestMethod] + public void GetJobById_ShouldReturnClone() + { + // Arrange + var job = new Job(); + _provider.AddJob(job); + + // Act + var result = _provider.GetJobById(job.Id); + + // Assert + result.ShouldNotBeNull().ShouldNotBe(job); + } + + [TestMethod] + public void GetJobByUniqueName_ShouldReturnClone() + { + // Arrange + var identifier = "my-unique-identifier"; + var job = new Job { UniqueName = identifier }; + _provider.AddJob(job); + + // Act + var result = _provider.GetJobByUniqueName(identifier); + + // Assert + result.ShouldNotBeNull().ShouldNotBe(job); + result.UniqueName.ShouldBe(identifier); + } + + [TestMethod] + public void GetTriggerById_ShouldReturnClone() + { + // Arrange + var jobId = 1; + var searchJobId = 2; + var trigger = new RecurringTrigger(); + _provider.AddTrigger(jobId, trigger); + + // Act + var result = _provider.GetTriggerById(searchJobId, trigger.Id); + + // Assert + result.ShouldNotBeNull().ShouldNotBe(trigger); + result.ShouldBeOfType(); + result.JobId.ShouldBe(jobId); + } + + [TestMethod] + public void GetJobRunById_ShouldReturnClone() + { + // Arrange + var jobRun = new JobRun(); + _provider.AddJobRun(jobRun); + + // Act + var result = _provider.GetJobRunById(jobRun.Id); + + // Assert + result.ShouldNotBeNull().ShouldNotBe(jobRun); + } + + [TestMethod] + public void DisableTrigger_ShouldSetIsActive() + { + // Arrange + var jobId = 1; + var trigger = new RecurringTrigger { IsActive = true }; + _provider.AddTrigger(jobId, trigger); + + // Act + _provider.DisableTrigger(jobId, trigger.Id); + + // Assert + trigger.IsActive.ShouldBeFalse(); + } + + [TestMethod] + public void DisableTrigger_BadId_ShouldThrow() + { + // Arrange + var jobId = 1; + var trigger = new RecurringTrigger { IsActive = true }; + _provider.AddTrigger(jobId, trigger); + + // Act & Assert + Should.Throw(() => _provider.DisableTrigger(jobId, trigger.Id + 1)); + } + + [TestMethod] + public void EnableTrigger_ShouldSetIsActive() + { + // Arrange + var jobId = 1; + var trigger = new RecurringTrigger { IsActive = false }; + _provider.AddTrigger(jobId, trigger); + + // Act + _provider.EnableTrigger(jobId, trigger.Id); + + // Assert + trigger.IsActive.ShouldBeTrue(); + } + + [TestMethod] + public void EnableTrigger_BadId_ShouldThrow() + { + // Arrange + var jobId = 1; + var trigger = new RecurringTrigger { IsActive = false }; + _provider.AddTrigger(jobId, trigger); + + // Act & Assert + Should.Throw(() => _provider.EnableTrigger(jobId, trigger.Id + 1)); + } + + [TestMethod] + public void Update_Job_ShouldReplaceExisting() + { + // Arrange + var job = new Job(); + _provider.AddJob(job); + + var jobUpdate = new Job { Id = job.Id }; + var identifier = "my-unique-identifier"; + jobUpdate.UniqueName = identifier; + var jobCount = _provider.GetJobsCount(); + + // Act + _provider.Update(jobUpdate); + + // Assert + _provider.GetJobsCount().ShouldBe(jobCount); + job = _provider.GetJobById(job.Id); + job.UniqueName.ShouldBe(jobUpdate.UniqueName); + } + + [Ignore("The AddJob() method generates the Job.Id values.\nThe Update() method behaves like an upsert but does not generate any Job.Id values.\n" + + "Therefore, adding a Job with a custom Job.Id can cause unknown behavior.\nHowever, the Update() method neither provides a valid Job.Id nor throws an acording error")] + [TestMethod] + public void Update_NewJob_ShouldSetIdOrThrow() + { + // Arrange + var job = new Job { Id = 4 }; + + // Act + _provider.Update(job); + + // Assert + job.Id.ShouldBe(1); // or throw... + } + + [TestMethod] + public void Update_JobRun_ShouldReplaceExisting() + { + // Arrange + var jobRun = new JobRun(); + _provider.AddJobRun(jobRun); + + var jobRunUpdate = new JobRun { Id = jobRun.Id }; + var jobParameters = "{ key: 2, value: \"test\"}"; + jobRunUpdate.JobParameters = jobParameters; + + // Act + _provider.Update(jobRunUpdate); + + // Assert + jobRun = _provider.GetJobRunById(jobRun.Id); + jobRun.JobParameters.ShouldBe(jobRunUpdate.JobParameters); + } + + + [Ignore("The AddJobRun() method generates the JobRun.Id values.\nThe Update() method behaves like an upsert but does not generate any JobRun.Id values.\n" + + "Therefore, adding a JobRun with a custom JobRun.Id can cause unknown behavior.\nHowever, the Update() method neither provides a valid JobRun.Id nor throws an acording error")] + [TestMethod] + public void Update_NewJobRun_ShouldSetIdOrThrow() + { + // Arrange + var jobRun = new JobRun { Id = 4 }; + + // Act + _provider.Update(jobRun); + + // Assert + jobRun.Id.ShouldBe(1); + } + + [TestMethod] + public void UpdateProgress_ShouldSetProgress() + { + // Arrange + var jobRun = new JobRun { Progress = 1 }; + _provider.AddJobRun(jobRun); + + // Act + _provider.UpdateProgress(jobRun.Id, 2); + + // Assert + jobRun.Progress.ShouldBe(2); + } + + [TestMethod] + public void UpdateProgress_NotFound_ShouldThrow() + { + // Act & Assert + Should.Throw(() => _provider.UpdateProgress(2, 2)); + } + + [TestMethod] + public void IsAvailable_ShouldReturnTrue() + { + // Act + var result = _provider.IsAvailable(); + + // Assert + result.ShouldBeTrue(); + } + + [TestMethod] + public void GetJobsCount_ShouldReturnCount() + { + // Arrange + var jobs = Enumerable.Range(0, 4).Select(_ => new Job()).ToList(); + jobs.ForEach(job => _provider.AddJob(job)); + + _provider.Update(new Job { Id = 2 }); // Update an existing job -> count remains the same + _provider.Update(new Job { Id = 128 }); // Update a new job -> count increases + + // Act + var result = _provider.GetJobsCount(); + + // Assert + result.ShouldBe(jobs.Count + 1); + } + + [TestMethod] + public void GetJobs_DefaultSearch_ShouldReturnsPagedList() + { + // Arrange + var jobs = Enumerable.Range(0, 127).Select(_ => new Job()).ToList(); + jobs.ForEach(job => _provider.AddJob(job)); + + // Act + var result = _provider.GetJobs(); + + // Assert + result.Items.Count.ShouldBe(50); + result.TotalItems.ShouldBe(jobs.Count); + result.Items.ShouldBeSubsetOf(jobs); + } + + [TestMethod] + public void GetJobs_UniqueNameFilter_ShouldReturnsPagedList() + { + // Arrange + var jobs = Enumerable.Range(0, 127).Select(x => new Job { UniqueName = $"unique-name-{x}" }).ToList(); + jobs.ForEach(job => _provider.AddJob(job)); + + // Act + var result = _provider.GetJobs(jobUniqueNameFilter: "unique-name-4"); + + // Assert + result.Items.Count.ShouldBe(1); + result.TotalItems.ShouldBe(1); + } + + [TestMethod] + public void GetJobRunsByUserId_ShouldReturnPagedList() + { + // Arrange + var userId = "Test User"; + var jobRuns = Enumerable.Range(0, 127).Select(_ => new JobRun { Trigger = new InstantTrigger { UserId = userId } }).ToList(); + var otherJobRuns = Enumerable.Range(0, 127).Select(_ => new JobRun { Trigger = new RecurringTrigger() }).ToList(); + jobRuns.ForEach(jobRun => _provider.AddJobRun(jobRun)); + otherJobRuns.ForEach(jobRun => _provider.AddJobRun(jobRun)); + + // Act + var result = _provider.GetJobRunsByUserId(userId); + + // Assert + result.ShouldNotBeNull(); + result.Items.Count.ShouldBe(50); + result.TotalItems.ShouldBe(jobRuns.Count); + } + + [TestMethod] + public void GetJobRunsByStates_ShouldReturnPagedList() + { + // Arrange + var allStates = Enum.GetValues(); + var jobRuns = Enumerable.Range(0, 127).Select(x => new JobRun { State = allStates[x % allStates.Length] }).ToList(); + jobRuns.ForEach(jobRun => _provider.AddJobRun(jobRun)); + var states = new JobRunStates[] { JobRunStates.Initializing, JobRunStates.Preparing, JobRunStates.Connected }; + var statesCount = jobRuns.Count(jobRun => states.Contains(jobRun.State)); + + // Act + var result = _provider.GetJobRunsByStates(states); + + // Assert + result.TotalItems.ShouldBe(statesCount); + result.Items.ShouldAllBe(item => states.Contains(item.State)); + } + } +} diff --git a/source/Jobbr.Server.UnitTests/Storage/JobbrRepositoryTests.cs b/source/Jobbr.Server.UnitTests/Storage/JobbrRepositoryTests.cs new file mode 100644 index 0000000..3a61144 --- /dev/null +++ b/source/Jobbr.Server.UnitTests/Storage/JobbrRepositoryTests.cs @@ -0,0 +1,232 @@ +using System; +using System.Linq; +using Jobbr.ComponentModel.JobStorage; +using Jobbr.ComponentModel.JobStorage.Model; +using Jobbr.Server.Storage; +using Microsoft.Extensions.Logging.Abstractions; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Shouldly; + +namespace Jobbr.Server.UnitTests.Storage +{ + [TestClass] + public class JobbrRepositoryTests + { + private readonly IJobbrRepository _repository; + private readonly Mock _storageProviderMock; + + public JobbrRepositoryTests() + { + _storageProviderMock = new Mock(); + + _repository = new JobbrRepository(NullLoggerFactory.Instance, _storageProviderMock.Object); + } + + [TestMethod] + public void SetPidForJobRun_ShouldSetAndPropagate() + { + // Arrange + var id = 1; + var job = new JobRun { Id = id }; + + // Act + _repository.SetPidForJobRun(job, id); + + // Assert + job.Pid.ShouldBe(id); + _storageProviderMock.Verify(provider => provider.Update(It.Is(x => x.Id == id && x.Pid == id)), Times.Once()); + } + + [TestMethod] + public void UpdatePlannedStartDateTimeUtc_ShouldSetPlannedStartDateTimeUtc() + { + // Arrange + var plannedStartDateTimeUtc = new DateTime(2022, 12, 14, 13, 59, 22); + var jobRun = new JobRun(); + _storageProviderMock.Setup(provider => provider.GetJobRunById(It.IsAny())).Returns(jobRun); + + // Act + _repository.UpdatePlannedStartDateTimeUtc(1, plannedStartDateTimeUtc); + + // Assert + jobRun.PlannedStartDateTimeUtc.ShouldBe(plannedStartDateTimeUtc); + } + + [TestMethod] + public void SaveUpdateTrigger_InstantTrigger_ShouldSetValuesAndPropagate() + { + // Arrange + var createdDateTimeUtc = new DateTime(2022, 12, 14, 14, 17, 0, DateTimeKind.Utc); + var trigger = new InstantTrigger { IsActive = false, CreatedDateTimeUtc = createdDateTimeUtc }; + var triggerUpdate = new InstantTrigger { IsActive = true, CreatedDateTimeUtc = createdDateTimeUtc.AddDays(1) }; + + SetupStorageProviderGetTriggerById(trigger); + + // Act + _repository.SaveUpdateTrigger(1, triggerUpdate, out var hasChanges); + + // Assert + hasChanges.ShouldBeTrue(); + triggerUpdate.CreatedDateTimeUtc.ShouldBe(createdDateTimeUtc); + _storageProviderMock.Verify(provider => provider.Update(It.IsAny(), It.IsAny()), Times.Once()); + } + + [TestMethod] + public void SaveUpdateTrigger_InstantTriggerNoChanges_ShouldNotSetValuesAndPropagate() + { + // Arrange + var createdDateTimeUtc = new DateTime(2022, 12, 14, 14, 17, 0, DateTimeKind.Utc); + var trigger = new InstantTrigger { CreatedDateTimeUtc = createdDateTimeUtc.AddHours(-1) }; + var triggerUpdate = new InstantTrigger { CreatedDateTimeUtc = createdDateTimeUtc }; + + SetupStorageProviderGetTriggerById(trigger); + + // Act + var result = _repository.SaveUpdateTrigger(1, triggerUpdate, out var hasChanges); + + // Assert + hasChanges.ShouldBeFalse(); + result.ShouldBe(trigger); + + _storageProviderMock.Verify(provider => provider.Update(It.IsAny(), It.IsAny()), Times.Never()); + + // TODO: Check if it is intendet to reverse the CreatedDateTimeUtc update? + triggerUpdate.CreatedDateTimeUtc.ShouldBe(createdDateTimeUtc); + } + + [TestMethod] + public void SaveUpdateTrigger_ScheduledTriggerOtherChanges_ShouldSetValuesAndPropagate() + { + // Assert + var startDateTimeUtc = new DateTime(2022, 12, 14, 14, 17, 0, DateTimeKind.Utc); + var startDateTimeUtcUpdate = startDateTimeUtc.AddHours(4); + + var trigger = new ScheduledTrigger { StartDateTimeUtc = startDateTimeUtc }; + var triggerUpdate = new ScheduledTrigger { StartDateTimeUtc = startDateTimeUtcUpdate }; + + SetupStorageProviderGetTriggerById(trigger); + + // Act + var result = _repository.SaveUpdateTrigger(1, triggerUpdate, out var hasChanges); + + // Assert + hasChanges.ShouldBeTrue(); + result.ShouldBe(trigger); + + trigger.StartDateTimeUtc.ShouldBe(startDateTimeUtcUpdate); + triggerUpdate.StartDateTimeUtc.ShouldBe(startDateTimeUtcUpdate); + + _storageProviderMock.Verify(provider => provider.Update(It.IsAny(), It.IsAny()), Times.Once()); + } + + [TestMethod] + public void SaveUpdateTrigger_ScheduledTriggerBaseChanges_ShouldSetValuesAndPropagate() + { + // Assert + var comment = "Scheduled trigger base changes"; + var commentUpdate = $"{comment} (update)"; + + var trigger = new ScheduledTrigger { Comment = comment }; + var triggerUpdate = new ScheduledTrigger { Comment = commentUpdate }; + + SetupStorageProviderGetTriggerById(trigger); + + // Act + var result = _repository.SaveUpdateTrigger(1, triggerUpdate, out var hasChanges); + + // Assert + hasChanges.ShouldBeTrue(); + result.ShouldBe(trigger); + _storageProviderMock.Verify(provider => provider.Update(It.IsAny(), It.IsAny()), Times.Once()); + } + + [TestMethod] + public void SaveUpdateTrigger_InstantTriggerBaseChanges_ShouldNotUpdateBaseValues() + { + // Assert + var comment = "Scheduled trigger base changes"; + var commentUpdate = $"{comment} (update)"; + + var trigger = new InstantTrigger { Comment = comment }; + var triggerUpdate = new InstantTrigger { Comment = commentUpdate }; + + SetupStorageProviderGetTriggerById(trigger); + + // Act + var result = _repository.SaveUpdateTrigger(1, triggerUpdate, out var hasChanges); + + // Assert + hasChanges.ShouldBeFalse(); + result.ShouldBe(trigger); + trigger.Comment.ShouldBe(comment); + _storageProviderMock.Verify(provider => provider.Update(It.IsAny(), It.IsAny()), Times.Never()); + } + + [TestMethod] + public void SaveNewJobRun_ShouldReturnNewInstance() + { + // Arrange + var job = new Job { Parameters = "{ key: 1, value: \"job-1\" }" }; + var trigger = new JobTriggerBase(); + var plannedStartDateTimeUtc = new DateTime(2022, 12, 14, 14, 59, 0, DateTimeKind.Utc); + + // Act + var result = _repository.SaveNewJobRun(job, trigger, plannedStartDateTimeUtc); + + // Assert + result.ShouldNotBeNull(); + result.JobParameters.ShouldBe(job.Parameters); + result.PlannedStartDateTimeUtc.ShouldBe(plannedStartDateTimeUtc); + + _storageProviderMock.Verify(provider => provider.AddJobRun(It.Is(x => x == result)), Times.Once()); + } + + [TestMethod] + public void SaveNewJobRun_MissingReference_ShouldThrow() + { + // Arrange + var job = new Job(); + var trigger = new JobTriggerBase(); + var plannedStartDateTimeUtc = new DateTime(2022, 12, 14, 15, 3, 0, DateTimeKind.Utc); + + // Act & Assert + Should.Throw(() => _repository.SaveNewJobRun(null, trigger, plannedStartDateTimeUtc)); + Should.Throw(() => _repository.SaveNewJobRun(job, null, plannedStartDateTimeUtc)); + } + + [TestMethod] + public void Delete_ExistingJobRun_ShouldSetDeleteState() + { + // Arrange + var jobRun = new JobRun { State = JobRunStates.Processing }; + var jobRunDelete = new JobRun { State = JobRunStates.Processing }; + + _storageProviderMock.Setup(provider => provider.GetJobRunById(It.IsAny())).Returns(jobRun); + + // Act + _repository.Delete(jobRun); + + // Assert + jobRun.State.ShouldBe(JobRunStates.Deleted); + jobRunDelete.State.ShouldBe(JobRunStates.Processing); + _storageProviderMock.Verify(provider => provider.Update(It.Is(x => x == jobRun)), Times.Once()); + } + + [TestMethod] + public void GetJobRunsByStateRange_InvalidMinMaxStateParams_ShouldThrow() + { + // Arrange + JobRunStates minState = JobRunStates.Completed, maxState = JobRunStates.Starting; + + // Act && Assert + Should.Throw(() => _repository.GetJobRunsByStateRange(minState, maxState).ToList()); + } + + private void SetupStorageProviderGetTriggerById(T trigger) + where T : JobTriggerBase + { + _storageProviderMock.Setup(provider => provider.GetTriggerById(It.IsAny(), It.IsAny())).Returns(trigger); + } + } +} From e306b4f41c74525529f3fe39bac3aa6051b77730 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Fri, 30 Dec 2022 15:08:45 +0100 Subject: [PATCH 24/41] Configure the shared Stylecop ruleset from devtools --- .../Jobbr.Server.IntegrationTests.csproj | 7 ++++++- .../Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj | 8 ++++++-- source/Jobbr.Server/Jobbr.Server.csproj | 8 ++++---- source/submodules/devsupport | 2 +- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj b/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj index 38c0c8e..274eddd 100644 --- a/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj +++ b/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj @@ -13,13 +13,15 @@ Copyright © Zuehlke Technology Group 2015 1.0.0.0-pre bin\$(Configuration)\ + true full - ..\JobbrRuleSet.ruleset + 1701;1702;1591;SA1600 pdbonly + 1701;1702;1591;SA1600 @@ -58,4 +60,7 @@ + + + \ No newline at end of file diff --git a/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj b/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj index 2946106..1b72668 100644 --- a/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj +++ b/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj @@ -7,13 +7,15 @@ Jobbr.Server.UnitTests 1.0.0.0-pre bin\$(Configuration)\ - Jobbr.Server.UnitTests.ruleset + true full + 1701;1702;1591;SA1600 full + 1701;1702;1591;SA1600 @@ -32,5 +34,7 @@ - + + + diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index a8a9f73..ea6a7e6 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -9,8 +9,8 @@ GPL-3.0-only images\icon.png https://github.com/jobbrIO/jobbr-server - ..\JobbrRuleSet.ruleset bin\$(Configuration)\ + true full @@ -34,9 +34,6 @@ - - all - @@ -48,4 +45,7 @@ + + + \ No newline at end of file diff --git a/source/submodules/devsupport b/source/submodules/devsupport index 643d004..3ce9da3 160000 --- a/source/submodules/devsupport +++ b/source/submodules/devsupport @@ -1 +1 @@ -Subproject commit 643d004936c5df825592233971320a702dae6daf +Subproject commit 3ce9da3c883806c720117d2372ce9d3b678bc71a From af05e8629f5c23dccbbc75b3a80cf0df90de5f31 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Tue, 3 Jan 2023 16:04:37 +0100 Subject: [PATCH 25/41] Apply most StyleCop suggestions --- .../JobRunService/ProgressChannelTests.cs | 42 +-- .../Scheduler/ManualTimeProvider.cs | 10 +- .../Components/Scheduler/PeriodicTimerMock.cs | 4 +- .../Components/Scheduler/PlanningTests.cs | 284 ++++++++++-------- .../Components/Scheduler/SchedulerTests.cs | 126 ++++---- .../Components/Scheduler/TestBase.cs | 20 +- .../FaultyJobStorageProvider.cs | 130 ++++---- .../Execution/JobRunExecutionTestBase.cs | 8 +- .../JobRunInformationServiceTests.cs | 17 +- .../Execution/ProgressChannelTests.cs | 71 +++-- .../Integration/ExposeAllServicesComponent.cs | 5 +- .../Integration/JobRunEnumMappingTests.cs | 41 +-- .../Integration/JobbrServerTestBase.cs | 10 +- .../Management/JobManagementTests.cs | 40 +-- .../Management/JobQueryServiceTests.cs | 187 ++++++------ .../Integration/Scheduler/SchedulerTests.cs | 16 +- .../Startup/ConfigurationValidationTests.cs | 24 +- .../Startup/SetupValidationTests.cs | 9 +- .../Jobbr.Server.IntegrationTests.csproj | 4 - .../PackagingTests.cs | 2 +- .../Registration/BuilderTests.cs | 24 +- .../Registration/TriggerExtensionsTests.cs | 16 +- .../Jobbr.Server.UnitTests.csproj | 4 - .../InMemoryJobStorageProviderTests.cs | 3 +- .../Execution/MappingProfile.cs | 6 +- .../Management/JobManagementService.cs | 1 - .../Management/JobQueryService.cs | 72 ++--- source/Jobbr.Server/Core/ITriggerService.cs | 2 +- source/Jobbr.Server/Core/JobRunService.cs | 7 +- .../Core/Messaging/TriggerAddedMessage.cs | 4 +- .../Messaging/TriggerStateChangedMessage.cs | 4 +- .../Core/Messaging/TriggerUpdatedMessage.cs | 4 +- .../Jobbr.Server/Core/Models/JobRunStates.cs | 2 +- .../Models/ModelToStorageMappingProfile.cs | 8 +- .../Models/StorageToModelMappingProfile.cs | 2 +- source/Jobbr.Server/Core/TriggerService.cs | 2 +- .../JobRegistry/IRegistryBuilder.cs | 2 +- .../Jobbr.Server/JobRegistry/JobDefinition.cs | 2 +- .../JobRegistry/RegistryBuilder.cs | 2 +- .../JobRegistry/TriggerExtensions.cs | 6 +- source/Jobbr.Server/Jobbr.Server.csproj | 1 + .../Scheduling/DefaultScheduler.cs | 5 +- .../Scheduling/FixedMinuteTimer.cs | 16 +- .../Scheduling/MaxConcurrentJobRunPlaner.cs | 2 +- .../Storage/InMemoryArtefactsStorage.cs | 14 +- .../Storage/InMemoryJobStorageProvider.cs | 152 +++++----- source/submodules/devsupport | 2 +- 47 files changed, 726 insertions(+), 689 deletions(-) diff --git a/source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressChannelTests.cs b/source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressChannelTests.cs index 4663ae3..9bd89e9 100644 --- a/source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressChannelTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressChannelTests.cs @@ -20,18 +20,18 @@ public class ProgressUpdateTests public ProgressUpdateTests() { var autoMapperConfig = new AutoMapperConfigurationFactory(new NullLoggerFactory()).GetNew(); - - this.repo = new JobbrRepository(new NullLoggerFactory(), new InMemoryJobStorageProvider()); - this.messengerHub = new TinyMessengerHub(); + repo = new JobbrRepository(new NullLoggerFactory(), new InMemoryJobStorageProvider()); - this.service = new Server.Core.JobRunService(new NullLoggerFactory(), this.messengerHub, this.repo, null, autoMapperConfig.CreateMapper()); + messengerHub = new TinyMessengerHub(); + + service = new Server.Core.JobRunService(new NullLoggerFactory(), messengerHub, repo, null, autoMapperConfig.CreateMapper()); } private JobRun GivenAJobRun() { var job1 = new Job(); - this.repo.AddJob(job1); + repo.AddJob(job1); var trigger = new InstantTrigger { @@ -39,18 +39,18 @@ private JobRun GivenAJobRun() IsActive = true }; - var jobrun = this.repo.SaveNewJobRun(job1, trigger, DateTime.UtcNow); + var jobrun = repo.SaveNewJobRun(job1, trigger, DateTime.UtcNow); return jobrun; } [TestMethod] public void JobRun_HasStarted_StartDateTimeIsStored() { - var jobrun = this.GivenAJobRun(); + var jobrun = GivenAJobRun(); - this.service.UpdateState(jobrun.Id, JobRunStates.Started); + service.UpdateState(jobrun.Id, JobRunStates.Started); - var fromRepo = this.repo.GetJobRunById(jobrun.Id); + var fromRepo = repo.GetJobRunById(jobrun.Id); Assert.IsNotNull(fromRepo.ActualStartDateTimeUtc); } @@ -58,10 +58,10 @@ public void JobRun_HasStarted_StartDateTimeIsStored() [TestMethod] public void JobRun_HasCompleted_EndDateTimeIsStored() { - var jobrun = this.GivenAJobRun(); + var jobrun = GivenAJobRun(); - this.service.UpdateState(jobrun.Id, JobRunStates.Completed); - var fromRepo = this.repo.GetJobRunById(jobrun.Id); + service.UpdateState(jobrun.Id, JobRunStates.Completed); + var fromRepo = repo.GetJobRunById(jobrun.Id); Assert.IsNotNull(fromRepo.ActualEndDateTimeUtc); } @@ -69,10 +69,10 @@ public void JobRun_HasCompleted_EndDateTimeIsStored() [TestMethod] public void JobRun_HasFailed_EndDateTimeIsStored() { - var jobrun = this.GivenAJobRun(); + var jobrun = GivenAJobRun(); - this.service.UpdateState(jobrun.Id, JobRunStates.Failed); - var fromRepo = this.repo.GetJobRunById(jobrun.Id); + service.UpdateState(jobrun.Id, JobRunStates.Failed); + var fromRepo = repo.GetJobRunById(jobrun.Id); Assert.IsNotNull(fromRepo.ActualEndDateTimeUtc); } @@ -80,13 +80,13 @@ public void JobRun_HasFailed_EndDateTimeIsStored() [TestMethod] public void JobRun_HasCompleted_MessageIsIssued() { - var jobrun = this.GivenAJobRun(); + var jobrun = GivenAJobRun(); JobRunCompletedMessage message = null; // Register for message - this.messengerHub.Subscribe(m => message = m); + messengerHub.Subscribe(m => message = m); - this.service.UpdateState(jobrun.Id, JobRunStates.Completed); + service.UpdateState(jobrun.Id, JobRunStates.Completed); Assert.IsNotNull(message); } @@ -94,13 +94,13 @@ public void JobRun_HasCompleted_MessageIsIssued() [TestMethod] public void JobRun_HasFailed_MessageIsIssued() { - var jobrun = this.GivenAJobRun(); + var jobrun = GivenAJobRun(); JobRunCompletedMessage message = null; // Register for message - this.messengerHub.Subscribe(m => message = m); + messengerHub.Subscribe(m => message = m); - this.service.UpdateState(jobrun.Id, JobRunStates.Failed); + service.UpdateState(jobrun.Id, JobRunStates.Failed); Assert.IsNotNull(message); } diff --git a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/ManualTimeProvider.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/ManualTimeProvider.cs index 3edd157..cd0601a 100644 --- a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/ManualTimeProvider.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/ManualTimeProvider.cs @@ -9,27 +9,27 @@ public class ManualTimeProvider : IDateTimeProvider public ManualTimeProvider() { - this.currentTime = DateTime.UtcNow; + currentTime = DateTime.UtcNow; } public DateTime GetUtcNow() { - return this.currentTime; + return currentTime; } public void AddMinute() { - this.currentTime = this.currentTime.AddMinutes(1); + currentTime = currentTime.AddMinutes(1); } public void AddSecond() { - this.currentTime = this.currentTime.AddSeconds(1); + currentTime = currentTime.AddSeconds(1); } public void Set(DateTime dateTimeUtc) { - this.currentTime = dateTimeUtc; + currentTime = dateTimeUtc; } } } \ No newline at end of file diff --git a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PeriodicTimerMock.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PeriodicTimerMock.cs index d3728fc..c8ecc6a 100644 --- a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PeriodicTimerMock.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PeriodicTimerMock.cs @@ -9,7 +9,7 @@ public class PeriodicTimerMock : IPeriodicTimer public void Setup(Action value) { - this.callback = value; + callback = value; } public void Start() @@ -22,7 +22,7 @@ public void Stop() public void CallbackOnce() { - this.callback(); + callback(); } } } \ No newline at end of file diff --git a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PlanningTests.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PlanningTests.cs index 44106d3..149b99a 100644 --- a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PlanningTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PlanningTests.cs @@ -11,52 +11,52 @@ public class PlanningTests : TestBase { public PlanningTests() { - this.scheduler.Start(); + scheduler.Start(); } private void AddAndSignalNewTrigger(long jobId, InstantTrigger trigger) { - this.repository.SaveAddTrigger(jobId, trigger); - this.scheduler.OnTriggerAdded(jobId, trigger.Id); + repository.SaveAddTrigger(jobId, trigger); + scheduler.OnTriggerAdded(jobId, trigger.Id); } private void AddAndSignalNewTrigger(long jobId, ScheduledTrigger trigger) { - this.repository.SaveAddTrigger(jobId, trigger); - this.scheduler.OnTriggerAdded(jobId, trigger.Id); + repository.SaveAddTrigger(jobId, trigger); + scheduler.OnTriggerAdded(jobId, trigger.Id); } private void AddAndSignalNewTrigger(long jobId, RecurringTrigger trigger) { - this.repository.SaveAddTrigger(jobId, trigger); - this.scheduler.OnTriggerAdded(jobId, trigger.Id); + repository.SaveAddTrigger(jobId, trigger); + scheduler.OnTriggerAdded(jobId, trigger.Id); } [TestMethod] public void NewScheduledTrigger_IsAdded_WillBePlanned() { - var scheduledTrigger = new ScheduledTrigger { JobId = this.demoJob1Id, StartDateTimeUtc = DateTime.UtcNow.AddSeconds(-1), IsActive = true }; - this.AddAndSignalNewTrigger(this.demoJob1Id, scheduledTrigger); + var scheduledTrigger = new ScheduledTrigger { JobId = demoJob1Id, StartDateTimeUtc = DateTime.UtcNow.AddSeconds(-1), IsActive = true }; + AddAndSignalNewTrigger(demoJob1Id, scheduledTrigger); - Assert.AreEqual(1, this.lastIssuedPlan.Count, "A scheduled trigger should cause one item in the plan"); + Assert.AreEqual(1, lastIssuedPlan.Count, "A scheduled trigger should cause one item in the plan"); } [TestMethod] public void NewInstantTrigger_IsAdded_WillBePlanned() { - var scheduledTrigger = new InstantTrigger() { JobId = this.demoJob1Id, IsActive = true }; - this.AddAndSignalNewTrigger(this.demoJob1Id, scheduledTrigger); + var scheduledTrigger = new InstantTrigger() { JobId = demoJob1Id, IsActive = true }; + AddAndSignalNewTrigger(demoJob1Id, scheduledTrigger); - Assert.AreEqual(1, this.lastIssuedPlan.Count, "A instant trigger should cause one item in the plan"); + Assert.AreEqual(1, lastIssuedPlan.Count, "A instant trigger should cause one item in the plan"); } [TestMethod] public void NewScheduledTrigger_IsAdded_CreatesANewJobRun() { - var scheduledTrigger = new ScheduledTrigger { JobId = this.demoJob1Id, StartDateTimeUtc = DateTime.UtcNow.AddSeconds(-1), IsActive = true }; - this.AddAndSignalNewTrigger(this.demoJob1Id, scheduledTrigger); + var scheduledTrigger = new ScheduledTrigger { JobId = demoJob1Id, StartDateTimeUtc = DateTime.UtcNow.AddSeconds(-1), IsActive = true }; + AddAndSignalNewTrigger(demoJob1Id, scheduledTrigger); - var jobRuns = this.repository.GetJobRuns(); + var jobRuns = repository.GetJobRuns(); Assert.AreEqual(1, jobRuns.Items.Count, "A scheduled trigger should create exact one jobrun when added"); Assert.AreEqual(scheduledTrigger.Id, jobRuns.Items.Single().Trigger.Id, "The jobrun should reference the trigger that cause the job to run"); @@ -67,13 +67,13 @@ public void NewScheduledTrigger_IsAdded_IsPlannedOnTime() { var dateTimeUtc = DateTime.UtcNow.AddHours(10); - var scheduledTrigger = new ScheduledTrigger { JobId = this.demoJob1Id, StartDateTimeUtc = dateTimeUtc, IsActive = true }; - this.AddAndSignalNewTrigger(this.demoJob1Id, scheduledTrigger); + var scheduledTrigger = new ScheduledTrigger { JobId = demoJob1Id, StartDateTimeUtc = dateTimeUtc, IsActive = true }; + AddAndSignalNewTrigger(demoJob1Id, scheduledTrigger); - var jobRun = this.repository.GetJobRuns().Items.Single(); + var jobRun = repository.GetJobRuns().Items.Single(); - Assert.AreEqual(dateTimeUtc, this.lastIssuedPlan.Single().PlannedStartDateTimeUtc, "The startdate should be considered in the plan"); - Assert.AreEqual(jobRun.Id, this.lastIssuedPlan.Single().Id, "The startdate should be considered in the plan"); + Assert.AreEqual(dateTimeUtc, lastIssuedPlan.Single().PlannedStartDateTimeUtc, "The startdate should be considered in the plan"); + Assert.AreEqual(jobRun.Id, lastIssuedPlan.Single().Id, "The startdate should be considered in the plan"); } [TestMethod] @@ -81,14 +81,14 @@ public void NewRecurringTriggerWithoutSeconds_IsAdded_IsPlannedOnTime() { var dateTimeUtc = new DateTime(DateTime.UtcNow.Year + 1, 09, 02, 17, 00, 00); - var scheduledTrigger = new RecurringTrigger() { Definition = "* * * * *", JobId = this.demoJob1Id, StartDateTimeUtc = dateTimeUtc, IsActive = true }; - this.AddAndSignalNewTrigger(this.demoJob1Id, scheduledTrigger); + var scheduledTrigger = new RecurringTrigger() { Definition = "* * * * *", JobId = demoJob1Id, StartDateTimeUtc = dateTimeUtc, IsActive = true }; + AddAndSignalNewTrigger(demoJob1Id, scheduledTrigger); - var jobRun = this.repository.GetJobRuns().Items.Single(); + var jobRun = repository.GetJobRuns().Items.Single(); var expectedTime = dateTimeUtc.AddMinutes(1); - Assert.AreEqual(expectedTime, this.lastIssuedPlan.Single().PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); - Assert.AreEqual(jobRun.Id, this.lastIssuedPlan.Single().Id, "The startdate should be considered in the plan"); + Assert.AreEqual(expectedTime, lastIssuedPlan.Single().PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); + Assert.AreEqual(jobRun.Id, lastIssuedPlan.Single().Id, "The startdate should be considered in the plan"); } [TestMethod] @@ -96,14 +96,14 @@ public void NewRecurringTriggerWithSeconds_IsAdded_DoesNotContainsSecondInTrigge { var dateTimeUtc = new DateTime(DateTime.UtcNow.Year + 1, 02, 09, 17, 00, 15); - var scheduledTrigger = new RecurringTrigger() { Definition = "* * * * *", StartDateTimeUtc = dateTimeUtc, JobId = this.demoJob1Id, IsActive = true }; - this.AddAndSignalNewTrigger(this.demoJob1Id, scheduledTrigger); + var scheduledTrigger = new RecurringTrigger() { Definition = "* * * * *", StartDateTimeUtc = dateTimeUtc, JobId = demoJob1Id, IsActive = true }; + AddAndSignalNewTrigger(demoJob1Id, scheduledTrigger); - var jobRun = this.repository.GetJobRuns().Items.Single(); + var jobRun = repository.GetJobRuns().Items.Single(); var expectedTime = dateTimeUtc.AddMinutes(1).AddSeconds(-15); - Assert.AreEqual(expectedTime, this.lastIssuedPlan.Single().PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); - Assert.AreEqual(jobRun.Id, this.lastIssuedPlan.Single().Id, "The startdate should be considered in the plan"); + Assert.AreEqual(expectedTime, lastIssuedPlan.Single().PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); + Assert.AreEqual(jobRun.Id, lastIssuedPlan.Single().Id, "The startdate should be considered in the plan"); } [TestMethod] @@ -111,18 +111,24 @@ public void RecurringTrigger_AfterTwoMinutes_IsPlannedMultipleTimes() { var dateTimeUtc = new DateTime(2017, 02, 09, 14, 00, 00); - this.currentTimeProvider.Set(dateTimeUtc); + currentTimeProvider.Set(dateTimeUtc); - var scheduledTrigger = new RecurringTrigger() { Definition = "* * * * *", JobId = this.demoJob1Id, StartDateTimeUtc = dateTimeUtc, IsActive = true }; - this.AddAndSignalNewTrigger(this.demoJob1Id, scheduledTrigger); + var scheduledTrigger = new RecurringTrigger + { + Definition = "* * * * *", + JobId = demoJob1Id, + StartDateTimeUtc = dateTimeUtc, + IsActive = true + }; + AddAndSignalNewTrigger(demoJob1Id, scheduledTrigger); - this.currentTimeProvider.AddMinute(); - this.periodicTimer.CallbackOnce(); + currentTimeProvider.AddMinute(); + periodicTimer.CallbackOnce(); - this.currentTimeProvider.AddMinute(); - this.periodicTimer.CallbackOnce(); + currentTimeProvider.AddMinute(); + periodicTimer.CallbackOnce(); - var jobRuns = this.repository.GetJobRuns(); + var jobRuns = repository.GetJobRuns(); var expectedTime1 = dateTimeUtc.AddMinutes(1); var expectedTime2 = dateTimeUtc.AddMinutes(2); @@ -130,136 +136,154 @@ public void RecurringTrigger_AfterTwoMinutes_IsPlannedMultipleTimes() Assert.AreEqual(3, jobRuns.Items.Count); - Assert.AreEqual(expectedTime1, this.lastIssuedPlan[0].PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); - Assert.AreEqual(expectedTime2, this.lastIssuedPlan[1].PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); - Assert.AreEqual(expectedTime3, this.lastIssuedPlan[2].PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); + Assert.AreEqual(expectedTime1, lastIssuedPlan[0].PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); + Assert.AreEqual(expectedTime2, lastIssuedPlan[1].PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); + Assert.AreEqual(expectedTime3, lastIssuedPlan[2].PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); } [TestMethod] public void ScheduledTrigger_HasCompletedJobRun_DoesNotTriggerNewOne() { // Note: The Scheduled Trigger needs to be in the past in order to invalidate the job reliable in this testing scenario (Issues with NCrunch, no issues with R# and VS-Runners) - var scheduledTrigger = new ScheduledTrigger { JobId = this.demoJob1Id, StartDateTimeUtc = DateTime.UtcNow.AddSeconds(-1), IsActive = true }; - this.AddAndSignalNewTrigger(this.demoJob1Id, scheduledTrigger); + var scheduledTrigger = new ScheduledTrigger + { + JobId = demoJob1Id, + StartDateTimeUtc = DateTime.UtcNow.AddSeconds(-1), + IsActive = true + }; + AddAndSignalNewTrigger(demoJob1Id, scheduledTrigger); // Simulate Job Completeness - var jobRunByScheduledTrigger = this.repository.GetJobRuns().Items.Single(jr => jr.Trigger.Id == scheduledTrigger.Id); + var jobRunByScheduledTrigger = repository.GetJobRuns().Items.Single(jr => jr.Trigger.Id == scheduledTrigger.Id); jobRunByScheduledTrigger.State = JobRunStates.Completed; - this.repository.Update(jobRunByScheduledTrigger); + repository.Update(jobRunByScheduledTrigger); - this.scheduler.OnJobRunEnded(jobRunByScheduledTrigger.Id); - - Assert.AreEqual(0, this.lastIssuedPlan.Count, "A scheduled trigger should not cause any additional jobruns after completion"); + scheduler.OnJobRunEnded(jobRunByScheduledTrigger.Id); + + Assert.AreEqual(0, lastIssuedPlan.Count, "A scheduled trigger should not cause any additional jobruns after completion"); } [TestMethod] public void RecurringTrigger_HasCompletedJobRun_TriggerNewOne() { - var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = this.demoJob1Id, IsActive = true, NoParallelExecution = false, StartDateTimeUtc = DateTime.UtcNow }; - this.AddAndSignalNewTrigger(this.demoJob1Id, recurringTrigger); + var recurringTrigger = new RecurringTrigger + { + Definition = "* * * * *", + JobId = demoJob1Id, + IsActive = true, + NoParallelExecution = false, + StartDateTimeUtc = DateTime.UtcNow + }; + AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); // Simulate Job Completeness - var jobRunByScheduledTrigger = this.repository.GetJobRuns().Items.Single(jr => jr.Trigger.Id == recurringTrigger.Id); + var jobRunByScheduledTrigger = repository.GetJobRuns().Items.Single(jr => jr.Trigger.Id == recurringTrigger.Id); jobRunByScheduledTrigger.State = JobRunStates.Completed; - this.repository.Update(jobRunByScheduledTrigger); + repository.Update(jobRunByScheduledTrigger); - this.scheduler.OnJobRunEnded(jobRunByScheduledTrigger.Id); + scheduler.OnJobRunEnded(jobRunByScheduledTrigger.Id); - var jobRun = this.repository.GetJobRuns(); + var jobRun = repository.GetJobRuns(); Assert.AreEqual(2, jobRun.Items.Count, "Trigger should have triggered an additional job after completion of the first"); - Assert.AreEqual(1, this.lastIssuedPlan.Count, "A scheduled trigger should not cause any additional jobruns after completion"); + Assert.AreEqual(1, lastIssuedPlan.Count, "A scheduled trigger should not cause any additional jobruns after completion"); } [TestMethod] public void RecurringTrigger_WithNoTriggerOrJobChanges_DoesTriggerNewOnes() { var initialDate = new DateTime(2017, 02, 01, 15, 42, 12, DateTimeKind.Utc); - this.currentTimeProvider.Set(initialDate); + currentTimeProvider.Set(initialDate); - var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = this.demoJob1Id, IsActive = true, NoParallelExecution = false}; - - // This triggers the first jobrun - this.AddAndSignalNewTrigger(this.demoJob1Id, recurringTrigger); + var recurringTrigger = new RecurringTrigger + { + Definition = "* * * * *", + JobId = demoJob1Id, + IsActive = true, + NoParallelExecution = false + }; - // wait for additional jobrun - this.currentTimeProvider.Set(initialDate.AddHours(2)); - this.periodicTimer.CallbackOnce(); + // This triggers the first job run + AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); - var jobRun = this.repository.GetJobRuns(); + // wait for additional job run + currentTimeProvider.Set(initialDate.AddHours(2)); + periodicTimer.CallbackOnce(); + + var jobRun = repository.GetJobRuns(); Assert.AreEqual(2, jobRun.Items.Count, "Trigger should continue trigger additional jobruns"); - Assert.AreEqual(2, this.lastIssuedPlan.Count, "The plan should contain items for all 3 triggers"); + Assert.AreEqual(2, lastIssuedPlan.Count, "The plan should contain items for all 3 triggers"); } [TestMethod] public void NoParallelExecutionDisabled_ForceNewPlanWhileJobIsStillRunning_NextJobRunIsCreated() { var initialDate = new DateTime(2017, 02, 01, 15, 42, 12, DateTimeKind.Utc); - this.currentTimeProvider.Set(initialDate); + currentTimeProvider.Set(initialDate); - var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = this.demoJob1Id, IsActive = true, NoParallelExecution = false }; - this.AddAndSignalNewTrigger(this.demoJob1Id, recurringTrigger); + var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = demoJob1Id, IsActive = true, NoParallelExecution = false }; + AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); // Simulate that the jobRun has started - var addedJobRun = this.repository.GetJobRunsByTriggerId(recurringTrigger.JobId, recurringTrigger.Id).Items.Single(); + var addedJobRun = repository.GetJobRunsByTriggerId(recurringTrigger.JobId, recurringTrigger.Id).Items.Single(); addedJobRun.State = JobRunStates.Processing; - this.repository.Update(addedJobRun); + repository.Update(addedJobRun); // Make sure the cron in the recurring trigger will base on an updated "now" - this.currentTimeProvider.Set(initialDate.AddHours(2)); - this.periodicTimer.CallbackOnce(); + currentTimeProvider.Set(initialDate.AddHours(2)); + periodicTimer.CallbackOnce(); - var jobRuns = this.repository.GetJobRuns(); + var jobRuns = repository.GetJobRuns(); Assert.AreEqual(2, jobRuns.Items.Count); - Assert.AreEqual(2, this.lastIssuedPlan.Count, "Since one JobRun has completed, there should be now 2 jobruns"); - Assert.AreEqual(2, this.repository.GetJobRuns().Items.Count, "The recurring trigger should should have triggered 2"); + Assert.AreEqual(2, lastIssuedPlan.Count, "Since one JobRun has completed, there should be now 2 jobruns"); + Assert.AreEqual(2, repository.GetJobRuns().Items.Count, "The recurring trigger should should have triggered 2"); } [TestMethod] public void NoParallelExecutionEnabled_TriggerWhileJobIsStillRunning_NextJobRunIsPrevented() { var initialDate = new DateTime(2017, 02, 01, 15, 42, 12, DateTimeKind.Utc); - this.currentTimeProvider.Set(initialDate); + currentTimeProvider.Set(initialDate); - var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = this.demoJob1Id, IsActive = true, NoParallelExecution = true }; + var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = demoJob1Id, IsActive = true, NoParallelExecution = true }; // This triggers the first jobrun - this.AddAndSignalNewTrigger(this.demoJob1Id, recurringTrigger); + AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); // Simulate that the jobRun has started - var addedJobRun = this.repository.GetJobRunsByTriggerId(recurringTrigger.JobId, recurringTrigger.Id).Items.Single(); + var addedJobRun = repository.GetJobRunsByTriggerId(recurringTrigger.JobId, recurringTrigger.Id).Items.Single(); addedJobRun.State = JobRunStates.Processing; - this.repository.Update(addedJobRun); + repository.Update(addedJobRun); // Make sure the cron in the recurring trigger will base on an updated "now" - this.currentTimeProvider.Set(initialDate.AddHours(2)); - this.periodicTimer.CallbackOnce(); + currentTimeProvider.Set(initialDate.AddHours(2)); + periodicTimer.CallbackOnce(); - var jobRuns = this.repository.GetJobRuns(); + var jobRuns = repository.GetJobRuns(); Assert.AreEqual(1, jobRuns.Items.Count, "Creating new jobruns should be prevented if a JobRun is not yet completed for the trigger"); - Assert.AreEqual(1, this.lastIssuedPlan.Count, "It doesn't mather how often the Callback for recurring trigger scheduling is called, as long as there is a job running, there shoulnd be any additional jobs"); + Assert.AreEqual(1, lastIssuedPlan.Count, "It doesn't mather how often the Callback for recurring trigger scheduling is called, as long as there is a job running, there shoulnd be any additional jobs"); } [TestMethod] public void RecurringTrigger_WhenAddedBeforeStart_ShouldTriggerOneRun() { - this.scheduler.Stop(); + scheduler.Stop(); var futureDate = new DateTime(2017, 02, 01, 15, 42, 12, DateTimeKind.Utc); - this.currentTimeProvider.Set(futureDate); + currentTimeProvider.Set(futureDate); - var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = this.demoJob1Id, IsActive = true }; + var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = demoJob1Id, IsActive = true }; - // This triggers the first jobrun - this.repository.AddJob(new Job {Id = this.demoJob1Id}); - this.repository.SaveAddTrigger(this.demoJob1Id, recurringTrigger); + // This triggers the first job run + repository.AddJob(new Job { Id = demoJob1Id }); + repository.SaveAddTrigger(demoJob1Id, recurringTrigger); - this.scheduler.Start(); + scheduler.Start(); - var jobRuns = this.repository.GetJobRuns(); + var jobRuns = repository.GetJobRuns(); Assert.AreEqual(1, jobRuns.Items.Count, "There should only be one jobrun"); Assert.AreEqual(futureDate.Date, jobRuns.Items[0].PlannedStartDateTimeUtc.Date); @@ -272,17 +296,22 @@ public void RecurringTrigger_WhenAddedBeforeStart_ShouldTriggerOneRun() public void RecurringTrigger_WhileRunIsIncomplete_ShouldNotRaiseNewRunsAtTheSameTime() { var futureDate = new DateTime(2017, 02, 01, 15, 42, 12, DateTimeKind.Utc); - this.currentTimeProvider.Set(futureDate); + currentTimeProvider.Set(futureDate); - var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = this.demoJob1Id, IsActive = true}; + var recurringTrigger = new RecurringTrigger + { + Definition = "* * * * *", + JobId = demoJob1Id, + IsActive = true + }; - // This triggers the first jobrun - this.AddAndSignalNewTrigger(this.demoJob1Id, recurringTrigger); + // This triggers the first job run + AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); - this.currentTimeProvider.AddSecond(); - this.periodicTimer.CallbackOnce(); + currentTimeProvider.AddSecond(); + periodicTimer.CallbackOnce(); - var jobRuns = this.repository.GetJobRuns(); + var jobRuns = repository.GetJobRuns(); Assert.AreEqual(1, jobRuns.Items.Count, "The periodic callback should not create new jobruns if they would start at the same time (== planned starttime has not changed)"); } @@ -291,16 +320,22 @@ public void RecurringTrigger_WhileRunIsIncomplete_ShouldNotRaiseNewRunsAtTheSame public void RecurringTrigger_EndDateInPast_DoesNotTriggerRun() { var currentNow = new DateTime(2017, 02, 01, 15, 42, 00, DateTimeKind.Utc); - this.currentTimeProvider.Set(currentNow); + currentTimeProvider.Set(currentNow); - var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = this.demoJob1Id, IsActive = true, EndDateTimeUtc = currentNow.AddDays(-1)}; + var recurringTrigger = new RecurringTrigger + { + Definition = "* * * * *", + JobId = demoJob1Id, + IsActive = true, + EndDateTimeUtc = currentNow.AddDays(-1) + }; - // This triggers the first jobrun - this.AddAndSignalNewTrigger(this.demoJob1Id, recurringTrigger); + // This triggers the first job run + AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); - this.periodicTimer.CallbackOnce(); + periodicTimer.CallbackOnce(); - var jobRuns = this.repository.GetJobRuns(); + var jobRuns = repository.GetJobRuns(); Assert.AreEqual(0, jobRuns.Items.Count, "The trigger is not valid anymore and should not trigger a run"); } @@ -309,16 +344,16 @@ public void RecurringTrigger_EndDateInPast_DoesNotTriggerRun() public void RecurringTrigger_StartDateInFuture_FirstRunIsAtStartDate() { var currentNow = new DateTime(2017, 02, 01, 15, 42, 00, DateTimeKind.Utc); - this.currentTimeProvider.Set(currentNow); + currentTimeProvider.Set(currentNow); - var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = this.demoJob1Id, IsActive = true, StartDateTimeUtc = currentNow.AddDays(1) }; + var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = demoJob1Id, IsActive = true, StartDateTimeUtc = currentNow.AddDays(1) }; // This triggers the first jobrun - this.AddAndSignalNewTrigger(this.demoJob1Id, recurringTrigger); + AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); - this.periodicTimer.CallbackOnce(); + periodicTimer.CallbackOnce(); - var jobRuns = this.repository.GetJobRuns(); + var jobRuns = repository.GetJobRuns(); Assert.AreEqual(1, jobRuns.Items.Count, "A startdate in the future should trigger the run"); Assert.AreEqual(currentNow.AddDays(1).Date, jobRuns.Items[0].PlannedStartDateTimeUtc.Date); @@ -328,16 +363,16 @@ public void RecurringTrigger_StartDateInFuture_FirstRunIsAtStartDate() public void RecurringTrigger_StartDateInPast_FirstRunIsAtCurrentNow() { var currentNow = new DateTime(2017, 02, 01, 15, 42, 00, DateTimeKind.Utc); - this.currentTimeProvider.Set(currentNow); + currentTimeProvider.Set(currentNow); - var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = this.demoJob1Id, IsActive = true, StartDateTimeUtc = currentNow.AddDays(-1) }; + var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = demoJob1Id, IsActive = true, StartDateTimeUtc = currentNow.AddDays(-1) }; // This triggers the first jobrun - this.AddAndSignalNewTrigger(this.demoJob1Id, recurringTrigger); + AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); - this.periodicTimer.CallbackOnce(); + periodicTimer.CallbackOnce(); - var jobRuns = this.repository.GetJobRuns(); + var jobRuns = repository.GetJobRuns(); Assert.AreEqual(1, jobRuns.Items.Count, "A startdate in the future should trigger the run"); Assert.AreEqual(currentNow.Date, jobRuns.Items[0].PlannedStartDateTimeUtc.Date); @@ -346,14 +381,21 @@ public void RecurringTrigger_StartDateInPast_FirstRunIsAtCurrentNow() [TestMethod] public void RecurringTrigger_StartAndEndDateCoversNow_DoesNotTriggerRun() { - var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = this.demoJob1Id, IsActive = true, StartDateTimeUtc = DateTime.UtcNow.AddDays(-1), EndDateTimeUtc = DateTime.UtcNow.AddDays(1)}; + var recurringTrigger = new RecurringTrigger + { + Definition = "* * * * *", + JobId = demoJob1Id, + IsActive = true, + StartDateTimeUtc = DateTime.UtcNow.AddDays(-1), + EndDateTimeUtc = DateTime.UtcNow.AddDays(1) + }; - // This triggers the first jobrun - this.AddAndSignalNewTrigger(this.demoJob1Id, recurringTrigger); + // This triggers the first job run + AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); - this.periodicTimer.CallbackOnce(); + periodicTimer.CallbackOnce(); - var jobRuns = this.repository.GetJobRuns(); + var jobRuns = repository.GetJobRuns(); Assert.AreEqual(1, jobRuns.Items.Count, "The trigger should cause a job run because its valid right now"); } diff --git a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/SchedulerTests.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/SchedulerTests.cs index ba3ed2d..fd1ab82 100644 --- a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/SchedulerTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/SchedulerTests.cs @@ -12,19 +12,19 @@ public class SchedulerTests : TestBase public void SchedulerStarts_HasScheduledJobsFromPast_WillSetToOmitted() { var currentTime = new DateTime(2017, 04, 06, 0, 0, 0); - this.currentTimeProvider.Set(currentTime); + currentTimeProvider.Set(currentTime); // Add a couple of jobruns - this.AddJobRun(currentTime.AddDays(-1), JobRunStates.Scheduled); - this.AddJobRun(currentTime.AddDays(-1), JobRunStates.Starting); - this.AddJobRun(currentTime.AddDays(-1), JobRunStates.Completed); - this.AddJobRun(currentTime.AddDays(-1), JobRunStates.Finishing); - this.AddJobRun(currentTime.AddDays(-1), JobRunStates.Failed); + AddJobRun(currentTime.AddDays(-1), JobRunStates.Scheduled); + AddJobRun(currentTime.AddDays(-1), JobRunStates.Starting); + AddJobRun(currentTime.AddDays(-1), JobRunStates.Completed); + AddJobRun(currentTime.AddDays(-1), JobRunStates.Finishing); + AddJobRun(currentTime.AddDays(-1), JobRunStates.Failed); - this.scheduler.Start(); + scheduler.Start(); - var schedulerJobRuns = this.repository.GetJobRunsByState(JobRunStates.Scheduled); - var omittedJobRuns = this.repository.GetJobRunsByState(JobRunStates.Omitted); + var schedulerJobRuns = repository.GetJobRunsByState(JobRunStates.Scheduled); + var omittedJobRuns = repository.GetJobRunsByState(JobRunStates.Omitted); Assert.AreEqual(0, schedulerJobRuns.Items.Count, "The only past scheduled jobrun should have been set to omitted"); Assert.AreEqual(1, omittedJobRuns.Items.Count, "It's assumed that the previous scheduled jobrun is now omitted"); @@ -34,14 +34,14 @@ public void SchedulerStarts_HasScheduledJobsFromPast_WillSetToOmitted() public void SchedulerStarts_HasScheduledJobsInFuture_WillNotTouch() { var currentTime = new DateTime(2017, 04, 06, 0, 0, 0); - this.currentTimeProvider.Set(currentTime); + currentTimeProvider.Set(currentTime); // Add a couple of jobruns - this.AddJobRun(currentTime.AddDays(1), JobRunStates.Scheduled); + AddJobRun(currentTime.AddDays(1), JobRunStates.Scheduled); - this.scheduler.Start(); + scheduler.Start(); - var schedulerJobRuns = this.repository.GetJobRunsByState(JobRunStates.Scheduled); + var schedulerJobRuns = repository.GetJobRunsByState(JobRunStates.Scheduled); Assert.AreEqual(1, schedulerJobRuns.Items.Count, "A future scheduled jobrun should not be omitted"); } @@ -50,104 +50,104 @@ public void SchedulerStarts_HasScheduledJobsInFuture_WillNotTouch() public void SchedulerStarts_HasSRunningJobsFromPast_WillSetToFailed() { var currentTime = new DateTime(2017, 04, 06, 0, 0, 0); - this.currentTimeProvider.Set(currentTime); + currentTimeProvider.Set(currentTime); // Add a couple of jobruns - this.AddJobRun(currentTime.AddDays(-1), JobRunStates.Preparing); - this.AddJobRun(currentTime.AddDays(-1), JobRunStates.Starting); - this.AddJobRun(currentTime.AddDays(-1), JobRunStates.Started); - this.AddJobRun(currentTime.AddDays(-1), JobRunStates.Started); - this.AddJobRun(currentTime.AddDays(-1), JobRunStates.Connected); - this.AddJobRun(currentTime.AddDays(-1), JobRunStates.Initializing); - this.AddJobRun(currentTime.AddDays(-1), JobRunStates.Processing); - this.AddJobRun(currentTime.AddDays(-1), JobRunStates.Finishing); - this.AddJobRun(currentTime.AddDays(-1), JobRunStates.Collecting); + AddJobRun(currentTime.AddDays(-1), JobRunStates.Preparing); + AddJobRun(currentTime.AddDays(-1), JobRunStates.Starting); + AddJobRun(currentTime.AddDays(-1), JobRunStates.Started); + AddJobRun(currentTime.AddDays(-1), JobRunStates.Started); + AddJobRun(currentTime.AddDays(-1), JobRunStates.Connected); + AddJobRun(currentTime.AddDays(-1), JobRunStates.Initializing); + AddJobRun(currentTime.AddDays(-1), JobRunStates.Processing); + AddJobRun(currentTime.AddDays(-1), JobRunStates.Finishing); + AddJobRun(currentTime.AddDays(-1), JobRunStates.Collecting); - this.AddJobRun(currentTime.AddDays(-1), JobRunStates.Completed); + AddJobRun(currentTime.AddDays(-1), JobRunStates.Completed); - this.scheduler.Start(); + scheduler.Start(); - var failedJobRuns = this.repository.GetJobRunsByState(JobRunStates.Failed); + var failedJobRuns = repository.GetJobRunsByState(JobRunStates.Failed); - Assert.AreEqual(9, failedJobRuns.Items.Count, $"Still have jobruns with the following states:\n {string.Join(", ", this.repository.GetJobRuns().Items.Select(jr => jr.State))}"); + Assert.AreEqual(9, failedJobRuns.Items.Count, $"Still have jobruns with the following states:\n {string.Join(", ", repository.GetJobRuns().Items.Select(jr => jr.State))}"); } [TestMethod] public void GivenMultipleScheduledJobRuns_WhenLimitingAmountOfParallelRuns_ThenNewestShouldBeExecuted() { - this.scheduler.Start(); - var jobId = this.AddAndSaveJob(1); + scheduler.Start(); + var jobId = AddAndSaveJob(1); var dateFrom2091 = new DateTime(2091, 5, 17); var dateFrom2092 = new DateTime(2092, 7, 12); var dateFrom2093 = new DateTime(2093, 7, 12); - var firstTrigger = new ScheduledTrigger {JobId = jobId, IsActive = true, StartDateTimeUtc = dateFrom2091}; + var firstTrigger = new ScheduledTrigger { JobId = jobId, IsActive = true, StartDateTimeUtc = dateFrom2091 }; var secondTrigger = new ScheduledTrigger { JobId = jobId, IsActive = true, StartDateTimeUtc = dateFrom2092 }; var thirdTrigger = new ScheduledTrigger { JobId = jobId, IsActive = true, StartDateTimeUtc = dateFrom2093 }; - this.repository.SaveAddTrigger(jobId, firstTrigger); - this.repository.SaveAddTrigger(jobId, secondTrigger); - this.repository.SaveAddTrigger(jobId, thirdTrigger); + repository.SaveAddTrigger(jobId, firstTrigger); + repository.SaveAddTrigger(jobId, secondTrigger); + repository.SaveAddTrigger(jobId, thirdTrigger); - this.scheduler.OnTriggerAdded(jobId, firstTrigger.Id); - this.scheduler.OnTriggerAdded(jobId, secondTrigger.Id); + scheduler.OnTriggerAdded(jobId, firstTrigger.Id); + scheduler.OnTriggerAdded(jobId, secondTrigger.Id); - Assert.AreEqual(1, this.lastIssuedPlan.Count); - Assert.AreEqual(dateFrom2091, this.lastIssuedPlan.Single().PlannedStartDateTimeUtc); + Assert.AreEqual(1, lastIssuedPlan.Count); + Assert.AreEqual(dateFrom2091, lastIssuedPlan.Single().PlannedStartDateTimeUtc); - this.scheduler.OnTriggerAdded(jobId, thirdTrigger.Id); + scheduler.OnTriggerAdded(jobId, thirdTrigger.Id); - Assert.AreEqual(1, this.lastIssuedPlan.Count); - Assert.AreEqual(dateFrom2091, this.lastIssuedPlan.Single().PlannedStartDateTimeUtc); + Assert.AreEqual(1, lastIssuedPlan.Count); + Assert.AreEqual(dateFrom2091, lastIssuedPlan.Single().PlannedStartDateTimeUtc); } [TestMethod] public void GivenMultipleScheduledJobRuns_WhenLimitingAmountOfParallelRuns_ThenLatestShouldNotBeExecuted() { - this.scheduler.Start(); - var jobId = this.AddAndSaveJob(2); + scheduler.Start(); + var jobId = AddAndSaveJob(2); var startTimeTrigger1 = new DateTime(2100, 1, 1); var startTimeTrigger2 = new DateTime(2200, 1, 1); var firstTrigger = new ScheduledTrigger { JobId = jobId, IsActive = true, StartDateTimeUtc = startTimeTrigger1 }; var secondTrigger = new ScheduledTrigger { JobId = jobId, IsActive = true, StartDateTimeUtc = startTimeTrigger2 }; - this.repository.SaveAddTrigger(jobId, firstTrigger); - this.repository.SaveAddTrigger(jobId, secondTrigger); - this.AddJobRun(new DateTime(2050, 1, 1), JobRunStates.Started, jobId); - this.scheduler.OnTriggerAdded(jobId, firstTrigger.Id); + repository.SaveAddTrigger(jobId, firstTrigger); + repository.SaveAddTrigger(jobId, secondTrigger); + AddJobRun(new DateTime(2050, 1, 1), JobRunStates.Started, jobId); + scheduler.OnTriggerAdded(jobId, firstTrigger.Id); - this.scheduler.OnTriggerAdded(jobId, secondTrigger.Id); + scheduler.OnTriggerAdded(jobId, secondTrigger.Id); - Assert.AreEqual(1, this.lastIssuedPlan.Count); - Assert.AreEqual(startTimeTrigger1, this.lastIssuedPlan.Single().PlannedStartDateTimeUtc); + Assert.AreEqual(1, lastIssuedPlan.Count); + Assert.AreEqual(startTimeTrigger1, lastIssuedPlan.Single().PlannedStartDateTimeUtc); } [TestMethod] public void ShouldQueueJobWhenJobRunEnded() { - this.scheduler.Start(); - var jobId = this.AddAndSaveJob(1); + scheduler.Start(); + var jobId = AddAndSaveJob(1); var startTimeTrigger1 = new DateTime(2100, 1, 1); var startTimeTrigger2 = new DateTime(2200, 1, 1); var firstTrigger = new ScheduledTrigger { JobId = jobId, IsActive = true, StartDateTimeUtc = startTimeTrigger1 }; var secondTrigger = new ScheduledTrigger { JobId = jobId, IsActive = true, StartDateTimeUtc = startTimeTrigger2 }; - this.repository.SaveAddTrigger(jobId, firstTrigger); - this.repository.SaveAddTrigger(jobId, secondTrigger); - this.scheduler.OnTriggerAdded(jobId, firstTrigger.Id); - var jobRunId = this.lastIssuedPlan.Single().Id; + repository.SaveAddTrigger(jobId, firstTrigger); + repository.SaveAddTrigger(jobId, secondTrigger); + scheduler.OnTriggerAdded(jobId, firstTrigger.Id); + var jobRunId = lastIssuedPlan.Single().Id; - this.scheduler.OnJobRunEnded(jobRunId); + scheduler.OnJobRunEnded(jobRunId); - Assert.AreEqual(1, this.lastIssuedPlan.Count); - Assert.AreEqual(startTimeTrigger1, this.lastIssuedPlan.Single().PlannedStartDateTimeUtc); + Assert.AreEqual(1, lastIssuedPlan.Count); + Assert.AreEqual(startTimeTrigger1, lastIssuedPlan.Single().PlannedStartDateTimeUtc); } private void AddJobRun(DateTime plannedStartDateTimeUtc, JobRunStates state, long jobId = 0) { - var accordingJobId = jobId != 0 ? jobId : this.demoJob1Id; + var accordingJobId = jobId != 0 ? jobId : demoJob1Id; var scheduledTrigger = new InstantTrigger() { JobId = accordingJobId, IsActive = true }; - var demoJob = this.repository.GetJob(accordingJobId); + var demoJob = repository.GetJob(accordingJobId); - var jobRun = this.repository.SaveNewJobRun(demoJob, scheduledTrigger, plannedStartDateTimeUtc); + var jobRun = repository.SaveNewJobRun(demoJob, scheduledTrigger, plannedStartDateTimeUtc); jobRun.State = state; - this.repository.Update(jobRun); + repository.Update(jobRun); } private long AddAndSaveJob(int maxConcurrentJobRuns) @@ -156,7 +156,7 @@ private long AddAndSaveJob(int maxConcurrentJobRuns) { MaxConcurrentJobRuns = maxConcurrentJobRuns }; - this.repository.AddJob(job); + repository.AddJob(job); return job.Id; } } diff --git a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/TestBase.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/TestBase.cs index e664ae5..d4dd6ac 100644 --- a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/TestBase.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/TestBase.cs @@ -21,23 +21,23 @@ public class TestBase public TestBase() { - this.repository = new JobbrRepository(new NullLoggerFactory(), new InMemoryJobStorageProvider()); + repository = new JobbrRepository(new NullLoggerFactory(), new InMemoryJobStorageProvider()); var executorMock = new Mock(); - executorMock.Setup(e => e.OnPlanChanged(It.IsNotNull>())).Callback>(p => this.lastIssuedPlan = p); + executorMock.Setup(e => e.OnPlanChanged(It.IsNotNull>())).Callback>(p => lastIssuedPlan = p); - this.periodicTimer = new PeriodicTimerMock(); + periodicTimer = new PeriodicTimerMock(); - this.currentTimeProvider = new ManualTimeProvider(); + currentTimeProvider = new ManualTimeProvider(); var job = new Job(); - this.repository.AddJob(job); - this.demoJob1Id = job.Id; + repository.AddJob(job); + demoJob1Id = job.Id; - this.scheduler = new DefaultScheduler(new NullLoggerFactory(), this.repository, executorMock.Object, - new InstantJobRunPlaner(this.currentTimeProvider), new ScheduledJobRunPlaner(this.currentTimeProvider), - new RecurringJobRunPlaner(new NullLoggerFactory(), this.repository, this.currentTimeProvider), new DefaultSchedulerConfiguration(), - this.periodicTimer, this.currentTimeProvider); + scheduler = new DefaultScheduler(new NullLoggerFactory(), repository, executorMock.Object, + new InstantJobRunPlaner(currentTimeProvider), new ScheduledJobRunPlaner(currentTimeProvider), + new RecurringJobRunPlaner(new NullLoggerFactory(), repository, currentTimeProvider), new DefaultSchedulerConfiguration(), + periodicTimer, currentTimeProvider); } } } \ No newline at end of file diff --git a/source/Jobbr.Server.IntegrationTests/Infrastructure/FaultyJobStorageProvider.cs b/source/Jobbr.Server.IntegrationTests/Infrastructure/FaultyJobStorageProvider.cs index 9a8f6dc..2d4fd7f 100644 --- a/source/Jobbr.Server.IntegrationTests/Infrastructure/FaultyJobStorageProvider.cs +++ b/source/Jobbr.Server.IntegrationTests/Infrastructure/FaultyJobStorageProvider.cs @@ -26,140 +26,140 @@ public void DeleteJob(long jobId) public long GetJobsCount() { - this.CheckFailAll(); - return this.inMemoryVersion.GetJobsCount(); + CheckFailAll(); + return inMemoryVersion.GetJobsCount(); } public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { - this.CheckFailAll(); - return this.inMemoryVersion.GetJobs(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); + CheckFailAll(); + return inMemoryVersion.GetJobs(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); } public void AddJob(Job job) { - this.CheckFailAll(); - this.inMemoryVersion.AddJob(job); + CheckFailAll(); + inMemoryVersion.AddJob(job); } public PagedResult GetTriggersByJobId(long jobId, int page = 1, int pageSize = 50, bool showDeleted = false) { - this.CheckFailAll(); - return this.inMemoryVersion.GetTriggersByJobId(jobId); + CheckFailAll(); + return inMemoryVersion.GetTriggersByJobId(jobId); } public PagedResult GetActiveTriggers(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, params string[] sort) { - this.CheckFailAll(); - return this.inMemoryVersion.GetActiveTriggers(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, sort); + CheckFailAll(); + return inMemoryVersion.GetActiveTriggers(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, sort); } public void AddTrigger(long jobId, RecurringTrigger trigger) { - this.CheckFailAll(); - this.inMemoryVersion.AddTrigger(jobId, trigger); + CheckFailAll(); + inMemoryVersion.AddTrigger(jobId, trigger); } public void AddTrigger(long jobId, InstantTrigger trigger) { - this.CheckFailAll(); - this.inMemoryVersion.AddTrigger(jobId, trigger); + CheckFailAll(); + inMemoryVersion.AddTrigger(jobId, trigger); } public void AddTrigger(long jobId, ScheduledTrigger trigger) { - this.CheckFailAll(); - this.inMemoryVersion.AddTrigger(jobId, trigger); + CheckFailAll(); + inMemoryVersion.AddTrigger(jobId, trigger); } public void DisableTrigger(long jobId, long triggerId) { - this.CheckFailAll(); - this.inMemoryVersion.DisableTrigger(jobId, triggerId); + CheckFailAll(); + inMemoryVersion.DisableTrigger(jobId, triggerId); } public void EnableTrigger(long jobId, long triggerId) { - this.CheckFailAll(); - this.inMemoryVersion.EnableTrigger(jobId, triggerId); + CheckFailAll(); + inMemoryVersion.EnableTrigger(jobId, triggerId); } public void DeleteTrigger(long jobId, long triggerId) { - this.CheckFailAll(); - this.inMemoryVersion.DeleteTrigger(jobId, triggerId); + CheckFailAll(); + inMemoryVersion.DeleteTrigger(jobId, triggerId); } public JobTriggerBase GetTriggerById(long jobId, long triggerId) { - this.CheckFailAll(); - return this.inMemoryVersion.GetTriggerById(jobId, triggerId); + CheckFailAll(); + return inMemoryVersion.GetTriggerById(jobId, triggerId); } public JobRun GetLastJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { - this.CheckFailAll(); - return this.inMemoryVersion.GetLastJobRunByTriggerId(jobId, triggerId, utcNow); + CheckFailAll(); + return inMemoryVersion.GetLastJobRunByTriggerId(jobId, triggerId, utcNow); } public JobRun GetNextJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { - this.CheckFailAll(); - return this.inMemoryVersion.GetNextJobRunByTriggerId(jobId, triggerId, utcNow); + CheckFailAll(); + return inMemoryVersion.GetNextJobRunByTriggerId(jobId, triggerId, utcNow); } public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) { - this.CheckFailAll(); - return this.inMemoryVersion.GetJobRunsByTriggerId(jobId, triggerId, page, pageSize, showDeleted, sort); + CheckFailAll(); + return inMemoryVersion.GetJobRunsByTriggerId(jobId, triggerId, page, pageSize, showDeleted, sort); } public PagedResult GetJobRunsByState(JobRunStates state, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { - this.CheckFailAll(); - return this.inMemoryVersion.GetJobRunsByState(state, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); + CheckFailAll(); + return inMemoryVersion.GetJobRunsByState(state, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); } public PagedResult GetJobRunsByStates(JobRunStates[] states, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { - this.CheckFailAll(); - return this.inMemoryVersion.GetJobRunsByStates(states, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); + CheckFailAll(); + return inMemoryVersion.GetJobRunsByStates(states, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); } public PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) { - this.CheckFailAll(); - return this.inMemoryVersion.GetJobRunsByJobId(jobId, page, pageSize, showDeleted, sort); + CheckFailAll(); + return inMemoryVersion.GetJobRunsByJobId(jobId, page, pageSize, showDeleted, sort); } public PagedResult GetJobRunsByUserId(string userId, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) { - this.CheckFailAll(); - return this.inMemoryVersion.GetJobRunsByUserId(userId, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); + CheckFailAll(); + return inMemoryVersion.GetJobRunsByUserId(userId, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); } public PagedResult GetJobRunsByUserDisplayName(string userDisplayName, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) { - this.CheckFailAll(); - return this.inMemoryVersion.GetJobRunsByUserDisplayName(userDisplayName, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); + CheckFailAll(); + return inMemoryVersion.GetJobRunsByUserDisplayName(userDisplayName, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); } public void AddJobRun(JobRun jobRun) { - this.CheckFailAll(); - this.inMemoryVersion.AddJobRun(jobRun); + CheckFailAll(); + inMemoryVersion.AddJobRun(jobRun); } public PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { - this.CheckFailAll(); - return this.inMemoryVersion.GetJobRuns(); + CheckFailAll(); + return inMemoryVersion.GetJobRuns(); } public void UpdateProgress(long jobRunId, double? progress) { - this.CheckFailAll(); - this.inMemoryVersion.UpdateProgress(jobRunId, progress); + CheckFailAll(); + inMemoryVersion.UpdateProgress(jobRunId, progress); } public void ApplyRetention(DateTimeOffset date) @@ -169,65 +169,65 @@ public void ApplyRetention(DateTimeOffset date) public void Update(JobRun jobRun) { - this.CheckFailAll(); - this.inMemoryVersion.Update(jobRun); + CheckFailAll(); + inMemoryVersion.Update(jobRun); } public Job GetJobById(long id) { - this.CheckFailAll(); - return this.inMemoryVersion.GetJobById(id); + CheckFailAll(); + return inMemoryVersion.GetJobById(id); } public Job GetJobByUniqueName(string identifier) { - this.CheckFailAll(); - return this.inMemoryVersion.GetJobByUniqueName(identifier); + CheckFailAll(); + return inMemoryVersion.GetJobByUniqueName(identifier); } public JobRun GetJobRunById(long id) { - this.CheckFailAll(); - return this.inMemoryVersion.GetJobRunById(id); + CheckFailAll(); + return inMemoryVersion.GetJobRunById(id); } public void Update(Job job) { - this.CheckFailAll(); - this.inMemoryVersion.Update(job); + CheckFailAll(); + inMemoryVersion.Update(job); } public void Update(long jobId, InstantTrigger trigger) { - this.CheckFailAll(); - this.inMemoryVersion.Update(jobId, trigger); + CheckFailAll(); + inMemoryVersion.Update(jobId, trigger); } public void Update(long jobId, ScheduledTrigger trigger) { - this.CheckFailAll(); - this.inMemoryVersion.Update(jobId, trigger); + CheckFailAll(); + inMemoryVersion.Update(jobId, trigger); } public void Update(long jobId, RecurringTrigger trigger) { - this.CheckFailAll(); - this.inMemoryVersion.Update(jobId, trigger); + CheckFailAll(); + inMemoryVersion.Update(jobId, trigger); } public void DisableImplementation() { - this.failAll = true; + failAll = true; } public void EnableImplementation() { - this.failAll = false; + failAll = false; } private void CheckFailAll() { - if (this.failAll) + if (failAll) { throw new TargetException("This JobStorageProvider is currently not healthy!"); } diff --git a/source/Jobbr.Server.IntegrationTests/Integration/Execution/JobRunExecutionTestBase.cs b/source/Jobbr.Server.IntegrationTests/Integration/Execution/JobRunExecutionTestBase.cs index f98b7f0..9f76432 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/Execution/JobRunExecutionTestBase.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Execution/JobRunExecutionTestBase.cs @@ -9,11 +9,11 @@ public class JobRunExecutionTestBase : RunningJobbrServerTestBase { protected JobRun TriggerNewJobRun(InstantTrigger trigger) { - this.Services.JobManagementService.AddTrigger(trigger.JobId, trigger); + Services.JobManagementService.AddTrigger(trigger.JobId, trigger); - WaitFor.HasElements(this.Services.JobStorageProvider.GetJobRuns().Items.Where(jr => jr.Trigger.Id == trigger.Id).ToList, 1500); + WaitFor.HasElements(Services.JobStorageProvider.GetJobRuns().Items.Where(jr => jr.Trigger.Id == trigger.Id).ToList, 1500); - var createdJobRun = this.Services.JobStorageProvider.GetJobRuns().Items.First(jr => jr.Trigger.Id == trigger.Id); + var createdJobRun = Services.JobStorageProvider.GetJobRuns().Items.First(jr => jr.Trigger.Id == trigger.Id); return createdJobRun; } @@ -40,7 +40,7 @@ protected Job CreateTestJob() UniqueName = "UniqueTestJobName" }; - this.Services.JobManagementService.AddJob(job); + Services.JobManagementService.AddJob(job); return job; } diff --git a/source/Jobbr.Server.IntegrationTests/Integration/Execution/JobRunInformationServiceTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Execution/JobRunInformationServiceTests.cs index 0126f5d..2207e14 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/Execution/JobRunInformationServiceTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Execution/JobRunInformationServiceTests.cs @@ -8,7 +8,7 @@ public class JobRunInformationServiceTests : JobRunExecutionTestBase [TestMethod] public void RunningServer_GetInfoByRandomId_ReturnsNull() { - var result = this.Services.InformationService.GetByJobRunId(-12); + var result = Services.InformationService.GetByJobRunId(-12); Assert.IsNull(result); } @@ -16,13 +16,13 @@ public void RunningServer_GetInfoByRandomId_ReturnsNull() [TestMethod] public void ExistingJobWithFirstRun_GetInfoById_MatchesConfiguration() { - var job = this.CreateTestJob(); + var job = CreateTestJob(); var trigger = CreateInstantTrigger(job); - var createdJobRun = this.TriggerNewJobRun(trigger); + var createdJobRun = TriggerNewJobRun(trigger); - var result = this.Services.InformationService.GetByJobRunId(createdJobRun.Id); + var result = Services.InformationService.GetByJobRunId(createdJobRun.Id); Assert.IsNotNull(result); Assert.AreEqual(job.Id, result.JobId); @@ -40,17 +40,17 @@ public void ExistingJobWithFirstRun_GetInfoById_MatchesConfiguration() [TestMethod] public void ExistingJobWithSecondRun_GetInfoById_MatchesConfiguration() { - var job = this.CreateTestJob(); + var job = CreateTestJob(); // First run - this.TriggerNewJobRun(CreateInstantTrigger(job)); + TriggerNewJobRun(CreateInstantTrigger(job)); // Second run var secondTrigger = CreateInstantTrigger(job); - var secondJobRun = this.TriggerNewJobRun(secondTrigger); + var secondJobRun = TriggerNewJobRun(secondTrigger); - var result = this.Services.InformationService.GetByJobRunId(secondJobRun.Id); + var result = Services.InformationService.GetByJobRunId(secondJobRun.Id); Assert.IsNotNull(result); Assert.AreEqual(job.Id, result.JobId); @@ -64,6 +64,5 @@ public void ExistingJobWithSecondRun_GetInfoById_MatchesConfiguration() Assert.AreEqual(job.Parameters, result.JobParameters); Assert.AreEqual(secondJobRun.InstanceParameters, result.InstanceParameters); } - } } diff --git a/source/Jobbr.Server.IntegrationTests/Integration/Execution/ProgressChannelTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Execution/ProgressChannelTests.cs index b90d90f..9cf3812 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/Execution/ProgressChannelTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Execution/ProgressChannelTests.cs @@ -12,26 +12,26 @@ public class ProgressChannelTests : JobRunExecutionTestBase public ProgressChannelTests() { - var job = this.CreateTestJob(); + var job = CreateTestJob(); var trigger = CreateInstantTrigger(job); - this.currentRun = this.TriggerNewJobRun(trigger); + currentRun = TriggerNewJobRun(trigger); } [TestMethod] public void Infrastructure_TriggeredJobIsReady() { - Assert.IsNotNull(this.currentRun); + Assert.IsNotNull(currentRun); } [TestMethod] public void ProgressUpdate_With50Percent_IsStored() { - var progressService = this.Services.ProgressChannel; + var progressService = Services.ProgressChannel; - progressService.PublishProgressUpdate(this.currentRun.Id, 50); + progressService.PublishProgressUpdate(currentRun.Id, 50); - var jobRunFromDb = this.Services.JobStorageProvider.GetJobRunsByTriggerId(this.currentRun.Job.Id, this.currentRun.Trigger.Id).Items.Single(); + var jobRunFromDb = Services.JobStorageProvider.GetJobRunsByTriggerId(currentRun.Job.Id, currentRun.Trigger.Id).Items.Single(); Assert.AreEqual(50, jobRunFromDb.Progress); } @@ -39,11 +39,11 @@ public void ProgressUpdate_With50Percent_IsStored() [TestMethod] public void PublishPid_WithRandomInt_IsStored() { - var progressService = this.Services.ProgressChannel; + var progressService = Services.ProgressChannel; - progressService.PublishPid(this.currentRun.Id, 42373, "host01"); + progressService.PublishPid(currentRun.Id, 42373, "host01"); - var jobRunFromDb = this.Services.JobStorageProvider.GetJobRunsByTriggerId(this.currentRun.Job.Id, this.currentRun.Trigger.Id).Items.Single(); + var jobRunFromDb = Services.JobStorageProvider.GetJobRunsByTriggerId(currentRun.Job.Id, currentRun.Trigger.Id).Items.Single(); Assert.AreEqual(42373, jobRunFromDb.Pid); } @@ -51,9 +51,9 @@ public void PublishPid_WithRandomInt_IsStored() [TestMethod] public void StateUpdate_GetsPreparing_IsStored() { - this.SimulateStateUpdate(JobRunStates.Preparing); + SimulateStateUpdate(JobRunStates.Preparing); - var actualState = this.GetActualStoredJobRunState(); + var actualState = GetActualStoredJobRunState(); Assert.AreEqual(ComponentModel.JobStorage.Model.JobRunStates.Preparing, actualState); } @@ -61,9 +61,9 @@ public void StateUpdate_GetsPreparing_IsStored() [TestMethod] public void StateUpdate_GetsStarting_IsStored() { - this.SimulateStateUpdate(JobRunStates.Starting); + SimulateStateUpdate(JobRunStates.Starting); - var actualState = this.GetActualStoredJobRunState(); + var actualState = GetActualStoredJobRunState(); Assert.AreEqual(ComponentModel.JobStorage.Model.JobRunStates.Starting, actualState); } @@ -71,9 +71,9 @@ public void StateUpdate_GetsStarting_IsStored() [TestMethod] public void StateUpdate_GetsStarted_IsStored() { - this.SimulateStateUpdate(JobRunStates.Started); + SimulateStateUpdate(JobRunStates.Started); - var actualState = this.GetActualStoredJobRunState(); + var actualState = GetActualStoredJobRunState(); Assert.AreEqual(ComponentModel.JobStorage.Model.JobRunStates.Started, actualState); } @@ -81,22 +81,22 @@ public void StateUpdate_GetsStarted_IsStored() [TestMethod] public void StateUpdate_GetsStarted_StartDateIsUpdated() { - this.SimulateStateUpdate(JobRunStates.Started); + SimulateStateUpdate(JobRunStates.Started); - var actualJobRun = this.Services.JobStorageProvider.GetJobRunsByTriggerId(this.currentRun.Job.Id, this.currentRun.Trigger.Id).Items.Single(); + var actualJobRun = Services.JobStorageProvider.GetJobRunsByTriggerId(currentRun.Job.Id, currentRun.Trigger.Id).Items.Single(); Assert.IsNotNull(actualJobRun.ActualStartDateTimeUtc); } /// - /// The connected state is usually needed if a forked executor signalizes the connection back to the server + /// The connected state is usually needed if a forked executor signalizes the connection back to the server. /// [TestMethod] public void StateUpdate_GetsConnected_IsStored() { - this.SimulateStateUpdate(JobRunStates.Connected); + SimulateStateUpdate(JobRunStates.Connected); - var actualState = this.GetActualStoredJobRunState(); + var actualState = GetActualStoredJobRunState(); Assert.AreEqual(ComponentModel.JobStorage.Model.JobRunStates.Connected, actualState); } @@ -104,9 +104,9 @@ public void StateUpdate_GetsConnected_IsStored() [TestMethod] public void StateUpdate_GetsInitializing_IsStored() { - this.SimulateStateUpdate(JobRunStates.Initializing); + SimulateStateUpdate(JobRunStates.Initializing); - var actualState = this.GetActualStoredJobRunState(); + var actualState = GetActualStoredJobRunState(); Assert.AreEqual(ComponentModel.JobStorage.Model.JobRunStates.Initializing, actualState); } @@ -114,9 +114,9 @@ public void StateUpdate_GetsInitializing_IsStored() [TestMethod] public void StateUpdate_GetsProcessing_IsStored() { - this.SimulateStateUpdate(JobRunStates.Processing); + SimulateStateUpdate(JobRunStates.Processing); - var actualState = this.GetActualStoredJobRunState(); + var actualState = GetActualStoredJobRunState(); Assert.AreEqual(ComponentModel.JobStorage.Model.JobRunStates.Processing, actualState); } @@ -124,20 +124,19 @@ public void StateUpdate_GetsProcessing_IsStored() [TestMethod] public void StateUpdate_GetsFinishing_IsStored() { - this.SimulateStateUpdate(JobRunStates.Finishing); + SimulateStateUpdate(JobRunStates.Finishing); - var actualState = this.GetActualStoredJobRunState(); + var actualState = GetActualStoredJobRunState(); Assert.AreEqual(ComponentModel.JobStorage.Model.JobRunStates.Finishing, actualState); } - [TestMethod] public void StateUpdate_GetsCollecting_IsStored() { - this.SimulateStateUpdate(JobRunStates.Collecting); + SimulateStateUpdate(JobRunStates.Collecting); - var actualState = this.GetActualStoredJobRunState(); + var actualState = GetActualStoredJobRunState(); Assert.AreEqual(ComponentModel.JobStorage.Model.JobRunStates.Collecting, actualState); } @@ -145,9 +144,9 @@ public void StateUpdate_GetsCollecting_IsStored() [TestMethod] public void StateUpdate_GetsCompleted_IsStored() { - this.SimulateStateUpdate(JobRunStates.Completed); + SimulateStateUpdate(JobRunStates.Completed); - var actualState = this.GetActualStoredJobRunState(); + var actualState = GetActualStoredJobRunState(); Assert.AreEqual(ComponentModel.JobStorage.Model.JobRunStates.Completed, actualState); } @@ -155,23 +154,23 @@ public void StateUpdate_GetsCompleted_IsStored() [TestMethod] public void StateUpdate_GetsFailed_IsStored() { - this.SimulateStateUpdate(JobRunStates.Failed); + SimulateStateUpdate(JobRunStates.Failed); - var actualState = this.GetActualStoredJobRunState(); + var actualState = GetActualStoredJobRunState(); Assert.AreEqual(ComponentModel.JobStorage.Model.JobRunStates.Failed, actualState); } private ComponentModel.JobStorage.Model.JobRunStates GetActualStoredJobRunState() { - return this.Services.JobStorageProvider.GetJobRunsByTriggerId(this.currentRun.Job.Id, this.currentRun.Trigger.Id).Items.Single().State; + return Services.JobStorageProvider.GetJobRunsByTriggerId(currentRun.Job.Id, currentRun.Trigger.Id).Items.Single().State; } private void SimulateStateUpdate(JobRunStates state) { - var progressService = this.Services.ProgressChannel; + var progressService = Services.ProgressChannel; - progressService.PublishStatusUpdate(this.currentRun.Id, state); + progressService.PublishStatusUpdate(currentRun.Id, state); } } } diff --git a/source/Jobbr.Server.IntegrationTests/Integration/ExposeAllServicesComponent.cs b/source/Jobbr.Server.IntegrationTests/Integration/ExposeAllServicesComponent.cs index 5f4ed56..6db737b 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/ExposeAllServicesComponent.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/ExposeAllServicesComponent.cs @@ -9,14 +9,13 @@ namespace Jobbr.Server.IntegrationTests.Integration { /// /// This component consumes all services provided by a standard JobbrServer instance and makes them available by separate properties - /// /// To use this class, register it as a component in the JobbrBuilder. /// public class ExposeAllServicesComponent : IJobbrComponent { public static ExposeAllServicesComponent Instance => instancesPerThread.Value; - private static ThreadLocal instancesPerThread = new (); + private static ThreadLocal instancesPerThread = new ThreadLocal(); public ExposeAllServicesComponent(IJobbrServiceProvider serviceProvider, IArtefactsStorageProvider artefactsStorageProvider, IJobStorageProvider jobStorageProvider, IJobManagementService jobManagementService, IQueryService queryService, IServerManagementService managementService, IJobRunInformationService informationService, IJobRunProgressChannel progressChannel) { @@ -45,7 +44,9 @@ public ExposeAllServicesComponent(IJobbrServiceProvider serviceProvider, IArtefa public IServerManagementService ManagementService { get; } public IJobRunInformationService InformationService { get; } + public IJobRunProgressChannel ProgressChannel { get; } + public void Dispose() { instancesPerThread.Value = null; diff --git a/source/Jobbr.Server.IntegrationTests/Integration/JobRunEnumMappingTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/JobRunEnumMappingTests.cs index 7f017b3..c09b18b 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/JobRunEnumMappingTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/JobRunEnumMappingTests.cs @@ -8,7 +8,7 @@ namespace Jobbr.Server.IntegrationTests.Integration { /// /// Tests that confirm that all members if JobRunStates do have same values if their name are equal - /// In addition, it's ensured that all core members are known in component models and vice-versa + /// In addition, it's ensured that all core members are known in component models and vice-versa. /// [TestClass] public class JobRunEnumMappingTests @@ -26,14 +26,14 @@ public JobRunEnumMappingTests() Assembly.Load(assemblyName); } - this.allComponentModelJobRunEnumTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(asm => asm.GetTypes().Where(this.enumTypeMatcher)); - this.coreType = typeof(Server.Core.Models.JobRunStates); + allComponentModelJobRunEnumTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(asm => asm.GetTypes().Where(enumTypeMatcher)); + coreType = typeof(Server.Core.Models.JobRunStates); } [TestMethod] public void InfrastructureTest_GetComponentModelJobRunEnumTypes_HasSome() { - Assert.IsTrue(this.allComponentModelJobRunEnumTypes.Any(), "There should be some JobRun Enum Types in the Component Models"); + Assert.IsTrue(allComponentModelJobRunEnumTypes.Any(), "There should be some JobRun Enum Types in the Component Models"); } [TestMethod] @@ -41,14 +41,14 @@ public void CoreRunStateNames_IfExistInComponentModels_NameHasSameValue() { var errors = new List(); - foreach (var componentModelEnumType in this.allComponentModelJobRunEnumTypes) + foreach (var componentModelEnumType in allComponentModelJobRunEnumTypes) { - var differences = FindDifferentValues(this.coreType, componentModelEnumType); + var differences = FindDifferentValues(coreType, componentModelEnumType); errors.AddRange(differences); } - Assert.AreEqual(0, errors.Count, $"Found different values while comparing core model enum '{this.coreType}' with component models\n\n" + string.Join("\n", errors)); + Assert.AreEqual(0, errors.Count, $"Found different values while comparing core model enum '{coreType}' with component models\n\n" + string.Join("\n", errors)); } [TestMethod] @@ -56,14 +56,14 @@ public void ComponentModelRunStateNames_IfExistInCore_NameHasSameValue() { var errors = new List(); - foreach (var componentModelEnumType in this.allComponentModelJobRunEnumTypes) + foreach (var componentModelEnumType in allComponentModelJobRunEnumTypes) { - var differences = FindDifferentValues(componentModelEnumType, this.coreType); + var differences = FindDifferentValues(componentModelEnumType, coreType); errors.AddRange(differences); } - Assert.AreEqual(0, errors.Count, $"Found different values for same enum names while comparing all component model with '{this.coreType}'\n\n" + string.Join("\n", errors)); + Assert.AreEqual(0, errors.Count, $"Found different values for same enum names while comparing all component model with '{coreType}'\n\n" + string.Join("\n", errors)); } [TestMethod] @@ -71,9 +71,9 @@ public void ComponentModelRunStateNames_ComparedToAllComponentModels_HaveSameVal { var errors = new List(); - foreach (var master in this.allComponentModelJobRunEnumTypes) + foreach (var master in allComponentModelJobRunEnumTypes) { - foreach (var target in this.allComponentModelJobRunEnumTypes) + foreach (var target in allComponentModelJobRunEnumTypes) { var differences = FindDifferentValues(master, target); errors.AddRange(differences); @@ -86,11 +86,11 @@ public void ComponentModelRunStateNames_ComparedToAllComponentModels_HaveSameVal [TestMethod] public void CoreRunStateNames_ForAllComponentModel_ShouldBeKnown() { - var masterMembers = Enum.GetNames(this.coreType); + var masterMembers = Enum.GetNames(coreType); var errors = new List(); - foreach (var cmEnumType in this.allComponentModelJobRunEnumTypes) + foreach (var cmEnumType in allComponentModelJobRunEnumTypes) { var notFound = masterMembers.Except(Enum.GetNames(cmEnumType)); @@ -103,11 +103,11 @@ public void CoreRunStateNames_ForAllComponentModel_ShouldBeKnown() [TestMethod] public void ComponentModelStateNames_ComparedToCore_ShouldBeKnown() { - var masterMembers = Enum.GetNames(this.coreType); + var masterMembers = Enum.GetNames(coreType); var errors = new List(); - foreach (var cmEnumType in this.allComponentModelJobRunEnumTypes) + foreach (var cmEnumType in allComponentModelJobRunEnumTypes) { var notFound = Enum.GetNames(cmEnumType).Except(masterMembers); @@ -124,11 +124,14 @@ private static IEnumerable FindDifferentValues(Type masterType, Type rem foreach (var name in Enum.GetNames(masterType)) { // Only check those member that also exist in remoteType - if (!remoteMembers.Contains(name)) continue; + if (!remoteMembers.Contains(name)) + { + continue; + } // AutoMapper maps by using the index/value of the enum so we do - var masterValue = (int) Enum.Parse(masterType, name); - var remoteValue = (int) Enum.Parse(remoteType, name); + var masterValue = (int)Enum.Parse(masterType, name); + var remoteValue = (int)Enum.Parse(remoteType, name); if (remoteValue != masterValue) { diff --git a/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs b/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs index 8f741fd..a7cc02e 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs @@ -13,21 +13,21 @@ public abstract class JobbrServerTestBase protected JobbrServerTestBase(Func creator) { - this.jobbrServer = creator(); + jobbrServer = creator(); } protected ExposeAllServicesComponent Services => ExposeAllServicesComponent.Instance; protected JobbrServer JobbrServer { - get { return this.jobbrServer; } + get { return jobbrServer; } } [TestCleanup] public void CleanUp() { - this.jobbrServer?.Stop(); - this.jobbrServer?.Dispose(); + jobbrServer?.Stop(); + jobbrServer?.Dispose(); } [TestMethod] @@ -47,7 +47,7 @@ protected static JobbrServer GivenAStartedServer() protected static JobbrServer GivenAServerInstance() { var builder = new JobbrBuilder(new NullLoggerFactory()); - + builder.RegisterForCollection(typeof(ExposeAllServicesComponent)); var server = builder.Create(); diff --git a/source/Jobbr.Server.IntegrationTests/Integration/Management/JobManagementTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Management/JobManagementTests.cs index 872ab34..e25ed08 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/Management/JobManagementTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Management/JobManagementTests.cs @@ -12,7 +12,7 @@ public class JobManagementTests : InitializedJobbrServerTestBase public void JobService_ExistingScheduledTriggerIsUpdated_UpdateIsPersisted() { var demoJob = new Job(); - var storageProvider = this.Services.JobStorageProvider; + var storageProvider = Services.JobStorageProvider; storageProvider.AddJob(demoJob); var futureDate1 = DateTime.UtcNow.AddHours(2); @@ -23,7 +23,7 @@ public void JobService_ExistingScheduledTriggerIsUpdated_UpdateIsPersisted() var updatedTrigger = new ScheduledTrigger { Id = initialTrigger.Id, JobId = demoJob.Id, StartDateTimeUtc = futureDate2, IsActive = true }; - this.Services.JobManagementService.UpdateTriggerStartTime(demoJob.Id, updatedTrigger.Id, updatedTrigger.StartDateTimeUtc); + Services.JobManagementService.UpdateTriggerStartTime(demoJob.Id, updatedTrigger.Id, updatedTrigger.StartDateTimeUtc); var assertTrigger = (ScheduledTrigger)storageProvider.GetTriggerById(demoJob.Id, initialTrigger.Id); @@ -34,7 +34,7 @@ public void JobService_ExistingScheduledTriggerIsUpdated_UpdateIsPersisted() public void JobService_ExistingRecurringTriggerIsUpdated_UpdateIsPersisted() { var demoJob = new Job(); - var storageProvider = this.Services.JobStorageProvider; + var storageProvider = Services.JobStorageProvider; storageProvider.AddJob(demoJob); var definition1 = "1 1 1 1 1"; @@ -45,7 +45,7 @@ public void JobService_ExistingRecurringTriggerIsUpdated_UpdateIsPersisted() var updatedTrigger = new RecurringTrigger { Id = initialTrigger.Id, JobId = demoJob.Id, Definition = definition2, IsActive = true }; - this.Services.JobManagementService.UpdateTriggerDefinition(demoJob.Id, updatedTrigger.Id, updatedTrigger.Definition); + Services.JobManagementService.UpdateTriggerDefinition(demoJob.Id, updatedTrigger.Id, updatedTrigger.Definition); var assertTrigger = (RecurringTrigger)storageProvider.GetTriggerById(demoJob.Id, initialTrigger.Id); @@ -57,12 +57,12 @@ public void JobRunWithArtefacts_WhenRetrieved_ReturnsAll() { // Arrange var jobRun = new JobRun(); - this.Services.JobStorageProvider.AddJobRun(jobRun); - this.Services.ArtefactsStorageProvider.Save(jobRun.Id.ToString(), "file1.txt", new MemoryStream()); - this.Services.ArtefactsStorageProvider.Save(jobRun.Id.ToString(), "file3.txt", new MemoryStream()); + Services.JobStorageProvider.AddJobRun(jobRun); + Services.ArtefactsStorageProvider.Save(jobRun.Id.ToString(), "file1.txt", new MemoryStream()); + Services.ArtefactsStorageProvider.Save(jobRun.Id.ToString(), "file3.txt", new MemoryStream()); // Act - var artefacts = this.Services.JobManagementService.GetArtefactForJob(1); + var artefacts = Services.JobManagementService.GetArtefactForJob(1); Assert.IsNotNull(artefacts); Assert.AreEqual(2, artefacts.Count); @@ -73,10 +73,10 @@ public void JobRunWithNoArtefacts_WhenRetrieved_ReturnsEmptyList() { // Arrange var jobRun = new JobRun(); - this.Services.JobStorageProvider.AddJobRun(jobRun); + Services.JobStorageProvider.AddJobRun(jobRun); // Act - var artefacts = this.Services.JobManagementService.GetArtefactForJob(jobRun.Id); + var artefacts = Services.JobManagementService.GetArtefactForJob(jobRun.Id); Assert.IsNotNull(artefacts); Assert.AreEqual(0, artefacts.Count); @@ -87,12 +87,12 @@ public void JobRunWithArtefacts_GetByFileName_ReturnsSingle() { // Arrange var jobRun = new JobRun(); - this.Services.JobStorageProvider.AddJobRun(jobRun); - this.Services.ArtefactsStorageProvider.Save(jobRun.Id.ToString(), "file1.txt", new MemoryStream()); - this.Services.ArtefactsStorageProvider.Save(jobRun.Id.ToString(), "file3.txt", new MemoryStream()); + Services.JobStorageProvider.AddJobRun(jobRun); + Services.ArtefactsStorageProvider.Save(jobRun.Id.ToString(), "file1.txt", new MemoryStream()); + Services.ArtefactsStorageProvider.Save(jobRun.Id.ToString(), "file3.txt", new MemoryStream()); // Act - var artefact = this.Services.JobManagementService.GetArtefactAsStream(jobRun.Id, "file3.txt"); + var artefact = Services.JobManagementService.GetArtefactAsStream(jobRun.Id, "file3.txt"); Assert.IsNotNull(artefact); } @@ -102,10 +102,10 @@ public void JobRunWithNoArtefacts_GetByFileName_ReturnsNull() { // Arrange var jobRun = new JobRun(); - this.Services.JobStorageProvider.AddJobRun(jobRun); + Services.JobStorageProvider.AddJobRun(jobRun); // Act - var artefact = this.Services.JobManagementService.GetArtefactAsStream(jobRun.Id, "file162z7.txt"); + var artefact = Services.JobManagementService.GetArtefactAsStream(jobRun.Id, "file162z7.txt"); Assert.IsNull(artefact); } @@ -115,12 +115,12 @@ public void JobRunWithArtefacts_GetByUnknownFileName_ReturnsNull() { // Arrange var jobRun = new JobRun(); - this.Services.JobStorageProvider.AddJobRun(jobRun); - this.Services.ArtefactsStorageProvider.Save(jobRun.Id.ToString(), "file1.txt", new MemoryStream()); - this.Services.ArtefactsStorageProvider.Save(jobRun.Id.ToString(), "file3.txt", new MemoryStream()); + Services.JobStorageProvider.AddJobRun(jobRun); + Services.ArtefactsStorageProvider.Save(jobRun.Id.ToString(), "file1.txt", new MemoryStream()); + Services.ArtefactsStorageProvider.Save(jobRun.Id.ToString(), "file3.txt", new MemoryStream()); // Act - var artefact = this.Services.JobManagementService.GetArtefactAsStream(jobRun.Id, "file162z7.txt"); + var artefact = Services.JobManagementService.GetArtefactAsStream(jobRun.Id, "file162z7.txt"); Assert.IsNull(artefact); } diff --git a/source/Jobbr.Server.IntegrationTests/Integration/Management/JobQueryServiceTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Management/JobQueryServiceTests.cs index c0d199f..aff31b1 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/Management/JobQueryServiceTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Management/JobQueryServiceTests.cs @@ -9,13 +9,13 @@ namespace Jobbr.Server.IntegrationTests.Integration.Management [TestClass] public class JobQueryServiceTests : InitializedJobbrServerTestBase { - public IQueryService QueryService => this.Services.QueryService; + public IQueryService QueryService => Services.QueryService; [TestMethod] public void HasNoJobs_QueryAllJobs_ShouldReturnEmptyList() { // Act - var jobs = this.QueryService.GetJobs(); + var jobs = QueryService.GetJobs(); // Assert Assert.IsNotNull(jobs); @@ -26,10 +26,10 @@ public void HasNoJobs_QueryAllJobs_ShouldReturnEmptyList() public void HasOneJob_QueryAllJobs_ShouldReturnOne() { // Arrange - this.Services.JobStorageProvider.AddJob(new Job()); + Services.JobStorageProvider.AddJob(new Job()); // Act - var jobs = this.QueryService.GetJobs(); + var jobs = QueryService.GetJobs(); // Assert Assert.AreEqual(1, jobs.Items.Count); @@ -40,10 +40,10 @@ public void HasOneJob_QueryJobByExistingId_ReturnsSingle() { // Arrange var job = new Job(); - this.Services.JobStorageProvider.AddJob(job); + Services.JobStorageProvider.AddJob(job); // Act - var jobQueried = this.QueryService.GetJobById(job.Id); + var jobQueried = QueryService.GetJobById(job.Id); // Assert Assert.AreEqual(job.Id, jobQueried.Id); @@ -54,24 +54,26 @@ public void HasOneJobWithTrigger_QueryJobByExistingId_ReturnsJobWithTrigger() { // Arrange var job = new Job(); - this.Services.JobStorageProvider.AddJob(job); - - var trigger = new RecurringTrigger() { Definition = "* * * * *" }; - this.Services.JobStorageProvider.AddTrigger(job.Id, trigger); + Services.JobStorageProvider.AddJob(job); + + var trigger = new RecurringTrigger + { + Definition = "* * * * *" + }; + Services.JobStorageProvider.AddTrigger(job.Id, trigger); // Act - var result = this.QueryService.GetJobById(job.Id); - + var result = QueryService.GetJobById(job.Id); } [TestMethod] public void HasOneJob_QueryJobByWrongId_ReturnsNull() { // Arrange - this.Services.JobStorageProvider.AddJob(new Job { Id = 13 }); + Services.JobStorageProvider.AddJob(new Job { Id = 13 }); // Act - var job = this.QueryService.GetJobById(42); + var job = QueryService.GetJobById(42); Assert.IsNull(job); } @@ -80,10 +82,10 @@ public void HasOneJob_QueryJobByWrongId_ReturnsNull() public void HasOneJob_QueryJobByExistingUniqueName_ReturnsSingle() { // Arrange - this.Services.JobStorageProvider.AddJob(new Job { UniqueName = "MyJob" }); + Services.JobStorageProvider.AddJob(new Job { UniqueName = "MyJob" }); // Act - var job = this.QueryService.GetJobByUniqueName("MyJob"); + var job = QueryService.GetJobByUniqueName("MyJob"); Assert.AreEqual("MyJob", job.UniqueName); } @@ -92,10 +94,10 @@ public void HasOneJob_QueryJobByExistingUniqueName_ReturnsSingle() public void HasOneJob_QueryJobByNonexistingUniqueName_ReturnsNull() { // Arrange - this.Services.JobStorageProvider.AddJob(new Job { UniqueName = "MyJob" }); + Services.JobStorageProvider.AddJob(new Job { UniqueName = "MyJob" }); // Act - var job = this.QueryService.GetJobByUniqueName("haklkjdijl"); + var job = QueryService.GetJobByUniqueName("haklkjdijl"); Assert.IsNull(job); } @@ -108,12 +110,12 @@ public void HasTriggerWithJobId_QueryByMatchingJobId_ReturnsListWithSingle() var recurringTrigger = new RecurringTrigger() { IsActive = true }; var scheduledTrigger = new ScheduledTrigger { IsActive = true }; - this.Services.JobStorageProvider.AddTrigger(100, instantTrigger); - this.Services.JobStorageProvider.AddTrigger(200, recurringTrigger); - this.Services.JobStorageProvider.AddTrigger(300, scheduledTrigger); + Services.JobStorageProvider.AddTrigger(100, instantTrigger); + Services.JobStorageProvider.AddTrigger(200, recurringTrigger); + Services.JobStorageProvider.AddTrigger(300, scheduledTrigger); // Act - var triggers = this.QueryService.GetTriggersByJobId(200, 1, 50).Items; + var triggers = QueryService.GetTriggersByJobId(200, 1, 50).Items; var assertingRecurringTrigger = triggers[0] as ComponentModel.Management.Model.RecurringTrigger; // Test @@ -135,10 +137,10 @@ public void Recurring_Trigger_Properties_Mapped() NoParallelExecution = true, }; - this.Services.JobStorageProvider.AddTrigger(1000, recurringTrigger); + Services.JobStorageProvider.AddTrigger(1000, recurringTrigger); // Act - var result = this.QueryService.GetTriggersByJobId(1000, 1, 50).Items[0] as ComponentModel.Management.Model.RecurringTrigger; + var result = QueryService.GetTriggersByJobId(1000, 1, 50).Items[0] as ComponentModel.Management.Model.RecurringTrigger; // Assert Assert.IsNotNull(result); @@ -156,14 +158,14 @@ public void HasDifferentTriggerTypes_QueryById_ReturnsCorrectType() var instantTrigger = new InstantTrigger(); var recurringTrigger = new RecurringTrigger(); var scheduledTrigger = new ScheduledTrigger(); - this.Services.JobStorageProvider.AddTrigger(jobId, instantTrigger); - this.Services.JobStorageProvider.AddTrigger(jobId, recurringTrigger); - this.Services.JobStorageProvider.AddTrigger(jobId, scheduledTrigger); + Services.JobStorageProvider.AddTrigger(jobId, instantTrigger); + Services.JobStorageProvider.AddTrigger(jobId, recurringTrigger); + Services.JobStorageProvider.AddTrigger(jobId, scheduledTrigger); // Act - var instantTypeTrigger = this.QueryService.GetTriggerById(jobId, instantTrigger.Id); - var recurringTypeTrigger = this.QueryService.GetTriggerById(jobId, recurringTrigger.Id); - var scheduledTypeTrigger = this.QueryService.GetTriggerById(jobId, scheduledTrigger.Id); + var instantTypeTrigger = QueryService.GetTriggerById(jobId, instantTrigger.Id); + var recurringTypeTrigger = QueryService.GetTriggerById(jobId, recurringTrigger.Id); + var scheduledTypeTrigger = QueryService.GetTriggerById(jobId, scheduledTrigger.Id); // Test Assert.AreEqual(typeof(ComponentModel.Management.Model.InstantTrigger), instantTypeTrigger.GetType()); @@ -171,19 +173,18 @@ public void HasDifferentTriggerTypes_QueryById_ReturnsCorrectType() Assert.AreEqual(typeof(ComponentModel.Management.Model.ScheduledTrigger), scheduledTypeTrigger.GetType()); } - [TestMethod] public void HasActiveTriggers_QueryActive_ReturnsAll() { const long jobId = 1; // Arrange - this.Services.JobStorageProvider.AddTrigger(jobId, new InstantTrigger { IsActive = true }); - this.Services.JobStorageProvider.AddTrigger(jobId, new RecurringTrigger { IsActive = true }); - this.Services.JobStorageProvider.AddTrigger(jobId, new ScheduledTrigger { IsActive = true }); + Services.JobStorageProvider.AddTrigger(jobId, new InstantTrigger { IsActive = true }); + Services.JobStorageProvider.AddTrigger(jobId, new RecurringTrigger { IsActive = true }); + Services.JobStorageProvider.AddTrigger(jobId, new ScheduledTrigger { IsActive = true }); // Act - var triggers = this.QueryService.GetActiveTriggers(); + var triggers = QueryService.GetActiveTriggers(); // Test Assert.AreEqual(3, triggers.Items.Count); @@ -195,15 +196,15 @@ public void HasActiveAndInactiveTriggers_QueryActive_ReturnsOnlyActive() const long jobId = 1; // Arrange - this.Services.JobStorageProvider.AddTrigger(jobId, new InstantTrigger { IsActive = true }); - this.Services.JobStorageProvider.AddTrigger(jobId, new RecurringTrigger { IsActive = true }); - this.Services.JobStorageProvider.AddTrigger(jobId, new ScheduledTrigger { IsActive = true }); - this.Services.JobStorageProvider.AddTrigger(jobId, new InstantTrigger { IsActive = false }); - this.Services.JobStorageProvider.AddTrigger(jobId, new RecurringTrigger { IsActive = false }); - this.Services.JobStorageProvider.AddTrigger(jobId, new ScheduledTrigger { IsActive = false }); + Services.JobStorageProvider.AddTrigger(jobId, new InstantTrigger { IsActive = true }); + Services.JobStorageProvider.AddTrigger(jobId, new RecurringTrigger { IsActive = true }); + Services.JobStorageProvider.AddTrigger(jobId, new ScheduledTrigger { IsActive = true }); + Services.JobStorageProvider.AddTrigger(jobId, new InstantTrigger { IsActive = false }); + Services.JobStorageProvider.AddTrigger(jobId, new RecurringTrigger { IsActive = false }); + Services.JobStorageProvider.AddTrigger(jobId, new ScheduledTrigger { IsActive = false }); // Act - var triggers = this.QueryService.GetActiveTriggers(); + var triggers = QueryService.GetActiveTriggers(); // Test Assert.AreEqual(3, triggers.Items.Count); @@ -215,14 +216,14 @@ public void HasActiveTriggers_QueryById_ReturnsSingle() const long jobId = 1; // Arrange - this.Services.JobStorageProvider.AddTrigger(jobId, new InstantTrigger { IsActive = true }); - this.Services.JobStorageProvider.AddTrigger(jobId, new RecurringTrigger { IsActive = true }); - this.Services.JobStorageProvider.AddTrigger(jobId, new ScheduledTrigger { IsActive = true }); + Services.JobStorageProvider.AddTrigger(jobId, new InstantTrigger { IsActive = true }); + Services.JobStorageProvider.AddTrigger(jobId, new RecurringTrigger { IsActive = true }); + Services.JobStorageProvider.AddTrigger(jobId, new ScheduledTrigger { IsActive = true }); // Act - var instantTypeTrigger = this.QueryService.GetTriggerById(jobId, 1); - var recurringTypeTrigger = this.QueryService.GetTriggerById(jobId, 2); - var scheduledTypeTrigger = this.QueryService.GetTriggerById(jobId, 3); + var instantTypeTrigger = QueryService.GetTriggerById(jobId, 1); + var recurringTypeTrigger = QueryService.GetTriggerById(jobId, 2); + var scheduledTypeTrigger = QueryService.GetTriggerById(jobId, 3); // Test Assert.IsNotNull(instantTypeTrigger); @@ -240,14 +241,14 @@ public void HasInactiveTriggers_QueryById_ReturnsSingle() const long jobId = 1; // Arrange - this.Services.JobStorageProvider.AddTrigger(jobId, new InstantTrigger { IsActive = false }); - this.Services.JobStorageProvider.AddTrigger(jobId, new RecurringTrigger { IsActive = false }); - this.Services.JobStorageProvider.AddTrigger(jobId, new ScheduledTrigger { IsActive = false }); + Services.JobStorageProvider.AddTrigger(jobId, new InstantTrigger { IsActive = false }); + Services.JobStorageProvider.AddTrigger(jobId, new RecurringTrigger { IsActive = false }); + Services.JobStorageProvider.AddTrigger(jobId, new ScheduledTrigger { IsActive = false }); // Act - var instantTypeTrigger = this.QueryService.GetTriggerById(jobId, 1); - var recurringTypeTrigger = this.QueryService.GetTriggerById(jobId, 2); - var scheduledTypeTrigger = this.QueryService.GetTriggerById(jobId, 3); + var instantTypeTrigger = QueryService.GetTriggerById(jobId, 1); + var recurringTypeTrigger = QueryService.GetTriggerById(jobId, 2); + var scheduledTypeTrigger = QueryService.GetTriggerById(jobId, 3); // Test Assert.IsNotNull(instantTypeTrigger); @@ -264,12 +265,12 @@ public void HasActiveTriggers_QueryByInExistentId_ReturnsNull() { const long jobId = 1; - this.Services.JobStorageProvider.AddTrigger(jobId, new InstantTrigger { IsActive = true }); - this.Services.JobStorageProvider.AddTrigger(jobId, new RecurringTrigger { IsActive = true }); - this.Services.JobStorageProvider.AddTrigger(jobId, new ScheduledTrigger { IsActive = true }); + Services.JobStorageProvider.AddTrigger(jobId, new InstantTrigger { IsActive = true }); + Services.JobStorageProvider.AddTrigger(jobId, new RecurringTrigger { IsActive = true }); + Services.JobStorageProvider.AddTrigger(jobId, new ScheduledTrigger { IsActive = true }); // Act - var trigger = this.QueryService.GetTriggerById(jobId, 42); + var trigger = QueryService.GetTriggerById(jobId, 42); Assert.IsNull(trigger); } @@ -278,12 +279,11 @@ public void HasActiveTriggers_QueryByInExistentId_ReturnsNull() public void HasNoJobRuns_QueryAll_ShouldReturnEmptyList() { // Act - var jobs = this.QueryService.GetJobRuns(); + var jobs = QueryService.GetJobRuns(); // Assert Assert.IsNotNull(jobs); Assert.AreEqual(0, jobs.Items.Count); - } [TestMethod] @@ -291,10 +291,10 @@ public void HasOneJobRun_QueryAll_ShouldReturnOne() { // Arrange var jobRun = new JobRun(); - this.Services.JobStorageProvider.AddJobRun(jobRun); + Services.JobStorageProvider.AddJobRun(jobRun); // Act - var jobs = this.QueryService.GetJobRuns(); + var jobs = QueryService.GetJobRuns(); // Assert Assert.AreEqual(1, jobs.Items.Count); @@ -305,10 +305,10 @@ public void HasOneJobRun_QueryJobByExistingId_ReturnsSingle() { // Arrange var jobRunToAdd = new JobRun(); - this.Services.JobStorageProvider.AddJobRun(jobRunToAdd); + Services.JobStorageProvider.AddJobRun(jobRunToAdd); // Act - var jobRun = this.QueryService.GetJobRunById(jobRunToAdd.Id); + var jobRun = QueryService.GetJobRunById(jobRunToAdd.Id); // Assert Assert.AreEqual(jobRunToAdd.Id, jobRun.Id); @@ -319,10 +319,10 @@ public void HasOneJobRun_QueryJobByWrongId_ReturnsNull() { // Arrange var jobRun = new JobRun(); - this.Services.JobStorageProvider.AddJobRun(jobRun); + Services.JobStorageProvider.AddJobRun(jobRun); // Act - var job = this.QueryService.GetJobRunById(42); + var job = QueryService.GetJobRunById(42); Assert.IsNull(job); } @@ -333,12 +333,12 @@ public void HasOneJobRun_QueryByExistingTriggerId_ReturnsListWithSingle() // Arrange var job = new Job { Id = 1337 }; var trigger = new ScheduledTrigger { Id = 34 }; - + var jobRun = new JobRun { Job = job, Trigger = trigger }; - this.Services.JobStorageProvider.AddJobRun(jobRun); + Services.JobStorageProvider.AddJobRun(jobRun); // Act - var runs = this.QueryService.GetJobRunsByTriggerId(1337, 34); + var runs = QueryService.GetJobRunsByTriggerId(1337, 34); Assert.IsNotNull(runs); Assert.AreEqual(1, runs.Items.Count); @@ -353,10 +353,10 @@ public void HasOneJobRun_QueryByInExistentTriggerId_ReturnsEmptyList() // Arrange var job = new Job { Id = 1000 }; var trigger = new ScheduledTrigger { Id = 34 }; - this.Services.JobStorageProvider.AddJobRun(new JobRun { Job = job, Trigger = trigger }); + Services.JobStorageProvider.AddJobRun(new JobRun { Job = job, Trigger = trigger }); // Act - var runs = this.QueryService.GetJobRunsByTriggerId(-1, -1); + var runs = QueryService.GetJobRunsByTriggerId(-1, -1); Assert.IsNotNull(runs); Assert.AreEqual(0, runs.Items.Count); @@ -370,13 +370,13 @@ public void HasOneMatchingJobRun_QueryJobByUserId_ReturnsListWithSingle() // Arrange var job = new Job { Id = jobId }; var instantTrigger = new InstantTrigger { UserId = "45" }; - this.Services.JobStorageProvider.AddTrigger(jobId, instantTrigger); + Services.JobStorageProvider.AddTrigger(jobId, instantTrigger); var jobRun = new JobRun { Trigger = instantTrigger, Job = job }; - this.Services.JobStorageProvider.AddJobRun(jobRun); + Services.JobStorageProvider.AddJobRun(jobRun); // Act - var runs = this.QueryService.GetJobRunsByUserId("45"); + var runs = QueryService.GetJobRunsByUserId("45"); Assert.IsNotNull(runs); Assert.AreEqual(1, runs.Items.Count); @@ -391,11 +391,11 @@ public void HasOneMatchingJobRun_QueryJobByInexistentUserId_ReturnsEmptyList() // Arrange var job = new Job { Id = jobId }; var instantTrigger = new InstantTrigger { UserId = "45" }; - this.Services.JobStorageProvider.AddTrigger(jobId, instantTrigger); - this.Services.JobStorageProvider.AddJobRun(new JobRun { Trigger = instantTrigger, Job = job }); + Services.JobStorageProvider.AddTrigger(jobId, instantTrigger); + Services.JobStorageProvider.AddJobRun(new JobRun { Trigger = instantTrigger, Job = job }); // Act - var runs = this.QueryService.GetJobRunsByUserId("88"); + var runs = QueryService.GetJobRunsByUserId("88"); Assert.IsNotNull(runs); Assert.AreEqual(0, runs.Items.Count); @@ -409,19 +409,19 @@ public void HasOneMatchingJobRun_QueryJobByUserId_ReturnsSortedListByIdDesc() // Arrange var job = new Job { Id = jobId }; var instantTrigger1 = new InstantTrigger { UserId = "45" }; - this.Services.JobStorageProvider.AddTrigger(jobId, instantTrigger1); + Services.JobStorageProvider.AddTrigger(jobId, instantTrigger1); var instantTrigger2 = new InstantTrigger { UserId = "45" }; - this.Services.JobStorageProvider.AddTrigger(jobId, instantTrigger2); + Services.JobStorageProvider.AddTrigger(jobId, instantTrigger2); var jobRun1 = new JobRun { Job = job, Trigger = instantTrigger1 }; - this.Services.JobStorageProvider.AddJobRun(jobRun1); + Services.JobStorageProvider.AddJobRun(jobRun1); var jobRun2 = new JobRun { Job = job, Trigger = instantTrigger2 }; - this.Services.JobStorageProvider.AddJobRun(jobRun2); + Services.JobStorageProvider.AddJobRun(jobRun2); // Act - var runs = this.QueryService.GetJobRunsByUserId("45"); + var runs = QueryService.GetJobRunsByUserId("45"); Assert.IsNotNull(runs); Assert.AreEqual(2, runs.Items.Count); @@ -433,15 +433,16 @@ public void HasOneMatchingJobRun_QueryJobByUserId_ReturnsSortedListByIdDesc() public void HasOneMatchingJobRun_QueryJobByUserName_ReturnsListWithSingle() { const long jobId = 1; + // Arrange var instantTrigger = new InstantTrigger { UserDisplayName = "hans" }; var job = new Job { Id = jobId }; - this.Services.JobStorageProvider.AddTrigger(jobId, instantTrigger); + Services.JobStorageProvider.AddTrigger(jobId, instantTrigger); - this.Services.JobStorageProvider.AddJobRun(new JobRun { Job = job, Trigger = instantTrigger }); + Services.JobStorageProvider.AddJobRun(new JobRun { Job = job, Trigger = instantTrigger }); // Act - var runs = this.QueryService.GetJobRunsByUserDisplayName("hans"); + var runs = QueryService.GetJobRunsByUserDisplayName("hans"); Assert.IsNotNull(runs); Assert.AreEqual(1, runs.Items.Count); @@ -456,13 +457,13 @@ public void HasOneMatchingJobRun_QueryJobByInexistentUserName_ReturnsEmptyList() // Arrange var instantTrigger = new InstantTrigger { UserDisplayName = "hans" }; var job = new Job { Id = jobId }; - this.Services.JobStorageProvider.AddTrigger(jobId, instantTrigger); + Services.JobStorageProvider.AddTrigger(jobId, instantTrigger); var jobRun = new JobRun { Job = job, Trigger = instantTrigger }; - this.Services.JobStorageProvider.AddJobRun(jobRun); + Services.JobStorageProvider.AddJobRun(jobRun); // Act - var runs = this.QueryService.GetJobRunsByUserDisplayName("blablablabl"); + var runs = QueryService.GetJobRunsByUserDisplayName("blablablabl"); Assert.IsNotNull(runs); Assert.AreEqual(0, runs.Items.Count); @@ -475,19 +476,19 @@ public void HasOneMatchingJobRun_QueryJobByUserName_ReturnsSortedListByIdDesc() // Arrange var instantTrigger1 = new InstantTrigger { UserDisplayName = "hans" }; - this.Services.JobStorageProvider.AddTrigger(jobId, instantTrigger1); + Services.JobStorageProvider.AddTrigger(jobId, instantTrigger1); var instantTrigger2 = new InstantTrigger { UserDisplayName = "hans" }; - this.Services.JobStorageProvider.AddTrigger(jobId, instantTrigger2); + Services.JobStorageProvider.AddTrigger(jobId, instantTrigger2); var jobRun1 = new JobRun { Trigger = instantTrigger1 }; - this.Services.JobStorageProvider.AddJobRun(jobRun1); + Services.JobStorageProvider.AddJobRun(jobRun1); var jobRun2 = new JobRun { Trigger = instantTrigger2 }; - this.Services.JobStorageProvider.AddJobRun(jobRun2); + Services.JobStorageProvider.AddJobRun(jobRun2); // Act - var runs = this.QueryService.GetJobRunsByUserDisplayName("hans"); + var runs = QueryService.GetJobRunsByUserDisplayName("hans"); Assert.IsNotNull(runs); Assert.AreEqual(2, runs.Items.Count); diff --git a/source/Jobbr.Server.IntegrationTests/Integration/Scheduler/SchedulerTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Scheduler/SchedulerTests.cs index 6f409ea..48d9d5b 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/Scheduler/SchedulerTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Scheduler/SchedulerTests.cs @@ -13,8 +13,8 @@ public class SchedulerTests : RunningJobbrServerTestBase [TestMethod] public void JobRunIsScheduled_RecurringTriggerGetsUpdated_JobRunScheduleIsAdjusted() { - var jobManagementService = this.Services.JobManagementService; - var storageProvider = this.Services.JobStorageProvider; + var jobManagementService = Services.JobManagementService; + var storageProvider = Services.JobStorageProvider; var demoJob = new Job(); storageProvider.AddJob(demoJob); @@ -49,8 +49,8 @@ public void JobRunIsScheduled_RecurringTriggerGetsUpdated_JobRunScheduleIsAdjust [TestMethod] public void JobRunIsScheduled_ScheduledTriggerGetsUpdated_JobRunScheduleIsAdjusted() { - var jobManagementService = this.Services.JobManagementService; - var storageProvider = this.Services.JobStorageProvider; + var jobManagementService = Services.JobManagementService; + var storageProvider = Services.JobStorageProvider; var demoJob = new Job(); storageProvider.AddJob(demoJob); @@ -84,8 +84,8 @@ public void JobRunIsScheduled_ScheduledTriggerGetsUpdated_JobRunScheduleIsAdjust [TestMethod] public void JobRunIsScheduler_WhenTriggerGetsDisabled_JobRunWillBeRemoved() { - var jobManagementService = this.Services.JobManagementService; - var storageProvider = this.Services.JobStorageProvider; + var jobManagementService = Services.JobManagementService; + var storageProvider = Services.JobStorageProvider; var demoJob = new Job(); storageProvider.AddJob(demoJob); @@ -116,8 +116,8 @@ public void JobRunIsScheduler_WhenTriggerGetsDisabled_JobRunWillBeRemoved() [TestMethod] public void JobRunIsScheduler_WhenTriggerIsEnabled_JobRunWillBeScheduled() { - var jobManagementService = this.Services.JobManagementService; - var storageProvider = this.Services.JobStorageProvider; + var jobManagementService = Services.JobManagementService; + var storageProvider = Services.JobStorageProvider; var demoJob = new Job(); storageProvider.AddJob(demoJob); diff --git a/source/Jobbr.Server.IntegrationTests/Integration/Startup/ConfigurationValidationTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Startup/ConfigurationValidationTests.cs index 92367c5..033f927 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/Startup/ConfigurationValidationTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Startup/ConfigurationValidationTests.cs @@ -30,33 +30,33 @@ public class DemoSettings public class DemoComponentValidator : IConfigurationValidator { - private readonly Action func; - private readonly bool validationShouldFail; - private readonly bool throwException; + private readonly Action _func; + private readonly bool _validationShouldFail; + private readonly bool _throwException; public Type ConfigurationType { get; set; } = typeof(DemoSettings); public DemoComponentValidator(bool validationShouldFail, bool throwException) { - this.validationShouldFail = validationShouldFail; - this.throwException = throwException; + _validationShouldFail = validationShouldFail; + _throwException = throwException; } public DemoComponentValidator(Action func) { - this.func = func; + _func = func; } public bool Validate(object configuration) { - if (this.throwException) + if (_throwException) { throw new Exception("Exception from here"); } - this.func?.Invoke((DemoSettings)configuration); + _func?.Invoke((DemoSettings)configuration); - return !this.validationShouldFail; + return !_validationShouldFail; } } @@ -67,7 +67,7 @@ public void ValidatorForSettings_WhenRegistered_IsCalled() builder.Add(new DemoSettings()); var isCalled = false; - + builder.AddForCollection(new DemoComponentValidator(s => isCalled = true)); var jobbr = builder.Create(); @@ -86,7 +86,7 @@ public void ValidatorForSettings_WhenCalled_SettingsIsPassedThrough() object settingsToValidate = null; builder.Add(demoSettings); - + builder.AddForCollection(new DemoComponentValidator(s => settingsToValidate = s)); var jobbr = builder.Create(); @@ -104,7 +104,7 @@ public void ValidatorForSettings_ValidationFails_PreventsStart() var builder = new JobbrBuilder(new NullLoggerFactory()); builder.Add(new DemoSettings()); - + builder.AddForCollection(new DemoComponentValidator(validationShouldFail: true, throwException: false)); var jobbr = builder.Create(); diff --git a/source/Jobbr.Server.IntegrationTests/Integration/Startup/SetupValidationTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Startup/SetupValidationTests.cs index 3650f98..8659020 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/Startup/SetupValidationTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Startup/SetupValidationTests.cs @@ -54,7 +54,8 @@ public void CreateJobbr_WithNoStorageProvider_IssuesError() builder.Create(); // Assert - _loggerMock.Verify(m => m.Log( + _loggerMock.Verify( + m => m.Log( LogLevel.Error, It.IsAny(), It.Is((v, _) => v.ToString().Contains("There was no JobStorageProvider registered. Will continue building with an in-memory version, which does not support production scenarios.")), @@ -75,7 +76,8 @@ public void CreateJobbr_WithNoArtefactsProvider_IssuesWarn() builder.Create(); // Assert - _loggerMock.Verify(m => m.Log( + _loggerMock.Verify( + m => m.Log( LogLevel.Warning, It.IsAny(), It.Is((v, _) => v.ToString().Contains("There was no ArtefactsStorageProvider registered. Adding a default InMemoryArtefactStorage, which stores artefacts in memory. Please register a proper ArtefactStorage for production use.")), @@ -96,7 +98,8 @@ public void CreateJobbr_WithNoExecutor_IssuesError() builder.Create(); // Assert - _loggerMock.Verify(m => m.Log( + _loggerMock.Verify( + m => m.Log( LogLevel.Error, It.IsAny(), It.Is((v, _) => v.ToString().Contains("There was no JobExecutor registered. Adding a Non-Operational JobExecutor")), diff --git a/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj b/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj index 274eddd..5726ab0 100644 --- a/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj +++ b/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj @@ -32,10 +32,6 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/source/Jobbr.Server.IntegrationTests/PackagingTests.cs b/source/Jobbr.Server.IntegrationTests/PackagingTests.cs index 378e8c0..36c654e 100644 --- a/source/Jobbr.Server.IntegrationTests/PackagingTests.cs +++ b/source/Jobbr.Server.IntegrationTests/PackagingTests.cs @@ -25,7 +25,7 @@ public void Feature_NuSpec_IsCompliant() asserter.Add(new PackageExistsInBothRule("SimpleInjector")); asserter.Add(new PackageExistsInBothRule("TinyMessenger")); - asserter.Add(new VersionIsIncludedInRange("Jobbr.ComponentModel.*")); + asserter.Add(new VersionIsIncludedInRange("Jobbr.ComponentModel.*")); asserter.Add(new VersionIsIncludedInRange("AutoMapper")); asserter.Add(new VersionIsIncludedInRange("Microsoft.Extensions.Configuration.Abstractions")); asserter.Add(new VersionIsIncludedInRange("Microsoft.Extensions.DependencyInjection")); diff --git a/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs b/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs index 02bf873..08ab200 100644 --- a/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs @@ -19,7 +19,7 @@ namespace Jobbr.Server.IntegrationTests.Registration [TestClass] public class BuilderTests { - ILoggerFactory _loggerFactory; + private ILoggerFactory _loggerFactory; [TestInitialize] public void Initialize() @@ -47,7 +47,8 @@ public void RegisterCustomArtefactStorageProvider_AfterCreation_CorrectTypeIsAct // Assert Assert.IsNotNull(ExposeAllServicesComponent.Instance.ArtefactsStorageProvider); - Assert.AreEqual(typeof(CustomArtefactStorageAdapter), + Assert.AreEqual( + typeof(CustomArtefactStorageAdapter), ExposeAllServicesComponent.Instance.ArtefactsStorageProvider.GetType()); } @@ -65,7 +66,8 @@ public void RegisterCustomJobStorageProvider_AfterCreation_CorrectTypeIsActivate // Assert Assert.IsNotNull(ExposeAllServicesComponent.Instance.ArtefactsStorageProvider); - Assert.AreEqual(typeof(CustomJobStorageProvider), + Assert.AreEqual( + typeof(CustomJobStorageProvider), ExposeAllServicesComponent.Instance.JobStorageProvider.GetType()); } @@ -84,7 +86,7 @@ public void ShouldDeleteJobsAndTriggers_WhenSingleSourceOfTruthIsActivated() var pagedJobs = CreatePagedResult(existingJob, nonExistingJob); var triggerForExistingJob = new RecurringTrigger { Id = existingTriggerId, JobId = existingJobId }; var triggerForNonExistingJob = new RecurringTrigger { Id = nonExistingTriggerId, JobId = nonExistingJobId }; - + var storageMock = new Mock(); storageMock.Setup(s => s.GetJobs(1, int.MaxValue, null, null, null, false)) .Returns(pagedJobs); @@ -93,7 +95,7 @@ public void ShouldDeleteJobsAndTriggers_WhenSingleSourceOfTruthIsActivated() storageMock.Setup(s => s.GetTriggersByJobId(nonExistingJobId, 1, int.MaxValue, false)) .Returns(CreatePagedResult(triggerForNonExistingJob)); SetupForSuccessfulRun(storageMock); - + var builder = new JobbrBuilder(_loggerFactory); builder.Add(storageMock.Object); builder.AddJobs(_loggerFactory, repo => repo.AsSingleSourceOfTruth().Define(existingJobName, "CLR.Type")); @@ -203,14 +205,14 @@ public void ShouldOmitScheduledJob_WhenTriggerIsDeactivated() storageMock.Setup(s => s.GetJobByUniqueName(jobName)).Returns(job); storageMock.Setup(s => s.GetJobRunsByTriggerId(1, 10, 1, int.MaxValue, false)) .Returns(CreatePagedResult(toOmitJobRun)); - + builder.Add(storageMock.Object); builder.AddJobs(_loggerFactory, repo => repo.AsSingleSourceOfTruth().Define(jobName, "CLR.Type").WithTrigger("* * * * *")); // Act builder.Create().Start(); - + // Assert Assert.IsTrue(toOmitJobRun.Deleted); Assert.AreEqual(JobRunStates.Omitted, toOmitJobRun.State); @@ -235,13 +237,10 @@ private static void SetupForSuccessfulRun(Mock storageMock) } } - public interface IPrioritizationStrategy: IComparable + public interface IPrioritizationStrategy : IComparable { - } - #region Fake Implementations - public class CustomArtefactStorageAdapter : IArtefactsStorageProvider { public void Save(string container, string fileName, Stream content) @@ -431,7 +430,4 @@ public bool IsAvailable() throw new NotImplementedException(); } } - } - -#endregion diff --git a/source/Jobbr.Server.IntegrationTests/Registration/TriggerExtensionsTests.cs b/source/Jobbr.Server.IntegrationTests/Registration/TriggerExtensionsTests.cs index df0ce0a..5e48fe6 100644 --- a/source/Jobbr.Server.IntegrationTests/Registration/TriggerExtensionsTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Registration/TriggerExtensionsTests.cs @@ -27,7 +27,7 @@ public void TriggerShouldNotBeTheSame_WhenOnOfTheTriggersIsNull() Assert.IsFalse(isTriggerEqual); - isTriggerEqual = ((InstantTrigger) null).IsTriggerEqual(trigger); + isTriggerEqual = ((InstantTrigger)null).IsTriggerEqual(trigger); Assert.IsFalse(isTriggerEqual); } @@ -90,8 +90,8 @@ public void InstantTriggerShouldBeEqual_WhenSameDelay() const int delay = 100; const int otherDelay = 120; var firstTrigger = new InstantTrigger { DelayedMinutes = delay }; - var secondTrigger = new InstantTrigger {DelayedMinutes = delay}; - var thirdTrigger = new InstantTrigger {DelayedMinutes = otherDelay}; + var secondTrigger = new InstantTrigger { DelayedMinutes = delay }; + var thirdTrigger = new InstantTrigger { DelayedMinutes = otherDelay }; var firstAndSecondEqual = firstTrigger.IsTriggerEqual(secondTrigger); var secondAndThirdEqual = secondTrigger.IsTriggerEqual(thirdTrigger); @@ -105,9 +105,9 @@ public void ScheduledTriggerShouldBeEqual_WhenStartDateIsSame() { var startTime = new DateTime(2000, 1, 1); var anotherStarTime = new DateTime(1999, 12, 12); - var firstTrigger = new ScheduledTrigger {StartDateTimeUtc = startTime}; - var secondTrigger = new ScheduledTrigger {StartDateTimeUtc = startTime}; - var thirdTrigger = new ScheduledTrigger {StartDateTimeUtc = anotherStarTime}; + var firstTrigger = new ScheduledTrigger { StartDateTimeUtc = startTime }; + var secondTrigger = new ScheduledTrigger { StartDateTimeUtc = startTime }; + var thirdTrigger = new ScheduledTrigger { StartDateTimeUtc = anotherStarTime }; var firstAndSecondEqual = firstTrigger.IsTriggerEqual(secondTrigger); var secondAndThirdEqual = secondTrigger.IsTriggerEqual(thirdTrigger); @@ -120,8 +120,8 @@ public void ScheduledTriggerShouldBeEqual_WhenStartDateIsSame() public void RecurringTriggerShouldBeEqual_WhenDefinitionIsEqual() { const string definition = "0 * * * *"; - var firstTrigger = new RecurringTrigger {Definition = definition }; - var secondTrigger = new RecurringTrigger {Definition = definition }; + var firstTrigger = new RecurringTrigger { Definition = definition }; + var secondTrigger = new RecurringTrigger { Definition = definition }; var thirdTrigger = new RecurringTrigger(); var firstAndSecondEqual = firstTrigger.IsTriggerEqual(secondTrigger); diff --git a/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj b/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj index 1b72668..acf266a 100644 --- a/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj +++ b/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj @@ -25,10 +25,6 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/source/Jobbr.Server.UnitTests/Storage/InMemoryJobStorageProviderTests.cs b/source/Jobbr.Server.UnitTests/Storage/InMemoryJobStorageProviderTests.cs index 1a5f50c..16ca150 100644 --- a/source/Jobbr.Server.UnitTests/Storage/InMemoryJobStorageProviderTests.cs +++ b/source/Jobbr.Server.UnitTests/Storage/InMemoryJobStorageProviderTests.cs @@ -280,9 +280,8 @@ public void Update_JobRun_ShouldReplaceExisting() jobRun.JobParameters.ShouldBe(jobRunUpdate.JobParameters); } - [Ignore("The AddJobRun() method generates the JobRun.Id values.\nThe Update() method behaves like an upsert but does not generate any JobRun.Id values.\n" + - "Therefore, adding a JobRun with a custom JobRun.Id can cause unknown behavior.\nHowever, the Update() method neither provides a valid JobRun.Id nor throws an acording error")] + "Therefore, adding a JobRun with a custom JobRun.Id can cause unknown behavior.\nHowever, the Update() method neither provides a valid JobRun.Id nor throws an acording error")] [TestMethod] public void Update_NewJobRun_ShouldSetIdOrThrow() { diff --git a/source/Jobbr.Server/ComponentServices/Execution/MappingProfile.cs b/source/Jobbr.Server/ComponentServices/Execution/MappingProfile.cs index 89a531c..b885c87 100644 --- a/source/Jobbr.Server/ComponentServices/Execution/MappingProfile.cs +++ b/source/Jobbr.Server/ComponentServices/Execution/MappingProfile.cs @@ -8,7 +8,7 @@ internal class MappingProfile : Profile { public MappingProfile() { - this.CreateMap() + CreateMap() .ForMember(d => d.JobId, c => c.MapFrom(s => s.Id)) .ForMember(d => d.JobParameters, c => c.MapFrom(s => s.Parameters)) @@ -21,7 +21,7 @@ public MappingProfile() // Mapped from trigger .ForMember(d => d.UserId, c => c.Ignore()); - this.CreateMap() + CreateMap() .ForMember(d => d.InstanceParameters, c => c.MapFrom(s => s.InstanceParameters)) // Mapped from the Job @@ -32,7 +32,7 @@ public MappingProfile() .ForMember(d => d.UserDisplayName, c => c.Ignore()) ; - this.CreateMap() + CreateMap() .ForMember(d => d.TriggerId, c => c.MapFrom(s => s.Id)) diff --git a/source/Jobbr.Server/ComponentServices/Management/JobManagementService.cs b/source/Jobbr.Server/ComponentServices/Management/JobManagementService.cs index 9fd4782..3e9e30f 100644 --- a/source/Jobbr.Server/ComponentServices/Management/JobManagementService.cs +++ b/source/Jobbr.Server/ComponentServices/Management/JobManagementService.cs @@ -47,7 +47,6 @@ public void DeleteJob(long jobId) { // TODO: implement :) // - terminate job if it is running - throw new NotImplementedException(); } diff --git a/source/Jobbr.Server/ComponentServices/Management/JobQueryService.cs b/source/Jobbr.Server/ComponentServices/Management/JobQueryService.cs index adadca8..4e704ea 100644 --- a/source/Jobbr.Server/ComponentServices/Management/JobQueryService.cs +++ b/source/Jobbr.Server/ComponentServices/Management/JobQueryService.cs @@ -10,36 +10,36 @@ namespace Jobbr.Server.ComponentServices.Management { internal class JobQueryService : IQueryService { - private readonly IJobbrRepository repository; - private readonly IMapper mapper; + private readonly IJobbrRepository _repository; + private readonly IMapper _mapper; public JobQueryService(IJobbrRepository repository, IMapper mapper) { - this.repository = repository; - this.mapper = mapper; + _repository = repository; + _mapper = mapper; } public Job GetJobById(long id) { - var job = this.repository.GetJob(id); + var job = _repository.GetJob(id); - return this.mapper.Map(job); + return _mapper.Map(job); } public Job GetJobByUniqueName(string uniqueName) { - var job = this.repository.GetJobByUniqueName(uniqueName); + var job = _repository.GetJobByUniqueName(uniqueName); - return this.mapper.Map(job); + return _mapper.Map(job); } public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { - var jobs = this.repository.GetJobs(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); + var jobs = _repository.GetJobs(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); return new PagedResult { - Items = this.mapper.Map>(jobs.Items), + Items = _mapper.Map>(jobs.Items), TotalItems = jobs.TotalItems, Page = page, PageSize = pageSize @@ -48,11 +48,11 @@ public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeF public PagedResult GetActiveTriggers(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, params string[] sort) { - var triggers = this.repository.GetActiveTriggers(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, sort); + var triggers = _repository.GetActiveTriggers(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, sort); return new PagedResult { - Items = this.mapper.Map>(triggers.Items), + Items = _mapper.Map>(triggers.Items), TotalItems = triggers.TotalItems, Page = page, PageSize = pageSize @@ -61,18 +61,18 @@ public PagedResult GetActiveTriggers(int page = 1, int pageSize = 5 public IJobTrigger GetTriggerById(long jobId, long triggerId) { - var trigger = this.repository.GetTriggerById(jobId, triggerId); + var trigger = _repository.GetTriggerById(jobId, triggerId); - return this.mapper.Map(trigger); + return _mapper.Map(trigger); } public PagedResult GetTriggersByJobId(long jobId, int page, int pageSize = 50, bool showDeleted = false) { - var triggers = this.repository.GetTriggersByJobId(jobId, page, pageSize, showDeleted); + var triggers = _repository.GetTriggersByJobId(jobId, page, pageSize, showDeleted); return new PagedResult { - Items = this.mapper.Map>(triggers.Items), + Items = _mapper.Map>(triggers.Items), TotalItems = triggers.TotalItems, Page = page, PageSize = pageSize @@ -81,18 +81,18 @@ public PagedResult GetTriggersByJobId(long jobId, int page, int pag public JobRun GetJobRunById(long id) { - var jobRun = this.repository.GetJobRunById(id); + var jobRun = _repository.GetJobRunById(id); - return this.mapper.Map(jobRun); + return _mapper.Map(jobRun); } public PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { - var jobruns = this.repository.GetJobRuns(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); + var jobruns = _repository.GetJobRuns(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); return new PagedResult { - Items = this.mapper.Map>(jobruns.Items), + Items = _mapper.Map>(jobruns.Items), TotalItems = jobruns.TotalItems, Page = page, PageSize = pageSize @@ -101,11 +101,11 @@ public PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jo public PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) { - var jobruns = this.repository.GetJobRunsByJobId(jobId, page, pageSize, showDeleted, sort); + var jobruns = _repository.GetJobRunsByJobId(jobId, page, pageSize, showDeleted, sort); return new PagedResult { - Items = this.mapper.Map>(jobruns.Items), + Items = _mapper.Map>(jobruns.Items), TotalItems = jobruns.TotalItems, Page = page, PageSize = pageSize @@ -114,11 +114,11 @@ public PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSi public PagedResult GetJobRunsByUserId(string userId, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) { - var jobruns = this.repository.GetJobRunsByUserId(userId, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); + var jobruns = _repository.GetJobRunsByUserId(userId, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); return new PagedResult { - Items = this.mapper.Map>(jobruns.Items), + Items = _mapper.Map>(jobruns.Items), TotalItems = jobruns.TotalItems, Page = page, PageSize = pageSize @@ -127,11 +127,11 @@ public PagedResult GetJobRunsByUserId(string userId, int page = 1, int p public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) { - var jobruns = this.repository.GetJobRunsByTriggerId(jobId, triggerId, page, pageSize, showDeleted, sort); + var jobruns = _repository.GetJobRunsByTriggerId(jobId, triggerId, page, pageSize, showDeleted, sort); return new PagedResult { - Items = this.mapper.Map>(jobruns.Items), + Items = _mapper.Map>(jobruns.Items), TotalItems = jobruns.TotalItems, Page = page, PageSize = pageSize @@ -140,11 +140,11 @@ public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int public PagedResult GetJobRunsByUserDisplayName(string userDisplayName, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) { - var jobruns = this.repository.GetJobRunsByUserDisplayName(userDisplayName, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); + var jobruns = _repository.GetJobRunsByUserDisplayName(userDisplayName, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); return new PagedResult { - Items = this.mapper.Map>(jobruns.Items), + Items = _mapper.Map>(jobruns.Items), TotalItems = jobruns.TotalItems, Page = page, PageSize = pageSize @@ -153,11 +153,11 @@ public PagedResult GetJobRunsByUserDisplayName(string userDisplayName, i public PagedResult GetJobRunsByState(JobRunStates state, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { - var jobruns = this.repository.GetJobRunsByState((ComponentModel.JobStorage.Model.JobRunStates)state, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); + var jobruns = _repository.GetJobRunsByState((ComponentModel.JobStorage.Model.JobRunStates)state, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); return new PagedResult { - Items = this.mapper.Map>(jobruns.Items), + Items = _mapper.Map>(jobruns.Items), TotalItems = jobruns.TotalItems, Page = page, PageSize = pageSize @@ -168,11 +168,11 @@ public PagedResult GetJobRunsByStates(JobRunStates[] states, int page = { var statesCast = states.Select(s => (ComponentModel.JobStorage.Model.JobRunStates)s).ToArray(); - var jobruns = this.repository.GetJobRunsByStates(statesCast, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); + var jobruns = _repository.GetJobRunsByStates(statesCast, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); return new PagedResult { - Items = this.mapper.Map>(jobruns.Items), + Items = _mapper.Map>(jobruns.Items), TotalItems = jobruns.TotalItems, Page = page, PageSize = pageSize @@ -181,16 +181,16 @@ public PagedResult GetJobRunsByStates(JobRunStates[] states, int page = public JobRun GetLastJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { - var jobrun = this.repository.GetLastJobRunByTriggerId(jobId, triggerId, utcNow); + var jobrun = _repository.GetLastJobRunByTriggerId(jobId, triggerId, utcNow); - return this.mapper.Map(jobrun); + return _mapper.Map(jobrun); } public JobRun GetNextJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { - var jobrun = this.repository.GetNextJobRunByTriggerId(jobId, triggerId, utcNow); + var jobrun = _repository.GetNextJobRunByTriggerId(jobId, triggerId, utcNow); - return this.mapper.Map(jobrun); + return _mapper.Map(jobrun); } } } \ No newline at end of file diff --git a/source/Jobbr.Server/Core/ITriggerService.cs b/source/Jobbr.Server/Core/ITriggerService.cs index 048c4d1..c59ad7a 100644 --- a/source/Jobbr.Server/Core/ITriggerService.cs +++ b/source/Jobbr.Server/Core/ITriggerService.cs @@ -39,7 +39,7 @@ public interface ITriggerService /// /// Deletes a trigger. /// - /// Job ID + /// Job ID. /// Trigger ID. void Delete(long jobId, long triggerId); diff --git a/source/Jobbr.Server/Core/JobRunService.cs b/source/Jobbr.Server/Core/JobRunService.cs index d5b28e7..9edb4d2 100644 --- a/source/Jobbr.Server/Core/JobRunService.cs +++ b/source/Jobbr.Server/Core/JobRunService.cs @@ -53,7 +53,12 @@ public void UpdateState(long jobRunId, JobRunStates state) jobRun.ActualStartDateTimeUtc = DateTime.UtcNow; } - if (state is JobRunStates.Completed or JobRunStates.Failed) + if (state == JobRunStates.Failed) + { + jobRun.ActualEndDateTimeUtc = DateTime.UtcNow; + } + + if (state == JobRunStates.Completed) { jobRun.ActualEndDateTimeUtc = DateTime.UtcNow; } diff --git a/source/Jobbr.Server/Core/Messaging/TriggerAddedMessage.cs b/source/Jobbr.Server/Core/Messaging/TriggerAddedMessage.cs index 97827b0..06c1792 100644 --- a/source/Jobbr.Server/Core/Messaging/TriggerAddedMessage.cs +++ b/source/Jobbr.Server/Core/Messaging/TriggerAddedMessage.cs @@ -9,8 +9,8 @@ public TriggerAddedMessage(object sender, TriggerKey content) { } - public long TriggerId => this.Content.TriggerId; + public long TriggerId => Content.TriggerId; - public long JobId => this.Content.JobId; + public long JobId => Content.JobId; } } \ No newline at end of file diff --git a/source/Jobbr.Server/Core/Messaging/TriggerStateChangedMessage.cs b/source/Jobbr.Server/Core/Messaging/TriggerStateChangedMessage.cs index 6b09516..d7aafb5 100644 --- a/source/Jobbr.Server/Core/Messaging/TriggerStateChangedMessage.cs +++ b/source/Jobbr.Server/Core/Messaging/TriggerStateChangedMessage.cs @@ -9,8 +9,8 @@ public TriggerStateChangedMessage(object sender, TriggerKey content) { } - public long JobId => this.Content.JobId; + public long JobId => Content.JobId; - public long TriggerId => this.Content.TriggerId; + public long TriggerId => Content.TriggerId; } } \ No newline at end of file diff --git a/source/Jobbr.Server/Core/Messaging/TriggerUpdatedMessage.cs b/source/Jobbr.Server/Core/Messaging/TriggerUpdatedMessage.cs index c5291cc..3f5a9cb 100644 --- a/source/Jobbr.Server/Core/Messaging/TriggerUpdatedMessage.cs +++ b/source/Jobbr.Server/Core/Messaging/TriggerUpdatedMessage.cs @@ -9,8 +9,8 @@ public TriggerUpdatedMessage(object sender, TriggerKey content) { } - public long JobId => this.Content.JobId; + public long JobId => Content.JobId; - public long TriggerId => this.Content.TriggerId; + public long TriggerId => Content.TriggerId; } } \ No newline at end of file diff --git a/source/Jobbr.Server/Core/Models/JobRunStates.cs b/source/Jobbr.Server/Core/Models/JobRunStates.cs index 82ae43a..b9aa026 100644 --- a/source/Jobbr.Server/Core/Models/JobRunStates.cs +++ b/source/Jobbr.Server/Core/Models/JobRunStates.cs @@ -18,7 +18,7 @@ public enum JobRunStates Preparing = 2, /// - /// The JobStarted has started a new executable + /// The JobStarted has started a new executable /// Starting = 3, diff --git a/source/Jobbr.Server/Core/Models/ModelToStorageMappingProfile.cs b/source/Jobbr.Server/Core/Models/ModelToStorageMappingProfile.cs index 81fc97b..5146a11 100644 --- a/source/Jobbr.Server/Core/Models/ModelToStorageMappingProfile.cs +++ b/source/Jobbr.Server/Core/Models/ModelToStorageMappingProfile.cs @@ -7,11 +7,11 @@ internal class ModelToStorageMappingProfile : Profile { public ModelToStorageMappingProfile() { - this.CreateMap(); - this.CreateMap(); - this.CreateMap(); + CreateMap(); + CreateMap(); + CreateMap(); - this.CreateMap(); + CreateMap(); } } } diff --git a/source/Jobbr.Server/Core/Models/StorageToModelMappingProfile.cs b/source/Jobbr.Server/Core/Models/StorageToModelMappingProfile.cs index 833d9fe..3db7e1d 100644 --- a/source/Jobbr.Server/Core/Models/StorageToModelMappingProfile.cs +++ b/source/Jobbr.Server/Core/Models/StorageToModelMappingProfile.cs @@ -7,7 +7,7 @@ internal class StorageToModelMappingProfile : Profile { public StorageToModelMappingProfile() { - this.CreateMap(); + CreateMap(); } } } diff --git a/source/Jobbr.Server/Core/TriggerService.cs b/source/Jobbr.Server/Core/TriggerService.cs index daf9ef3..70d99a4 100644 --- a/source/Jobbr.Server/Core/TriggerService.cs +++ b/source/Jobbr.Server/Core/TriggerService.cs @@ -23,7 +23,7 @@ internal class TriggerService : ITriggerService /// Initializes a new instance of the class. /// /// The logger factory. - /// Repository for accessing job data, + /// Repository for accessing job data. /// SubPub messenger hub. /// The mapper. public TriggerService(ILoggerFactory loggerFactory, IJobbrRepository jobbrRepository, ITinyMessengerHub messengerHub, IMapper mapper) diff --git a/source/Jobbr.Server/JobRegistry/IRegistryBuilder.cs b/source/Jobbr.Server/JobRegistry/IRegistryBuilder.cs index 8c2c7b1..4c22292 100644 --- a/source/Jobbr.Server/JobRegistry/IRegistryBuilder.cs +++ b/source/Jobbr.Server/JobRegistry/IRegistryBuilder.cs @@ -1,5 +1,5 @@ -using Jobbr.ComponentModel.JobStorage; using System; +using Jobbr.ComponentModel.JobStorage; namespace Jobbr.Server.JobRegistry { diff --git a/source/Jobbr.Server/JobRegistry/JobDefinition.cs b/source/Jobbr.Server/JobRegistry/JobDefinition.cs index ef36bfc..9cc88d1 100644 --- a/source/Jobbr.Server/JobRegistry/JobDefinition.cs +++ b/source/Jobbr.Server/JobRegistry/JobDefinition.cs @@ -10,7 +10,7 @@ namespace Jobbr.Server.JobRegistry /// public class JobDefinition { - private readonly List _triggers = new (); + private readonly List _triggers = new List(); private bool _hasTriggerDefinition; /// diff --git a/source/Jobbr.Server/JobRegistry/RegistryBuilder.cs b/source/Jobbr.Server/JobRegistry/RegistryBuilder.cs index d3b509f..e18ea11 100644 --- a/source/Jobbr.Server/JobRegistry/RegistryBuilder.cs +++ b/source/Jobbr.Server/JobRegistry/RegistryBuilder.cs @@ -32,7 +32,7 @@ public RegistryBuilder(ILoggerFactory loggerFactory) /// /// Accessor for s. /// - internal List Definitions { get; } = new (); + internal List Definitions { get; } = new List(); /// public RegistryBuilder RemoveAll() diff --git a/source/Jobbr.Server/JobRegistry/TriggerExtensions.cs b/source/Jobbr.Server/JobRegistry/TriggerExtensions.cs index 8fa5a49..e9e48fc 100644 --- a/source/Jobbr.Server/JobRegistry/TriggerExtensions.cs +++ b/source/Jobbr.Server/JobRegistry/TriggerExtensions.cs @@ -46,11 +46,11 @@ private static bool IsSame(JobTriggerBase left, JobTriggerBase right) switch (left) { case RecurringTrigger leftRecurringTrigger: - return IsSame(leftRecurringTrigger, (RecurringTrigger) right); + return IsSame(leftRecurringTrigger, (RecurringTrigger)right); case ScheduledTrigger leftSchedulingTrigger: - return IsSame(leftSchedulingTrigger, (ScheduledTrigger) right); + return IsSame(leftSchedulingTrigger, (ScheduledTrigger)right); case InstantTrigger leftInstantTrigger: - return IsSame(leftInstantTrigger, (InstantTrigger) right); + return IsSame(leftInstantTrigger, (InstantTrigger)right); default: return false; } diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index ea6a7e6..b3e6bd1 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -34,6 +34,7 @@ + diff --git a/source/Jobbr.Server/Scheduling/DefaultScheduler.cs b/source/Jobbr.Server/Scheduling/DefaultScheduler.cs index 16ff07a..b217188 100644 --- a/source/Jobbr.Server/Scheduling/DefaultScheduler.cs +++ b/source/Jobbr.Server/Scheduling/DefaultScheduler.cs @@ -305,7 +305,6 @@ private void SetRunningJobsToFailed() return; } - _logger.LogWarning("{runningCount} JobRuns are still in the 'Running'-State. They which may have crashed after an unhealthy shutdown.", runningJobRuns.Count); _logger.LogInformation("Need to manually set {runningCount} JobRuns to the state 'Failed'...", runningJobRuns.Count); @@ -432,8 +431,8 @@ private void UpdatePlannedJobRun(JobRun plannedNextRun, JobTriggerBase trigger, if (utcNow.AddSeconds(_schedulerConfiguration.AllowChangesBeforeStartInSec) >= calculatedNextRun) { _logger.LogWarning( - "The planned start date '{startTime}' has changed to '{nextRunStart}'. This change was done too close (less than {changeWindowSecs} seconds) to the next planned run and cannot be adjusted", - plannedNextRun.PlannedStartDateTimeUtc, + "The planned start date '{startTime}' has changed to '{nextRunStart}'. This change was done too close (less than {changeWindowSecs} seconds) to the next planned run and cannot be adjusted", + plannedNextRun.PlannedStartDateTimeUtc, calculatedNextRun, _schedulerConfiguration.AllowChangesBeforeStartInSec); diff --git a/source/Jobbr.Server/Scheduling/FixedMinuteTimer.cs b/source/Jobbr.Server/Scheduling/FixedMinuteTimer.cs index b9a3656..d05b962 100644 --- a/source/Jobbr.Server/Scheduling/FixedMinuteTimer.cs +++ b/source/Jobbr.Server/Scheduling/FixedMinuteTimer.cs @@ -11,27 +11,27 @@ internal class FixedMinuteTimer : IPeriodicTimer, IDisposable public FixedMinuteTimer() { - this.timer = new Timer(state => this.callback()); + timer = new Timer(state => callback()); } public void Setup(Action value) { - this.callback = value; + callback = value; } public void Start() { - this.timer.Change(TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); + timer.Change(TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); } public void Stop() { - this.timer.Change(int.MaxValue, int.MaxValue); + timer.Change(int.MaxValue, int.MaxValue); } public void Dispose() { - this.Dispose(true); + Dispose(true); GC.SuppressFinalize(this); } @@ -39,10 +39,10 @@ protected virtual void Dispose(bool isDisposing) { if (isDisposing) { - if (this.timer != null) + if (timer != null) { - this.timer.Dispose(); - this.timer = null; + timer.Dispose(); + timer = null; } } } diff --git a/source/Jobbr.Server/Scheduling/MaxConcurrentJobRunPlaner.cs b/source/Jobbr.Server/Scheduling/MaxConcurrentJobRunPlaner.cs index 7ca610e..f9c02f1 100644 --- a/source/Jobbr.Server/Scheduling/MaxConcurrentJobRunPlaner.cs +++ b/source/Jobbr.Server/Scheduling/MaxConcurrentJobRunPlaner.cs @@ -15,7 +15,7 @@ public static List GetPossiblePlannedJobRuns(IList GetPossibleRunsPerJob(IEnumerable currentPlan, IJobbrRepository repository) { diff --git a/source/Jobbr.Server/Storage/InMemoryArtefactsStorage.cs b/source/Jobbr.Server/Storage/InMemoryArtefactsStorage.cs index df5784d..7dbc2b5 100644 --- a/source/Jobbr.Server/Storage/InMemoryArtefactsStorage.cs +++ b/source/Jobbr.Server/Storage/InMemoryArtefactsStorage.cs @@ -13,12 +13,12 @@ public class InMemoryArtefactsStorage : IArtefactsStorageProvider public void Save(string container, string fileName, Stream content) { - if (this.files.ContainsKey(container) == false) + if (files.ContainsKey(container) == false) { - this.files.Add(container, new List()); + files.Add(container, new List()); } - var list = this.files[container]; + var list = files[container]; var memoryStream = new MemoryStream(); @@ -37,7 +37,7 @@ public void Save(string container, string fileName, Stream content) public Stream Load(string container, string fileName) { - var filesInContainer = this.GetFilesFromContainer(container); + var filesInContainer = GetFilesFromContainer(container); var file = filesInContainer.FirstOrDefault(p => string.Equals(p.Name, fileName, StringComparison.OrdinalIgnoreCase)); @@ -51,19 +51,19 @@ public Stream Load(string container, string fileName) public List GetArtefacts(string container) { - var filesInContainer = this.GetFilesFromContainer(container); + var filesInContainer = GetFilesFromContainer(container); return filesInContainer.Select(s => new JobbrArtefact { FileName = s.Name }).ToList(); } private IEnumerable GetFilesFromContainer(string container) { - if (this.files.ContainsKey(container) == false) + if (files.ContainsKey(container) == false) { throw new ArgumentException("Container not found"); } - return this.files[container]; + return files[container]; } private class InMemoryFile diff --git a/source/Jobbr.Server/Storage/InMemoryJobStorageProvider.cs b/source/Jobbr.Server/Storage/InMemoryJobStorageProvider.cs index 5b07747..ed30c59 100644 --- a/source/Jobbr.Server/Storage/InMemoryJobStorageProvider.cs +++ b/source/Jobbr.Server/Storage/InMemoryJobStorageProvider.cs @@ -11,34 +11,34 @@ public class InMemoryJobStorageProvider : IJobStorageProvider { private readonly IDictionary>> TriggerOrderByMapping = new Dictionary>> { - {nameof(JobTriggerBase.UserDisplayName), e => e.UserDisplayName}, - {nameof(JobTriggerBase.UserId), e => e.UserId}, - {nameof(JobTriggerBase.Comment), e => e.Comment}, - {nameof(JobTriggerBase.Parameters), e => e.Parameters}, - {nameof(JobTriggerBase.Id), e => e.Id}, - {nameof(JobTriggerBase.JobId), e => e.JobId}, - {nameof(JobTriggerBase.CreatedDateTimeUtc), e => e.CreatedDateTimeUtc}, + { nameof(JobTriggerBase.UserDisplayName), e => e.UserDisplayName }, + { nameof(JobTriggerBase.UserId), e => e.UserId }, + { nameof(JobTriggerBase.Comment), e => e.Comment }, + { nameof(JobTriggerBase.Parameters), e => e.Parameters }, + { nameof(JobTriggerBase.Id), e => e.Id }, + { nameof(JobTriggerBase.JobId), e => e.JobId }, + { nameof(JobTriggerBase.CreatedDateTimeUtc), e => e.CreatedDateTimeUtc } }; private readonly IDictionary>> JobOrderByMapping = new Dictionary>> { - {nameof(Job.Id), e => e.Id}, - {nameof(Job.Title), e => e.Title}, - {nameof(Job.Type), e => e.Type}, - {nameof(Job.UniqueName), e => e.UniqueName}, - {nameof(Job.CreatedDateTimeUtc), e => e.CreatedDateTimeUtc}, - {nameof(Job.UpdatedDateTimeUtc), e => e.UpdatedDateTimeUtc}, + { nameof(Job.Id), e => e.Id }, + { nameof(Job.Title), e => e.Title }, + { nameof(Job.Type), e => e.Type }, + { nameof(Job.UniqueName), e => e.UniqueName }, + { nameof(Job.CreatedDateTimeUtc), e => e.CreatedDateTimeUtc }, + { nameof(Job.UpdatedDateTimeUtc), e => e.UpdatedDateTimeUtc } }; private readonly IDictionary>> JobRunOrderByMapping = new Dictionary>> { - {nameof(JobRun.Id), e => e.Id}, - {nameof(JobRun.ActualStartDateTimeUtc), e => e.ActualStartDateTimeUtc}, - {nameof(JobRun.InstanceParameters), e => e.InstanceParameters}, - {nameof(JobRun.JobParameters), e => e.JobParameters}, - {nameof(JobRun.PlannedStartDateTimeUtc), e => e.PlannedStartDateTimeUtc}, - {nameof(JobRun.ActualEndDateTimeUtc), e => e.ActualEndDateTimeUtc}, - {nameof(JobRun.EstimatedEndDateTimeUtc), e => e.EstimatedEndDateTimeUtc}, + { nameof(JobRun.Id), e => e.Id }, + { nameof(JobRun.ActualStartDateTimeUtc), e => e.ActualStartDateTimeUtc }, + { nameof(JobRun.InstanceParameters), e => e.InstanceParameters }, + { nameof(JobRun.JobParameters), e => e.JobParameters }, + { nameof(JobRun.PlannedStartDateTimeUtc), e => e.PlannedStartDateTimeUtc }, + { nameof(JobRun.ActualEndDateTimeUtc), e => e.ActualEndDateTimeUtc }, + { nameof(JobRun.EstimatedEndDateTimeUtc), e => e.EstimatedEndDateTimeUtc } }; private readonly List localTriggers = new List(); @@ -49,11 +49,11 @@ public class InMemoryJobStorageProvider : IJobStorageProvider public PagedResult GetTriggersByJobId(long jobId, int page = 1, int pageSize = 50, bool showDeleted = false) { - var enumerable = this.localTriggers.Where(t => t.JobId == jobId); + var enumerable = localTriggers.Where(t => t.JobId == jobId); int totalItems; - enumerable = this.ApplyFiltersAndPaging(page, pageSize, null, null, null, enumerable, out totalItems); + enumerable = ApplyFiltersAndPaging(page, pageSize, null, null, null, enumerable, out totalItems); var list = enumerable.ToList().Clone(); @@ -68,11 +68,11 @@ public PagedResult GetTriggersByJobId(long jobId, int page = 1, public PagedResult GetActiveTriggers(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, params string[] sort) { - var enumerable = this.localTriggers.Where(t => t.IsActive); + var enumerable = localTriggers.Where(t => t.IsActive); int totalItems; - enumerable = this.ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, enumerable, out totalItems); + enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, enumerable, out totalItems); if (sort == null || sort.Length == 0) { @@ -80,7 +80,7 @@ public PagedResult GetActiveTriggers(int page = 1, int pageSize } else { - enumerable = ApplySorting(sort, enumerable, this.TriggerOrderByMapping); + enumerable = ApplySorting(sort, enumerable, TriggerOrderByMapping); } var list = enumerable.ToList().Clone(); @@ -98,7 +98,7 @@ public PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jo { int totalItems; - var enumerable = this.ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, this.localJobRuns, out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, localJobRuns, out totalItems); if (sort == null || sort.Length == 0) { @@ -106,7 +106,7 @@ public PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jo } else { - enumerable = ApplySorting(sort, enumerable, this.JobRunOrderByMapping); + enumerable = ApplySorting(sort, enumerable, JobRunOrderByMapping); } return new PagedResult @@ -122,7 +122,7 @@ public PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSi { int totalItems; - var enumerable = this.ApplyFiltersAndPaging(page, pageSize, null, null, null, this.localJobRuns, out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, null, null, null, localJobRuns, out totalItems); if (sort == null || sort.Length == 0) { @@ -130,7 +130,7 @@ public PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSi } else { - enumerable = ApplySorting(sort, enumerable, this.JobRunOrderByMapping); + enumerable = ApplySorting(sort, enumerable, JobRunOrderByMapping); } return new PagedResult @@ -146,7 +146,7 @@ public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int { int totalItems; - var enumerable = this.ApplyFiltersAndPaging(page, pageSize, null, null, null, this.localJobRuns.Where(p => p.Trigger.Id == triggerId), out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, null, null, null, localJobRuns.Where(p => p.Trigger.Id == triggerId), out totalItems); if (sort == null || sort.Length == 0) { @@ -154,7 +154,7 @@ public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int } else { - enumerable = ApplySorting(sort, enumerable, this.JobRunOrderByMapping); + enumerable = ApplySorting(sort, enumerable, JobRunOrderByMapping); } return new PagedResult @@ -168,24 +168,24 @@ public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int public JobTriggerBase GetTriggerById(long jobId, long triggerId) { - return this.localTriggers.FirstOrDefault(t => t.Id == triggerId).Clone(); + return localTriggers.FirstOrDefault(t => t.Id == triggerId).Clone(); } public JobRun GetLastJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { - return this.localJobRuns.FirstOrDefault(jr => jr.Trigger.Id == triggerId && jr.ActualEndDateTimeUtc < utcNow).Clone(); + return localJobRuns.FirstOrDefault(jr => jr.Trigger.Id == triggerId && jr.ActualEndDateTimeUtc < utcNow).Clone(); } public JobRun GetNextJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { - return this.localJobRuns.FirstOrDefault(jr => jr.Trigger.Id == triggerId && jr.PlannedStartDateTimeUtc >= utcNow).Clone(); + return localJobRuns.FirstOrDefault(jr => jr.Trigger.Id == triggerId && jr.PlannedStartDateTimeUtc >= utcNow).Clone(); } public PagedResult GetJobRunsByState(JobRunStates state, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { int totalItems; - var enumerable = this.ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, this.localJobRuns.Where(p => p.State == state), out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, localJobRuns.Where(p => p.State == state), out totalItems); if (sort == null || sort.Length == 0) { @@ -193,7 +193,7 @@ public PagedResult GetJobRunsByState(JobRunStates state, int page = 1, i } else { - enumerable = ApplySorting(sort, enumerable, this.JobRunOrderByMapping); + enumerable = ApplySorting(sort, enumerable, JobRunOrderByMapping); } return new PagedResult @@ -209,7 +209,7 @@ public PagedResult GetJobRunsByStates(JobRunStates[] states, int page = { int totalItems; - var enumerable = this.ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, this.localJobRuns.Where(p => states.Contains(p.State)), out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, localJobRuns.Where(p => states.Contains(p.State)), out totalItems); if (sort == null || sort.Length == 0) { @@ -217,7 +217,7 @@ public PagedResult GetJobRunsByStates(JobRunStates[] states, int page = } else { - enumerable = ApplySorting(sort, enumerable, this.JobRunOrderByMapping); + enumerable = ApplySorting(sort, enumerable, JobRunOrderByMapping); } return new PagedResult @@ -233,7 +233,7 @@ public PagedResult GetJobRunsByUserId(string userId, int page = 1, int p { int totalItems; - var enumerable = this.ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, null, this.localJobRuns.Where(p => string.Equals(p.Trigger.UserId, userId, StringComparison.OrdinalIgnoreCase)), out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, null, localJobRuns.Where(p => string.Equals(p.Trigger.UserId, userId, StringComparison.OrdinalIgnoreCase)), out totalItems); if (sort == null || sort.Length == 0) { @@ -241,7 +241,7 @@ public PagedResult GetJobRunsByUserId(string userId, int page = 1, int p } else { - enumerable = ApplySorting(sort, enumerable, this.JobRunOrderByMapping); + enumerable = ApplySorting(sort, enumerable, JobRunOrderByMapping); } return new PagedResult @@ -255,9 +255,9 @@ public PagedResult GetJobRunsByUserId(string userId, int page = 1, int p public PagedResult GetJobRunsByUserDisplayName(string userDisplayName, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) { - int totalItems; + int totalItems; - var enumerable = this.ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, null, this.localJobRuns.Where(p => string.Equals(p.Trigger.UserDisplayName, userDisplayName, StringComparison.OrdinalIgnoreCase)), out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, null, localJobRuns.Where(p => string.Equals(p.Trigger.UserDisplayName, userDisplayName, StringComparison.OrdinalIgnoreCase)), out totalItems); if (sort == null || sort.Length == 0) { @@ -265,7 +265,7 @@ public PagedResult GetJobRunsByUserDisplayName(string userDisplayName, i } else { - enumerable = ApplySorting(sort, enumerable, this.JobRunOrderByMapping); + enumerable = ApplySorting(sort, enumerable, JobRunOrderByMapping); } return new PagedResult @@ -281,7 +281,7 @@ public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeF { int totalItems; - var enumerable = this.ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, this.localJobs, out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, localJobs, out totalItems); if (sort == null || sort.Length == 0) { @@ -289,7 +289,7 @@ public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeF } else { - enumerable = ApplySorting(sort, enumerable, this.JobOrderByMapping); + enumerable = ApplySorting(sort, enumerable, JobOrderByMapping); } return new PagedResult @@ -303,68 +303,68 @@ public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeF public Job GetJobById(long id) { - return this.localJobs.FirstOrDefault(j => j.Id == id).Clone(); + return localJobs.FirstOrDefault(j => j.Id == id).Clone(); } public Job GetJobByUniqueName(string identifier) { - return this.localJobs.FirstOrDefault(j => string.Equals(j.UniqueName, identifier, StringComparison.OrdinalIgnoreCase)).Clone(); + return localJobs.FirstOrDefault(j => string.Equals(j.UniqueName, identifier, StringComparison.OrdinalIgnoreCase)).Clone(); } public JobRun GetJobRunById(long id) { - return this.localJobRuns.FirstOrDefault(j => j.Id == id).Clone(); + return localJobRuns.FirstOrDefault(j => j.Id == id).Clone(); } public void AddJob(Job job) { - var maxJobId = this.localJobs.Count + 1; + var maxJobId = localJobs.Count + 1; job.Id = maxJobId; - this.localJobs.Add(job); + localJobs.Add(job); } public void AddTrigger(long jobId, RecurringTrigger trigger) { - var newTriggerId = this.localTriggers.Count + 1; + var newTriggerId = localTriggers.Count + 1; trigger.Id = newTriggerId; trigger.JobId = jobId; - this.localTriggers.Add(trigger); + localTriggers.Add(trigger); } public void AddTrigger(long jobId, InstantTrigger trigger) { - var newTriggerId = this.localTriggers.Count + 1; + var newTriggerId = localTriggers.Count + 1; trigger.Id = newTriggerId; trigger.JobId = jobId; - this.localTriggers.Add(trigger); + localTriggers.Add(trigger); } public void AddTrigger(long jobId, ScheduledTrigger trigger) { - var newTriggerId = this.localTriggers.Count + 1; + var newTriggerId = localTriggers.Count + 1; trigger.Id = newTriggerId; trigger.JobId = jobId; - this.localTriggers.Add(trigger); + localTriggers.Add(trigger); } public void AddJobRun(JobRun jobRun) { - var maxJobRunId = this.localJobRuns.Count + 1; + var maxJobRunId = localJobRuns.Count + 1; jobRun.Id = maxJobRunId; - this.localJobRuns.Add(jobRun); + localJobRuns.Add(jobRun); } public void DisableTrigger(long jobId, long triggerId) { - var trigger = this.localTriggers.Single(t => t.Id == triggerId); + var trigger = localTriggers.Single(t => t.Id == triggerId); trigger.IsActive = false; } public void EnableTrigger(long jobId, long triggerId) { - var trigger = this.localTriggers.Single(t => t.Id == triggerId); + var trigger = localTriggers.Single(t => t.Id == triggerId); trigger.IsActive = true; } @@ -380,13 +380,13 @@ public void DeleteJob(long jobId) public void Update(JobRun jobRun) { - this.localJobRuns.Remove(this.localJobRuns.FirstOrDefault(jr => jr.Id == jobRun.Id)); - this.localJobRuns.Add(jobRun); + localJobRuns.Remove(localJobRuns.FirstOrDefault(jr => jr.Id == jobRun.Id)); + localJobRuns.Add(jobRun); } public void UpdateProgress(long jobRunId, double? progress) { - var jobRun = this.localJobRuns.First(p => p.Id == jobRunId); + var jobRun = localJobRuns.First(p => p.Id == jobRunId); jobRun.Progress = progress; } @@ -397,26 +397,26 @@ public void ApplyRetention(DateTimeOffset date) public void Update(Job job) { - this.localJobs.Remove(this.localJobs.FirstOrDefault(j => j.Id == job.Id)); - this.localJobs.Add(job); + localJobs.Remove(localJobs.FirstOrDefault(j => j.Id == job.Id)); + localJobs.Add(job); } public void Update(long jobId, InstantTrigger trigger) { - this.localTriggers.Remove(this.localTriggers.FirstOrDefault(j => j.Id == trigger.Id)); - this.localTriggers.Add(trigger); + localTriggers.Remove(localTriggers.FirstOrDefault(j => j.Id == trigger.Id)); + localTriggers.Add(trigger); } public void Update(long jobId, ScheduledTrigger trigger) { - this.localTriggers.Remove(this.localTriggers.FirstOrDefault(j => j.Id == trigger.Id)); - this.localTriggers.Add(trigger); + localTriggers.Remove(localTriggers.FirstOrDefault(j => j.Id == trigger.Id)); + localTriggers.Add(trigger); } public void Update(long jobId, RecurringTrigger trigger) { - this.localTriggers.Remove(this.localTriggers.FirstOrDefault(j => j.Id == trigger.Id)); - this.localTriggers.Add(trigger); + localTriggers.Remove(localTriggers.FirstOrDefault(j => j.Id == trigger.Id)); + localTriggers.Add(trigger); } public bool IsAvailable() @@ -428,14 +428,14 @@ public bool IsAvailable() public long GetJobsCount() #pragma warning restore CA1024 // Use properties where appropriate. { - return this.localJobs.Count; + return localJobs.Count; } private IEnumerable ApplyFiltersAndPaging(int page, int pageSize, string jobTypeFilter, string jobUniqueNameFilter, string query, IEnumerable enumerable, out int totalItems) { if (string.IsNullOrWhiteSpace(jobTypeFilter) == false) { - var jobs = this.localJobs.Where(p => string.Equals(p.Type, jobTypeFilter, StringComparison.OrdinalIgnoreCase)); + var jobs = localJobs.Where(p => string.Equals(p.Type, jobTypeFilter, StringComparison.OrdinalIgnoreCase)); var jobIds = jobs.Select(s => s.Id).ToList(); enumerable = enumerable.Where(p => jobIds.Contains(p.JobId)); @@ -443,7 +443,7 @@ private IEnumerable ApplyFiltersAndPaging(int page, int pageSize if (string.IsNullOrWhiteSpace(jobUniqueNameFilter) == false) { - var jobs = this.localJobs.Where(p => string.Equals(p.UniqueName, jobTypeFilter, StringComparison.OrdinalIgnoreCase)); + var jobs = localJobs.Where(p => string.Equals(p.UniqueName, jobTypeFilter, StringComparison.OrdinalIgnoreCase)); var jobIds = jobs.Select(s => s.Id).ToList(); enumerable = enumerable.Where(p => jobIds.Contains(p.JobId)); @@ -464,8 +464,6 @@ private IEnumerable ApplyFiltersAndPaging(int page, int pageSize private IEnumerable ApplyFiltersAndPaging(int page, int pageSize, string jobTypeFilter, string jobUniqueNameFilter, string query, IEnumerable enumerable, out int totalItems) { - - if (string.IsNullOrWhiteSpace(jobTypeFilter) == false) { enumerable = enumerable.Where(p => string.Equals(p.Type, jobTypeFilter, StringComparison.OrdinalIgnoreCase)); @@ -549,7 +547,7 @@ private static IEnumerable ApplySorting(string[] sort, IEnumerable enum } else { - var orderedEnumerable = (IOrderedEnumerable) enumerable; + var orderedEnumerable = (IOrderedEnumerable)enumerable; if (@ascending) { diff --git a/source/submodules/devsupport b/source/submodules/devsupport index 3ce9da3..a48352c 160000 --- a/source/submodules/devsupport +++ b/source/submodules/devsupport @@ -1 +1 @@ -Subproject commit 3ce9da3c883806c720117d2372ce9d3b678bc71a +Subproject commit a48352cdc76fcdb0b6426fe62e1ee30d3efee7de From b05fd26eadf480e9e5c317193a8718c048eb82b8 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Wed, 4 Jan 2023 14:39:10 +0100 Subject: [PATCH 26/41] Update namings to fit the style rules --- ...ChannelTests.cs => ProgressUpdateTests.cs} | 62 +++++----- .../Scheduler/ManualTimeProvider.cs | 12 +- .../Components/Scheduler/PeriodicTimerMock.cs | 6 +- .../Components/Scheduler/PlanningTests.cs | 36 +++--- .../Infrastructure/Extensions.cs | 28 ++--- .../FaultyJobStorageProvider.cs | 76 ++++++------ .../Execution/ProgressChannelTests.cs | 20 +-- .../Integration/JobRunEnumMappingTests.cs | 37 +++--- .../Integration/JobbrServerTestBase.cs | 10 +- .../Management/ServerManagementService.cs | 8 +- .../Scheduling/FixedMinuteTimer.cs | 14 +-- .../Storage/InMemoryArtefactsStorage.cs | 12 +- .../Storage/InMemoryJobStorageProvider.cs | 114 +++++++++--------- 13 files changed, 217 insertions(+), 218 deletions(-) rename source/Jobbr.Server.IntegrationTests/Components/JobRunService/{ProgressChannelTests.cs => ProgressUpdateTests.cs} (62%) diff --git a/source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressChannelTests.cs b/source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressUpdateTests.cs similarity index 62% rename from source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressChannelTests.cs rename to source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressUpdateTests.cs index 9bd89e9..3653767 100644 --- a/source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressChannelTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressUpdateTests.cs @@ -13,34 +13,19 @@ namespace Jobbr.Server.IntegrationTests.Components.JobRunService [TestClass] public class ProgressUpdateTests { - private readonly Server.Core.JobRunService service; - private readonly JobbrRepository repo; - private readonly TinyMessengerHub messengerHub; + private readonly Server.Core.JobRunService _service; + private readonly JobbrRepository _repo; + private readonly TinyMessengerHub _messengerHub; public ProgressUpdateTests() { var autoMapperConfig = new AutoMapperConfigurationFactory(new NullLoggerFactory()).GetNew(); - repo = new JobbrRepository(new NullLoggerFactory(), new InMemoryJobStorageProvider()); + _repo = new JobbrRepository(new NullLoggerFactory(), new InMemoryJobStorageProvider()); - messengerHub = new TinyMessengerHub(); + _messengerHub = new TinyMessengerHub(); - service = new Server.Core.JobRunService(new NullLoggerFactory(), messengerHub, repo, null, autoMapperConfig.CreateMapper()); - } - - private JobRun GivenAJobRun() - { - var job1 = new Job(); - repo.AddJob(job1); - - var trigger = new InstantTrigger - { - JobId = job1.Id, - IsActive = true - }; - - var jobrun = repo.SaveNewJobRun(job1, trigger, DateTime.UtcNow); - return jobrun; + _service = new Server.Core.JobRunService(new NullLoggerFactory(), _messengerHub, _repo, null, autoMapperConfig.CreateMapper()); } [TestMethod] @@ -48,9 +33,9 @@ public void JobRun_HasStarted_StartDateTimeIsStored() { var jobrun = GivenAJobRun(); - service.UpdateState(jobrun.Id, JobRunStates.Started); + _service.UpdateState(jobrun.Id, JobRunStates.Started); - var fromRepo = repo.GetJobRunById(jobrun.Id); + var fromRepo = _repo.GetJobRunById(jobrun.Id); Assert.IsNotNull(fromRepo.ActualStartDateTimeUtc); } @@ -60,8 +45,8 @@ public void JobRun_HasCompleted_EndDateTimeIsStored() { var jobrun = GivenAJobRun(); - service.UpdateState(jobrun.Id, JobRunStates.Completed); - var fromRepo = repo.GetJobRunById(jobrun.Id); + _service.UpdateState(jobrun.Id, JobRunStates.Completed); + var fromRepo = _repo.GetJobRunById(jobrun.Id); Assert.IsNotNull(fromRepo.ActualEndDateTimeUtc); } @@ -71,8 +56,8 @@ public void JobRun_HasFailed_EndDateTimeIsStored() { var jobrun = GivenAJobRun(); - service.UpdateState(jobrun.Id, JobRunStates.Failed); - var fromRepo = repo.GetJobRunById(jobrun.Id); + _service.UpdateState(jobrun.Id, JobRunStates.Failed); + var fromRepo = _repo.GetJobRunById(jobrun.Id); Assert.IsNotNull(fromRepo.ActualEndDateTimeUtc); } @@ -84,9 +69,9 @@ public void JobRun_HasCompleted_MessageIsIssued() JobRunCompletedMessage message = null; // Register for message - messengerHub.Subscribe(m => message = m); + _messengerHub.Subscribe(m => message = m); - service.UpdateState(jobrun.Id, JobRunStates.Completed); + _service.UpdateState(jobrun.Id, JobRunStates.Completed); Assert.IsNotNull(message); } @@ -98,11 +83,26 @@ public void JobRun_HasFailed_MessageIsIssued() JobRunCompletedMessage message = null; // Register for message - messengerHub.Subscribe(m => message = m); + _messengerHub.Subscribe(m => message = m); - service.UpdateState(jobrun.Id, JobRunStates.Failed); + _service.UpdateState(jobrun.Id, JobRunStates.Failed); Assert.IsNotNull(message); } + + private JobRun GivenAJobRun() + { + var job1 = new Job(); + _repo.AddJob(job1); + + var trigger = new InstantTrigger + { + JobId = job1.Id, + IsActive = true + }; + + var jobrun = _repo.SaveNewJobRun(job1, trigger, DateTime.UtcNow); + return jobrun; + } } } diff --git a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/ManualTimeProvider.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/ManualTimeProvider.cs index cd0601a..b1b6f10 100644 --- a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/ManualTimeProvider.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/ManualTimeProvider.cs @@ -5,31 +5,31 @@ namespace Jobbr.Server.IntegrationTests.Components.Scheduler { public class ManualTimeProvider : IDateTimeProvider { - private DateTime currentTime; + private DateTime _currentTime; public ManualTimeProvider() { - currentTime = DateTime.UtcNow; + _currentTime = DateTime.UtcNow; } public DateTime GetUtcNow() { - return currentTime; + return _currentTime; } public void AddMinute() { - currentTime = currentTime.AddMinutes(1); + _currentTime = _currentTime.AddMinutes(1); } public void AddSecond() { - currentTime = currentTime.AddSeconds(1); + _currentTime = _currentTime.AddSeconds(1); } public void Set(DateTime dateTimeUtc) { - currentTime = dateTimeUtc; + _currentTime = dateTimeUtc; } } } \ No newline at end of file diff --git a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PeriodicTimerMock.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PeriodicTimerMock.cs index c8ecc6a..6a61647 100644 --- a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PeriodicTimerMock.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PeriodicTimerMock.cs @@ -5,11 +5,11 @@ namespace Jobbr.Server.IntegrationTests.Components.Scheduler { public class PeriodicTimerMock : IPeriodicTimer { - private Action callback; + private Action _callback; public void Setup(Action value) { - callback = value; + _callback = value; } public void Start() @@ -22,7 +22,7 @@ public void Stop() public void CallbackOnce() { - callback(); + _callback(); } } } \ No newline at end of file diff --git a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PlanningTests.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PlanningTests.cs index 149b99a..25095ee 100644 --- a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PlanningTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PlanningTests.cs @@ -14,24 +14,6 @@ public PlanningTests() scheduler.Start(); } - private void AddAndSignalNewTrigger(long jobId, InstantTrigger trigger) - { - repository.SaveAddTrigger(jobId, trigger); - scheduler.OnTriggerAdded(jobId, trigger.Id); - } - - private void AddAndSignalNewTrigger(long jobId, ScheduledTrigger trigger) - { - repository.SaveAddTrigger(jobId, trigger); - scheduler.OnTriggerAdded(jobId, trigger.Id); - } - - private void AddAndSignalNewTrigger(long jobId, RecurringTrigger trigger) - { - repository.SaveAddTrigger(jobId, trigger); - scheduler.OnTriggerAdded(jobId, trigger.Id); - } - [TestMethod] public void NewScheduledTrigger_IsAdded_WillBePlanned() { @@ -399,5 +381,23 @@ public void RecurringTrigger_StartAndEndDateCoversNow_DoesNotTriggerRun() Assert.AreEqual(1, jobRuns.Items.Count, "The trigger should cause a job run because its valid right now"); } + + private void AddAndSignalNewTrigger(long jobId, InstantTrigger trigger) + { + repository.SaveAddTrigger(jobId, trigger); + scheduler.OnTriggerAdded(jobId, trigger.Id); + } + + private void AddAndSignalNewTrigger(long jobId, ScheduledTrigger trigger) + { + repository.SaveAddTrigger(jobId, trigger); + scheduler.OnTriggerAdded(jobId, trigger.Id); + } + + private void AddAndSignalNewTrigger(long jobId, RecurringTrigger trigger) + { + repository.SaveAddTrigger(jobId, trigger); + scheduler.OnTriggerAdded(jobId, trigger.Id); + } } } diff --git a/source/Jobbr.Server.IntegrationTests/Infrastructure/Extensions.cs b/source/Jobbr.Server.IntegrationTests/Infrastructure/Extensions.cs index 92e18ab..fd26846 100644 --- a/source/Jobbr.Server.IntegrationTests/Infrastructure/Extensions.cs +++ b/source/Jobbr.Server.IntegrationTests/Infrastructure/Extensions.cs @@ -3,23 +3,23 @@ namespace Jobbr.Server.IntegrationTests.Infrastructure { - public static class ExtensionMethods + public static class Extensions + { + // Deep clone + public static T Clone(this T a) { - // Deep clone - public static T Clone(this T a) + if (a == null) { - if (a == null) - { - return default(T); - } + return default; + } - using (MemoryStream stream = new MemoryStream()) - { - BinaryFormatter formatter = new BinaryFormatter(); - formatter.Serialize(stream, a); - stream.Position = 0; - return (T)formatter.Deserialize(stream); - } + using (MemoryStream stream = new MemoryStream()) + { + BinaryFormatter formatter = new BinaryFormatter(); + formatter.Serialize(stream, a); + stream.Position = 0; + return (T)formatter.Deserialize(stream); } + } } } diff --git a/source/Jobbr.Server.IntegrationTests/Infrastructure/FaultyJobStorageProvider.cs b/source/Jobbr.Server.IntegrationTests/Infrastructure/FaultyJobStorageProvider.cs index 2d4fd7f..bd1df63 100644 --- a/source/Jobbr.Server.IntegrationTests/Infrastructure/FaultyJobStorageProvider.cs +++ b/source/Jobbr.Server.IntegrationTests/Infrastructure/FaultyJobStorageProvider.cs @@ -8,17 +8,17 @@ namespace Jobbr.Server.IntegrationTests.Infrastructure { public class FaultyJobStorageProvider : IJobStorageProvider { - public static FaultyJobStorageProvider Instance { get; private set; } - - private readonly IJobStorageProvider inMemoryVersion = new InMemoryJobStorageProvider(); + private readonly IJobStorageProvider _inMemoryVersion = new InMemoryJobStorageProvider(); - private bool failAll; + private bool _failAll; public FaultyJobStorageProvider() { Instance = this; } + public static FaultyJobStorageProvider Instance { get; private set; } + public void DeleteJob(long jobId) { throw new NotImplementedException(); @@ -27,139 +27,139 @@ public void DeleteJob(long jobId) public long GetJobsCount() { CheckFailAll(); - return inMemoryVersion.GetJobsCount(); + return _inMemoryVersion.GetJobsCount(); } public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { CheckFailAll(); - return inMemoryVersion.GetJobs(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); + return _inMemoryVersion.GetJobs(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); } public void AddJob(Job job) { CheckFailAll(); - inMemoryVersion.AddJob(job); + _inMemoryVersion.AddJob(job); } public PagedResult GetTriggersByJobId(long jobId, int page = 1, int pageSize = 50, bool showDeleted = false) { CheckFailAll(); - return inMemoryVersion.GetTriggersByJobId(jobId); + return _inMemoryVersion.GetTriggersByJobId(jobId); } public PagedResult GetActiveTriggers(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, params string[] sort) { CheckFailAll(); - return inMemoryVersion.GetActiveTriggers(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, sort); + return _inMemoryVersion.GetActiveTriggers(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, sort); } public void AddTrigger(long jobId, RecurringTrigger trigger) { CheckFailAll(); - inMemoryVersion.AddTrigger(jobId, trigger); + _inMemoryVersion.AddTrigger(jobId, trigger); } public void AddTrigger(long jobId, InstantTrigger trigger) { CheckFailAll(); - inMemoryVersion.AddTrigger(jobId, trigger); + _inMemoryVersion.AddTrigger(jobId, trigger); } public void AddTrigger(long jobId, ScheduledTrigger trigger) { CheckFailAll(); - inMemoryVersion.AddTrigger(jobId, trigger); + _inMemoryVersion.AddTrigger(jobId, trigger); } public void DisableTrigger(long jobId, long triggerId) { CheckFailAll(); - inMemoryVersion.DisableTrigger(jobId, triggerId); + _inMemoryVersion.DisableTrigger(jobId, triggerId); } public void EnableTrigger(long jobId, long triggerId) { CheckFailAll(); - inMemoryVersion.EnableTrigger(jobId, triggerId); + _inMemoryVersion.EnableTrigger(jobId, triggerId); } public void DeleteTrigger(long jobId, long triggerId) { CheckFailAll(); - inMemoryVersion.DeleteTrigger(jobId, triggerId); + _inMemoryVersion.DeleteTrigger(jobId, triggerId); } public JobTriggerBase GetTriggerById(long jobId, long triggerId) { CheckFailAll(); - return inMemoryVersion.GetTriggerById(jobId, triggerId); + return _inMemoryVersion.GetTriggerById(jobId, triggerId); } public JobRun GetLastJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { CheckFailAll(); - return inMemoryVersion.GetLastJobRunByTriggerId(jobId, triggerId, utcNow); + return _inMemoryVersion.GetLastJobRunByTriggerId(jobId, triggerId, utcNow); } public JobRun GetNextJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { CheckFailAll(); - return inMemoryVersion.GetNextJobRunByTriggerId(jobId, triggerId, utcNow); + return _inMemoryVersion.GetNextJobRunByTriggerId(jobId, triggerId, utcNow); } public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) { CheckFailAll(); - return inMemoryVersion.GetJobRunsByTriggerId(jobId, triggerId, page, pageSize, showDeleted, sort); + return _inMemoryVersion.GetJobRunsByTriggerId(jobId, triggerId, page, pageSize, showDeleted, sort); } public PagedResult GetJobRunsByState(JobRunStates state, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { CheckFailAll(); - return inMemoryVersion.GetJobRunsByState(state, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); + return _inMemoryVersion.GetJobRunsByState(state, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); } public PagedResult GetJobRunsByStates(JobRunStates[] states, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { CheckFailAll(); - return inMemoryVersion.GetJobRunsByStates(states, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); + return _inMemoryVersion.GetJobRunsByStates(states, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); } public PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) { CheckFailAll(); - return inMemoryVersion.GetJobRunsByJobId(jobId, page, pageSize, showDeleted, sort); + return _inMemoryVersion.GetJobRunsByJobId(jobId, page, pageSize, showDeleted, sort); } public PagedResult GetJobRunsByUserId(string userId, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) { CheckFailAll(); - return inMemoryVersion.GetJobRunsByUserId(userId, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); + return _inMemoryVersion.GetJobRunsByUserId(userId, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); } public PagedResult GetJobRunsByUserDisplayName(string userDisplayName, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) { CheckFailAll(); - return inMemoryVersion.GetJobRunsByUserDisplayName(userDisplayName, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); + return _inMemoryVersion.GetJobRunsByUserDisplayName(userDisplayName, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); } public void AddJobRun(JobRun jobRun) { CheckFailAll(); - inMemoryVersion.AddJobRun(jobRun); + _inMemoryVersion.AddJobRun(jobRun); } public PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { CheckFailAll(); - return inMemoryVersion.GetJobRuns(); + return _inMemoryVersion.GetJobRuns(); } public void UpdateProgress(long jobRunId, double? progress) { CheckFailAll(); - inMemoryVersion.UpdateProgress(jobRunId, progress); + _inMemoryVersion.UpdateProgress(jobRunId, progress); } public void ApplyRetention(DateTimeOffset date) @@ -170,64 +170,64 @@ public void ApplyRetention(DateTimeOffset date) public void Update(JobRun jobRun) { CheckFailAll(); - inMemoryVersion.Update(jobRun); + _inMemoryVersion.Update(jobRun); } public Job GetJobById(long id) { CheckFailAll(); - return inMemoryVersion.GetJobById(id); + return _inMemoryVersion.GetJobById(id); } public Job GetJobByUniqueName(string identifier) { CheckFailAll(); - return inMemoryVersion.GetJobByUniqueName(identifier); + return _inMemoryVersion.GetJobByUniqueName(identifier); } public JobRun GetJobRunById(long id) { CheckFailAll(); - return inMemoryVersion.GetJobRunById(id); + return _inMemoryVersion.GetJobRunById(id); } public void Update(Job job) { CheckFailAll(); - inMemoryVersion.Update(job); + _inMemoryVersion.Update(job); } public void Update(long jobId, InstantTrigger trigger) { CheckFailAll(); - inMemoryVersion.Update(jobId, trigger); + _inMemoryVersion.Update(jobId, trigger); } public void Update(long jobId, ScheduledTrigger trigger) { CheckFailAll(); - inMemoryVersion.Update(jobId, trigger); + _inMemoryVersion.Update(jobId, trigger); } public void Update(long jobId, RecurringTrigger trigger) { CheckFailAll(); - inMemoryVersion.Update(jobId, trigger); + _inMemoryVersion.Update(jobId, trigger); } public void DisableImplementation() { - failAll = true; + _failAll = true; } public void EnableImplementation() { - failAll = false; + _failAll = false; } private void CheckFailAll() { - if (failAll) + if (_failAll) { throw new TargetException("This JobStorageProvider is currently not healthy!"); } diff --git a/source/Jobbr.Server.IntegrationTests/Integration/Execution/ProgressChannelTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Execution/ProgressChannelTests.cs index 9cf3812..743942a 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/Execution/ProgressChannelTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Execution/ProgressChannelTests.cs @@ -8,20 +8,20 @@ namespace Jobbr.Server.IntegrationTests.Integration.Execution [TestClass] public class ProgressChannelTests : JobRunExecutionTestBase { - private readonly JobRun currentRun; + private readonly JobRun _currentRun; public ProgressChannelTests() { var job = CreateTestJob(); var trigger = CreateInstantTrigger(job); - currentRun = TriggerNewJobRun(trigger); + _currentRun = TriggerNewJobRun(trigger); } [TestMethod] public void Infrastructure_TriggeredJobIsReady() { - Assert.IsNotNull(currentRun); + Assert.IsNotNull(_currentRun); } [TestMethod] @@ -29,9 +29,9 @@ public void ProgressUpdate_With50Percent_IsStored() { var progressService = Services.ProgressChannel; - progressService.PublishProgressUpdate(currentRun.Id, 50); + progressService.PublishProgressUpdate(_currentRun.Id, 50); - var jobRunFromDb = Services.JobStorageProvider.GetJobRunsByTriggerId(currentRun.Job.Id, currentRun.Trigger.Id).Items.Single(); + var jobRunFromDb = Services.JobStorageProvider.GetJobRunsByTriggerId(_currentRun.Job.Id, _currentRun.Trigger.Id).Items.Single(); Assert.AreEqual(50, jobRunFromDb.Progress); } @@ -41,9 +41,9 @@ public void PublishPid_WithRandomInt_IsStored() { var progressService = Services.ProgressChannel; - progressService.PublishPid(currentRun.Id, 42373, "host01"); + progressService.PublishPid(_currentRun.Id, 42373, "host01"); - var jobRunFromDb = Services.JobStorageProvider.GetJobRunsByTriggerId(currentRun.Job.Id, currentRun.Trigger.Id).Items.Single(); + var jobRunFromDb = Services.JobStorageProvider.GetJobRunsByTriggerId(_currentRun.Job.Id, _currentRun.Trigger.Id).Items.Single(); Assert.AreEqual(42373, jobRunFromDb.Pid); } @@ -83,7 +83,7 @@ public void StateUpdate_GetsStarted_StartDateIsUpdated() { SimulateStateUpdate(JobRunStates.Started); - var actualJobRun = Services.JobStorageProvider.GetJobRunsByTriggerId(currentRun.Job.Id, currentRun.Trigger.Id).Items.Single(); + var actualJobRun = Services.JobStorageProvider.GetJobRunsByTriggerId(_currentRun.Job.Id, _currentRun.Trigger.Id).Items.Single(); Assert.IsNotNull(actualJobRun.ActualStartDateTimeUtc); } @@ -163,14 +163,14 @@ public void StateUpdate_GetsFailed_IsStored() private ComponentModel.JobStorage.Model.JobRunStates GetActualStoredJobRunState() { - return Services.JobStorageProvider.GetJobRunsByTriggerId(currentRun.Job.Id, currentRun.Trigger.Id).Items.Single().State; + return Services.JobStorageProvider.GetJobRunsByTriggerId(_currentRun.Job.Id, _currentRun.Trigger.Id).Items.Single().State; } private void SimulateStateUpdate(JobRunStates state) { var progressService = Services.ProgressChannel; - progressService.PublishStatusUpdate(currentRun.Id, state); + progressService.PublishStatusUpdate(_currentRun.Id, state); } } } diff --git a/source/Jobbr.Server.IntegrationTests/Integration/JobRunEnumMappingTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/JobRunEnumMappingTests.cs index c09b18b..7c2cced 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/JobRunEnumMappingTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/JobRunEnumMappingTests.cs @@ -13,10 +13,9 @@ namespace Jobbr.Server.IntegrationTests.Integration [TestClass] public class JobRunEnumMappingTests { - private readonly IEnumerable allComponentModelJobRunEnumTypes; - private readonly Type coreType; - - private readonly Func enumTypeMatcher = t => t.Namespace != null && t.IsEnum && t.Namespace.Contains("ComponentModel") && t.Name.Contains("JobRun"); + private readonly IEnumerable _allComponentModelJobRunEnumTypes; + private readonly Type _coreType; + private readonly Func _enumTypeMatcher = t => t.Namespace != null && t.IsEnum && t.Namespace.Contains("ComponentModel") && t.Name.Contains("JobRun"); public JobRunEnumMappingTests() { @@ -26,14 +25,14 @@ public JobRunEnumMappingTests() Assembly.Load(assemblyName); } - allComponentModelJobRunEnumTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(asm => asm.GetTypes().Where(enumTypeMatcher)); - coreType = typeof(Server.Core.Models.JobRunStates); + _allComponentModelJobRunEnumTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(asm => asm.GetTypes().Where(_enumTypeMatcher)); + _coreType = typeof(Server.Core.Models.JobRunStates); } [TestMethod] public void InfrastructureTest_GetComponentModelJobRunEnumTypes_HasSome() { - Assert.IsTrue(allComponentModelJobRunEnumTypes.Any(), "There should be some JobRun Enum Types in the Component Models"); + Assert.IsTrue(_allComponentModelJobRunEnumTypes.Any(), "There should be some JobRun Enum Types in the Component Models"); } [TestMethod] @@ -41,14 +40,14 @@ public void CoreRunStateNames_IfExistInComponentModels_NameHasSameValue() { var errors = new List(); - foreach (var componentModelEnumType in allComponentModelJobRunEnumTypes) + foreach (var componentModelEnumType in _allComponentModelJobRunEnumTypes) { - var differences = FindDifferentValues(coreType, componentModelEnumType); + var differences = FindDifferentValues(_coreType, componentModelEnumType); errors.AddRange(differences); } - Assert.AreEqual(0, errors.Count, $"Found different values while comparing core model enum '{coreType}' with component models\n\n" + string.Join("\n", errors)); + Assert.AreEqual(0, errors.Count, $"Found different values while comparing core model enum '{_coreType}' with component models\n\n" + string.Join("\n", errors)); } [TestMethod] @@ -56,14 +55,14 @@ public void ComponentModelRunStateNames_IfExistInCore_NameHasSameValue() { var errors = new List(); - foreach (var componentModelEnumType in allComponentModelJobRunEnumTypes) + foreach (var componentModelEnumType in _allComponentModelJobRunEnumTypes) { - var differences = FindDifferentValues(componentModelEnumType, coreType); + var differences = FindDifferentValues(componentModelEnumType, _coreType); errors.AddRange(differences); } - Assert.AreEqual(0, errors.Count, $"Found different values for same enum names while comparing all component model with '{coreType}'\n\n" + string.Join("\n", errors)); + Assert.AreEqual(0, errors.Count, $"Found different values for same enum names while comparing all component model with '{_coreType}'\n\n" + string.Join("\n", errors)); } [TestMethod] @@ -71,9 +70,9 @@ public void ComponentModelRunStateNames_ComparedToAllComponentModels_HaveSameVal { var errors = new List(); - foreach (var master in allComponentModelJobRunEnumTypes) + foreach (var master in _allComponentModelJobRunEnumTypes) { - foreach (var target in allComponentModelJobRunEnumTypes) + foreach (var target in _allComponentModelJobRunEnumTypes) { var differences = FindDifferentValues(master, target); errors.AddRange(differences); @@ -86,11 +85,11 @@ public void ComponentModelRunStateNames_ComparedToAllComponentModels_HaveSameVal [TestMethod] public void CoreRunStateNames_ForAllComponentModel_ShouldBeKnown() { - var masterMembers = Enum.GetNames(coreType); + var masterMembers = Enum.GetNames(_coreType); var errors = new List(); - foreach (var cmEnumType in allComponentModelJobRunEnumTypes) + foreach (var cmEnumType in _allComponentModelJobRunEnumTypes) { var notFound = masterMembers.Except(Enum.GetNames(cmEnumType)); @@ -103,11 +102,11 @@ public void CoreRunStateNames_ForAllComponentModel_ShouldBeKnown() [TestMethod] public void ComponentModelStateNames_ComparedToCore_ShouldBeKnown() { - var masterMembers = Enum.GetNames(coreType); + var masterMembers = Enum.GetNames(_coreType); var errors = new List(); - foreach (var cmEnumType in allComponentModelJobRunEnumTypes) + foreach (var cmEnumType in _allComponentModelJobRunEnumTypes) { var notFound = Enum.GetNames(cmEnumType).Except(masterMembers); diff --git a/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs b/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs index a7cc02e..7f5ccfb 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs @@ -9,25 +9,25 @@ namespace Jobbr.Server.IntegrationTests.Integration { public abstract class JobbrServerTestBase { - private readonly JobbrServer jobbrServer; + private readonly JobbrServer _jobbrServer; protected JobbrServerTestBase(Func creator) { - jobbrServer = creator(); + _jobbrServer = creator(); } protected ExposeAllServicesComponent Services => ExposeAllServicesComponent.Instance; protected JobbrServer JobbrServer { - get { return jobbrServer; } + get { return _jobbrServer; } } [TestCleanup] public void CleanUp() { - jobbrServer?.Stop(); - jobbrServer?.Dispose(); + _jobbrServer?.Stop(); + _jobbrServer?.Dispose(); } [TestMethod] diff --git a/source/Jobbr.Server/ComponentServices/Management/ServerManagementService.cs b/source/Jobbr.Server/ComponentServices/Management/ServerManagementService.cs index c39ceff..0a29cfb 100644 --- a/source/Jobbr.Server/ComponentServices/Management/ServerManagementService.cs +++ b/source/Jobbr.Server/ComponentServices/Management/ServerManagementService.cs @@ -6,12 +6,12 @@ namespace Jobbr.Server.ComponentServices.Management { public class ServerManagementService : IServerManagementService { - public void Shutdown() - { - } - public int MaxConcurrentJobs { get; set; } public DateTime StartTime => Process.GetCurrentProcess().StartTime.ToUniversalTime(); + + public void Shutdown() + { + } } } diff --git a/source/Jobbr.Server/Scheduling/FixedMinuteTimer.cs b/source/Jobbr.Server/Scheduling/FixedMinuteTimer.cs index d05b962..d008dfe 100644 --- a/source/Jobbr.Server/Scheduling/FixedMinuteTimer.cs +++ b/source/Jobbr.Server/Scheduling/FixedMinuteTimer.cs @@ -5,13 +5,13 @@ namespace Jobbr.Server.Scheduling { internal class FixedMinuteTimer : IPeriodicTimer, IDisposable { - private Timer timer; + private Timer _timer; private Action callback; public FixedMinuteTimer() { - timer = new Timer(state => callback()); + _timer = new Timer(state => callback()); } public void Setup(Action value) @@ -21,12 +21,12 @@ public void Setup(Action value) public void Start() { - timer.Change(TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); + _timer.Change(TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); } public void Stop() { - timer.Change(int.MaxValue, int.MaxValue); + _timer.Change(int.MaxValue, int.MaxValue); } public void Dispose() @@ -39,10 +39,10 @@ protected virtual void Dispose(bool isDisposing) { if (isDisposing) { - if (timer != null) + if (_timer != null) { - timer.Dispose(); - timer = null; + _timer.Dispose(); + _timer = null; } } } diff --git a/source/Jobbr.Server/Storage/InMemoryArtefactsStorage.cs b/source/Jobbr.Server/Storage/InMemoryArtefactsStorage.cs index 7dbc2b5..e2a2f52 100644 --- a/source/Jobbr.Server/Storage/InMemoryArtefactsStorage.cs +++ b/source/Jobbr.Server/Storage/InMemoryArtefactsStorage.cs @@ -9,16 +9,16 @@ namespace Jobbr.Server.Storage { public class InMemoryArtefactsStorage : IArtefactsStorageProvider { - private readonly IDictionary> files = new Dictionary>(); + private readonly IDictionary> _files = new Dictionary>(); public void Save(string container, string fileName, Stream content) { - if (files.ContainsKey(container) == false) + if (_files.ContainsKey(container) == false) { - files.Add(container, new List()); + _files.Add(container, new List()); } - var list = files[container]; + var list = _files[container]; var memoryStream = new MemoryStream(); @@ -58,12 +58,12 @@ public List GetArtefacts(string container) private IEnumerable GetFilesFromContainer(string container) { - if (files.ContainsKey(container) == false) + if (_files.ContainsKey(container) == false) { throw new ArgumentException("Container not found"); } - return files[container]; + return _files[container]; } private class InMemoryFile diff --git a/source/Jobbr.Server/Storage/InMemoryJobStorageProvider.cs b/source/Jobbr.Server/Storage/InMemoryJobStorageProvider.cs index ed30c59..9c55205 100644 --- a/source/Jobbr.Server/Storage/InMemoryJobStorageProvider.cs +++ b/source/Jobbr.Server/Storage/InMemoryJobStorageProvider.cs @@ -9,7 +9,7 @@ namespace Jobbr.Server.Storage { public class InMemoryJobStorageProvider : IJobStorageProvider { - private readonly IDictionary>> TriggerOrderByMapping = new Dictionary>> + private readonly IDictionary>> _triggerOrderByMapping = new Dictionary>> { { nameof(JobTriggerBase.UserDisplayName), e => e.UserDisplayName }, { nameof(JobTriggerBase.UserId), e => e.UserId }, @@ -20,7 +20,7 @@ public class InMemoryJobStorageProvider : IJobStorageProvider { nameof(JobTriggerBase.CreatedDateTimeUtc), e => e.CreatedDateTimeUtc } }; - private readonly IDictionary>> JobOrderByMapping = new Dictionary>> + private readonly IDictionary>> _jobOrderByMapping = new Dictionary>> { { nameof(Job.Id), e => e.Id }, { nameof(Job.Title), e => e.Title }, @@ -30,7 +30,7 @@ public class InMemoryJobStorageProvider : IJobStorageProvider { nameof(Job.UpdatedDateTimeUtc), e => e.UpdatedDateTimeUtc } }; - private readonly IDictionary>> JobRunOrderByMapping = new Dictionary>> + private readonly IDictionary>> _jobRunOrderByMapping = new Dictionary>> { { nameof(JobRun.Id), e => e.Id }, { nameof(JobRun.ActualStartDateTimeUtc), e => e.ActualStartDateTimeUtc }, @@ -41,15 +41,15 @@ public class InMemoryJobStorageProvider : IJobStorageProvider { nameof(JobRun.EstimatedEndDateTimeUtc), e => e.EstimatedEndDateTimeUtc } }; - private readonly List localTriggers = new List(); + private readonly List _localTriggers = new List(); - private readonly List localJobs = new List(); + private readonly List _localJobs = new List(); - private readonly List localJobRuns = new List(); + private readonly List _localJobRuns = new List(); public PagedResult GetTriggersByJobId(long jobId, int page = 1, int pageSize = 50, bool showDeleted = false) { - var enumerable = localTriggers.Where(t => t.JobId == jobId); + var enumerable = _localTriggers.Where(t => t.JobId == jobId); int totalItems; @@ -68,7 +68,7 @@ public PagedResult GetTriggersByJobId(long jobId, int page = 1, public PagedResult GetActiveTriggers(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, params string[] sort) { - var enumerable = localTriggers.Where(t => t.IsActive); + var enumerable = _localTriggers.Where(t => t.IsActive); int totalItems; @@ -80,7 +80,7 @@ public PagedResult GetActiveTriggers(int page = 1, int pageSize } else { - enumerable = ApplySorting(sort, enumerable, TriggerOrderByMapping); + enumerable = ApplySorting(sort, enumerable, _triggerOrderByMapping); } var list = enumerable.ToList().Clone(); @@ -98,7 +98,7 @@ public PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jo { int totalItems; - var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, localJobRuns, out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, _localJobRuns, out totalItems); if (sort == null || sort.Length == 0) { @@ -106,7 +106,7 @@ public PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jo } else { - enumerable = ApplySorting(sort, enumerable, JobRunOrderByMapping); + enumerable = ApplySorting(sort, enumerable, _jobRunOrderByMapping); } return new PagedResult @@ -122,7 +122,7 @@ public PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSi { int totalItems; - var enumerable = ApplyFiltersAndPaging(page, pageSize, null, null, null, localJobRuns, out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, null, null, null, _localJobRuns, out totalItems); if (sort == null || sort.Length == 0) { @@ -130,7 +130,7 @@ public PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSi } else { - enumerable = ApplySorting(sort, enumerable, JobRunOrderByMapping); + enumerable = ApplySorting(sort, enumerable, _jobRunOrderByMapping); } return new PagedResult @@ -146,7 +146,7 @@ public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int { int totalItems; - var enumerable = ApplyFiltersAndPaging(page, pageSize, null, null, null, localJobRuns.Where(p => p.Trigger.Id == triggerId), out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, null, null, null, _localJobRuns.Where(p => p.Trigger.Id == triggerId), out totalItems); if (sort == null || sort.Length == 0) { @@ -154,7 +154,7 @@ public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int } else { - enumerable = ApplySorting(sort, enumerable, JobRunOrderByMapping); + enumerable = ApplySorting(sort, enumerable, _jobRunOrderByMapping); } return new PagedResult @@ -168,24 +168,24 @@ public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int public JobTriggerBase GetTriggerById(long jobId, long triggerId) { - return localTriggers.FirstOrDefault(t => t.Id == triggerId).Clone(); + return _localTriggers.FirstOrDefault(t => t.Id == triggerId).Clone(); } public JobRun GetLastJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { - return localJobRuns.FirstOrDefault(jr => jr.Trigger.Id == triggerId && jr.ActualEndDateTimeUtc < utcNow).Clone(); + return _localJobRuns.FirstOrDefault(jr => jr.Trigger.Id == triggerId && jr.ActualEndDateTimeUtc < utcNow).Clone(); } public JobRun GetNextJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { - return localJobRuns.FirstOrDefault(jr => jr.Trigger.Id == triggerId && jr.PlannedStartDateTimeUtc >= utcNow).Clone(); + return _localJobRuns.FirstOrDefault(jr => jr.Trigger.Id == triggerId && jr.PlannedStartDateTimeUtc >= utcNow).Clone(); } public PagedResult GetJobRunsByState(JobRunStates state, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { int totalItems; - var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, localJobRuns.Where(p => p.State == state), out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, _localJobRuns.Where(p => p.State == state), out totalItems); if (sort == null || sort.Length == 0) { @@ -193,7 +193,7 @@ public PagedResult GetJobRunsByState(JobRunStates state, int page = 1, i } else { - enumerable = ApplySorting(sort, enumerable, JobRunOrderByMapping); + enumerable = ApplySorting(sort, enumerable, _jobRunOrderByMapping); } return new PagedResult @@ -209,7 +209,7 @@ public PagedResult GetJobRunsByStates(JobRunStates[] states, int page = { int totalItems; - var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, localJobRuns.Where(p => states.Contains(p.State)), out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, _localJobRuns.Where(p => states.Contains(p.State)), out totalItems); if (sort == null || sort.Length == 0) { @@ -217,7 +217,7 @@ public PagedResult GetJobRunsByStates(JobRunStates[] states, int page = } else { - enumerable = ApplySorting(sort, enumerable, JobRunOrderByMapping); + enumerable = ApplySorting(sort, enumerable, _jobRunOrderByMapping); } return new PagedResult @@ -233,7 +233,7 @@ public PagedResult GetJobRunsByUserId(string userId, int page = 1, int p { int totalItems; - var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, null, localJobRuns.Where(p => string.Equals(p.Trigger.UserId, userId, StringComparison.OrdinalIgnoreCase)), out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, null, _localJobRuns.Where(p => string.Equals(p.Trigger.UserId, userId, StringComparison.OrdinalIgnoreCase)), out totalItems); if (sort == null || sort.Length == 0) { @@ -241,7 +241,7 @@ public PagedResult GetJobRunsByUserId(string userId, int page = 1, int p } else { - enumerable = ApplySorting(sort, enumerable, JobRunOrderByMapping); + enumerable = ApplySorting(sort, enumerable, _jobRunOrderByMapping); } return new PagedResult @@ -257,7 +257,7 @@ public PagedResult GetJobRunsByUserDisplayName(string userDisplayName, i { int totalItems; - var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, null, localJobRuns.Where(p => string.Equals(p.Trigger.UserDisplayName, userDisplayName, StringComparison.OrdinalIgnoreCase)), out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, null, _localJobRuns.Where(p => string.Equals(p.Trigger.UserDisplayName, userDisplayName, StringComparison.OrdinalIgnoreCase)), out totalItems); if (sort == null || sort.Length == 0) { @@ -265,7 +265,7 @@ public PagedResult GetJobRunsByUserDisplayName(string userDisplayName, i } else { - enumerable = ApplySorting(sort, enumerable, JobRunOrderByMapping); + enumerable = ApplySorting(sort, enumerable, _jobRunOrderByMapping); } return new PagedResult @@ -281,7 +281,7 @@ public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeF { int totalItems; - var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, localJobs, out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, _localJobs, out totalItems); if (sort == null || sort.Length == 0) { @@ -289,7 +289,7 @@ public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeF } else { - enumerable = ApplySorting(sort, enumerable, JobOrderByMapping); + enumerable = ApplySorting(sort, enumerable, _jobOrderByMapping); } return new PagedResult @@ -303,68 +303,68 @@ public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeF public Job GetJobById(long id) { - return localJobs.FirstOrDefault(j => j.Id == id).Clone(); + return _localJobs.FirstOrDefault(j => j.Id == id).Clone(); } public Job GetJobByUniqueName(string identifier) { - return localJobs.FirstOrDefault(j => string.Equals(j.UniqueName, identifier, StringComparison.OrdinalIgnoreCase)).Clone(); + return _localJobs.FirstOrDefault(j => string.Equals(j.UniqueName, identifier, StringComparison.OrdinalIgnoreCase)).Clone(); } public JobRun GetJobRunById(long id) { - return localJobRuns.FirstOrDefault(j => j.Id == id).Clone(); + return _localJobRuns.FirstOrDefault(j => j.Id == id).Clone(); } public void AddJob(Job job) { - var maxJobId = localJobs.Count + 1; + var maxJobId = _localJobs.Count + 1; job.Id = maxJobId; - localJobs.Add(job); + _localJobs.Add(job); } public void AddTrigger(long jobId, RecurringTrigger trigger) { - var newTriggerId = localTriggers.Count + 1; + var newTriggerId = _localTriggers.Count + 1; trigger.Id = newTriggerId; trigger.JobId = jobId; - localTriggers.Add(trigger); + _localTriggers.Add(trigger); } public void AddTrigger(long jobId, InstantTrigger trigger) { - var newTriggerId = localTriggers.Count + 1; + var newTriggerId = _localTriggers.Count + 1; trigger.Id = newTriggerId; trigger.JobId = jobId; - localTriggers.Add(trigger); + _localTriggers.Add(trigger); } public void AddTrigger(long jobId, ScheduledTrigger trigger) { - var newTriggerId = localTriggers.Count + 1; + var newTriggerId = _localTriggers.Count + 1; trigger.Id = newTriggerId; trigger.JobId = jobId; - localTriggers.Add(trigger); + _localTriggers.Add(trigger); } public void AddJobRun(JobRun jobRun) { - var maxJobRunId = localJobRuns.Count + 1; + var maxJobRunId = _localJobRuns.Count + 1; jobRun.Id = maxJobRunId; - localJobRuns.Add(jobRun); + _localJobRuns.Add(jobRun); } public void DisableTrigger(long jobId, long triggerId) { - var trigger = localTriggers.Single(t => t.Id == triggerId); + var trigger = _localTriggers.Single(t => t.Id == triggerId); trigger.IsActive = false; } public void EnableTrigger(long jobId, long triggerId) { - var trigger = localTriggers.Single(t => t.Id == triggerId); + var trigger = _localTriggers.Single(t => t.Id == triggerId); trigger.IsActive = true; } @@ -380,13 +380,13 @@ public void DeleteJob(long jobId) public void Update(JobRun jobRun) { - localJobRuns.Remove(localJobRuns.FirstOrDefault(jr => jr.Id == jobRun.Id)); - localJobRuns.Add(jobRun); + _localJobRuns.Remove(_localJobRuns.FirstOrDefault(jr => jr.Id == jobRun.Id)); + _localJobRuns.Add(jobRun); } public void UpdateProgress(long jobRunId, double? progress) { - var jobRun = localJobRuns.First(p => p.Id == jobRunId); + var jobRun = _localJobRuns.First(p => p.Id == jobRunId); jobRun.Progress = progress; } @@ -397,26 +397,26 @@ public void ApplyRetention(DateTimeOffset date) public void Update(Job job) { - localJobs.Remove(localJobs.FirstOrDefault(j => j.Id == job.Id)); - localJobs.Add(job); + _localJobs.Remove(_localJobs.FirstOrDefault(j => j.Id == job.Id)); + _localJobs.Add(job); } public void Update(long jobId, InstantTrigger trigger) { - localTriggers.Remove(localTriggers.FirstOrDefault(j => j.Id == trigger.Id)); - localTriggers.Add(trigger); + _localTriggers.Remove(_localTriggers.FirstOrDefault(j => j.Id == trigger.Id)); + _localTriggers.Add(trigger); } public void Update(long jobId, ScheduledTrigger trigger) { - localTriggers.Remove(localTriggers.FirstOrDefault(j => j.Id == trigger.Id)); - localTriggers.Add(trigger); + _localTriggers.Remove(_localTriggers.FirstOrDefault(j => j.Id == trigger.Id)); + _localTriggers.Add(trigger); } public void Update(long jobId, RecurringTrigger trigger) { - localTriggers.Remove(localTriggers.FirstOrDefault(j => j.Id == trigger.Id)); - localTriggers.Add(trigger); + _localTriggers.Remove(_localTriggers.FirstOrDefault(j => j.Id == trigger.Id)); + _localTriggers.Add(trigger); } public bool IsAvailable() @@ -428,14 +428,14 @@ public bool IsAvailable() public long GetJobsCount() #pragma warning restore CA1024 // Use properties where appropriate. { - return localJobs.Count; + return _localJobs.Count; } private IEnumerable ApplyFiltersAndPaging(int page, int pageSize, string jobTypeFilter, string jobUniqueNameFilter, string query, IEnumerable enumerable, out int totalItems) { if (string.IsNullOrWhiteSpace(jobTypeFilter) == false) { - var jobs = localJobs.Where(p => string.Equals(p.Type, jobTypeFilter, StringComparison.OrdinalIgnoreCase)); + var jobs = _localJobs.Where(p => string.Equals(p.Type, jobTypeFilter, StringComparison.OrdinalIgnoreCase)); var jobIds = jobs.Select(s => s.Id).ToList(); enumerable = enumerable.Where(p => jobIds.Contains(p.JobId)); @@ -443,7 +443,7 @@ private IEnumerable ApplyFiltersAndPaging(int page, int pageSize if (string.IsNullOrWhiteSpace(jobUniqueNameFilter) == false) { - var jobs = localJobs.Where(p => string.Equals(p.UniqueName, jobTypeFilter, StringComparison.OrdinalIgnoreCase)); + var jobs = _localJobs.Where(p => string.Equals(p.UniqueName, jobTypeFilter, StringComparison.OrdinalIgnoreCase)); var jobIds = jobs.Select(s => s.Id).ToList(); enumerable = enumerable.Where(p => jobIds.Contains(p.JobId)); From 96acc109c8775b54d3be1c460ee27e56625f6179 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Fri, 6 Jan 2023 16:16:54 +0100 Subject: [PATCH 27/41] Comment most public methods --- .../FaultyJobStorageProvider.cs | 10 +- .../Integration/ExposeAllServicesComponent.cs | 10 +- .../InitializedJobbrServerTestBase.cs | 9 + .../Integration/JobbrServerTestBase.cs | 28 +- .../Integration/RunningJobbrServerTestBase.cs | 9 + source/Jobbr.Server/Builder/NoExecutor.cs | 20 ++ .../Execution/MappingProfile.cs | 6 + .../Management/JobManagementService.cs | 85 ++++++ .../Management/JobQueryService.cs | 148 ++++++++++ .../Management/ServerManagementService.cs | 12 + source/Jobbr.Server/Core/IJobService.cs | 3 + .../Core/Messaging/JobRunCompletedMessage.cs | 16 +- .../Core/Messaging/TriggerAddedMessage.cs | 17 +- .../Jobbr.Server/Core/Messaging/TriggerKey.cs | 9 + .../Messaging/TriggerStateChangedMessage.cs | 17 +- .../Core/Messaging/TriggerUpdatedMessage.cs | 17 +- .../Core/Models/JobArtefactModel.cs | 12 + source/Jobbr.Server/Core/Models/JobModel.cs | 30 ++ .../Jobbr.Server/Core/Models/JobRunStates.cs | 3 + .../Models/ModelToStorageMappingProfile.cs | 7 +- .../Models/StorageToModelMappingProfile.cs | 6 + .../Extensions/AssemblyExtensions.cs | 11 +- .../JobRegistry/TriggerExtensions.cs | 9 + source/Jobbr.Server/JobbrServer.cs | 10 +- source/Jobbr.Server/JobbrState.cs | 3 + .../Scheduling/BuilderExtension.cs | 14 +- .../Scheduling/DefaultScheduler.cs | 22 ++ .../DefaultSchedulerConfiguration.cs | 3 + .../Scheduling/FixedMinuteTimer.cs | 21 +- .../Scheduling/IDateTimeProvider.cs | 7 + .../Jobbr.Server/Scheduling/IJobScheduler.cs | 28 ++ .../Jobbr.Server/Scheduling/IPeriodicTimer.cs | 13 + .../Scheduling/MaxConcurrentJobRunPlaner.cs | 15 +- .../Scheduling/Planer/PlanAction.cs | 3 + .../Scheduling/Planer/PlanResult.cs | 20 +- .../Scheduling/ScheduledPlanItem.cs | 15 + .../Scheduling/UtcNowTimeProvider.cs | 4 + .../Jobbr.Server/Storage/ExtensionMethods.cs | 12 +- .../Jobbr.Server/Storage/IJobbrRepository.cs | 235 +++++++++++++++ .../Storage/InMemoryArtefactsStorage.cs | 21 ++ .../Storage/InMemoryJobStorageProvider.cs | 268 ++++++++++++++++-- .../Jobbr.Server/Storage/JobbrRepository.cs | 42 +++ 42 files changed, 1159 insertions(+), 91 deletions(-) create mode 100644 source/Jobbr.Server.IntegrationTests/Integration/InitializedJobbrServerTestBase.cs create mode 100644 source/Jobbr.Server.IntegrationTests/Integration/RunningJobbrServerTestBase.cs diff --git a/source/Jobbr.Server.IntegrationTests/Infrastructure/FaultyJobStorageProvider.cs b/source/Jobbr.Server.IntegrationTests/Infrastructure/FaultyJobStorageProvider.cs index bd1df63..f3d3e55 100644 --- a/source/Jobbr.Server.IntegrationTests/Infrastructure/FaultyJobStorageProvider.cs +++ b/source/Jobbr.Server.IntegrationTests/Infrastructure/FaultyJobStorageProvider.cs @@ -225,6 +225,11 @@ public void EnableImplementation() _failAll = false; } + public bool IsAvailable() + { + return true; + } + private void CheckFailAll() { if (_failAll) @@ -232,10 +237,5 @@ private void CheckFailAll() throw new TargetException("This JobStorageProvider is currently not healthy!"); } } - - public bool IsAvailable() - { - return true; - } } } \ No newline at end of file diff --git a/source/Jobbr.Server.IntegrationTests/Integration/ExposeAllServicesComponent.cs b/source/Jobbr.Server.IntegrationTests/Integration/ExposeAllServicesComponent.cs index 6db737b..19ae5ae 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/ExposeAllServicesComponent.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/ExposeAllServicesComponent.cs @@ -13,9 +13,7 @@ namespace Jobbr.Server.IntegrationTests.Integration /// public class ExposeAllServicesComponent : IJobbrComponent { - public static ExposeAllServicesComponent Instance => instancesPerThread.Value; - - private static ThreadLocal instancesPerThread = new ThreadLocal(); + private static readonly ThreadLocal InstancesPerThread = new (); public ExposeAllServicesComponent(IJobbrServiceProvider serviceProvider, IArtefactsStorageProvider artefactsStorageProvider, IJobStorageProvider jobStorageProvider, IJobManagementService jobManagementService, IQueryService queryService, IServerManagementService managementService, IJobRunInformationService informationService, IJobRunProgressChannel progressChannel) { @@ -28,9 +26,11 @@ public ExposeAllServicesComponent(IJobbrServiceProvider serviceProvider, IArtefa InformationService = informationService; ProgressChannel = progressChannel; - instancesPerThread.Value = this; + InstancesPerThread.Value = this; } + public static ExposeAllServicesComponent Instance => InstancesPerThread.Value; + public IJobbrServiceProvider ServiceProvider { get; } public IArtefactsStorageProvider ArtefactsStorageProvider { get; } @@ -49,7 +49,7 @@ public ExposeAllServicesComponent(IJobbrServiceProvider serviceProvider, IArtefa public void Dispose() { - instancesPerThread.Value = null; + InstancesPerThread.Value = null; } public void Start() diff --git a/source/Jobbr.Server.IntegrationTests/Integration/InitializedJobbrServerTestBase.cs b/source/Jobbr.Server.IntegrationTests/Integration/InitializedJobbrServerTestBase.cs new file mode 100644 index 0000000..c41aeb9 --- /dev/null +++ b/source/Jobbr.Server.IntegrationTests/Integration/InitializedJobbrServerTestBase.cs @@ -0,0 +1,9 @@ +namespace Jobbr.Server.IntegrationTests.Integration +{ + public class InitializedJobbrServerTestBase : JobbrServerTestBase + { + public InitializedJobbrServerTestBase() : base(GivenAServerInstance) + { + } + } +} \ No newline at end of file diff --git a/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs b/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs index 7f5ccfb..964d5ec 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs @@ -1,6 +1,5 @@ using System; using Jobbr.ComponentModel.Registration; -using Jobbr.Server; using Jobbr.Server.Builder; using Microsoft.Extensions.Logging.Abstractions; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -9,25 +8,20 @@ namespace Jobbr.Server.IntegrationTests.Integration { public abstract class JobbrServerTestBase { - private readonly JobbrServer _jobbrServer; - protected JobbrServerTestBase(Func creator) { - _jobbrServer = creator(); + JobbrServer = creator(); } protected ExposeAllServicesComponent Services => ExposeAllServicesComponent.Instance; - protected JobbrServer JobbrServer - { - get { return _jobbrServer; } - } + protected JobbrServer JobbrServer { get; } [TestCleanup] public void CleanUp() { - _jobbrServer?.Stop(); - _jobbrServer?.Dispose(); + JobbrServer?.Stop(); + JobbrServer?.Dispose(); } [TestMethod] @@ -54,18 +48,4 @@ protected static JobbrServer GivenAServerInstance() return server; } } - - public class RunningJobbrServerTestBase : JobbrServerTestBase - { - public RunningJobbrServerTestBase() : base(GivenAStartedServer) - { - } - } - - public class InitializedJobbrServerTestBase : JobbrServerTestBase - { - public InitializedJobbrServerTestBase() : base(GivenAServerInstance) - { - } - } } \ No newline at end of file diff --git a/source/Jobbr.Server.IntegrationTests/Integration/RunningJobbrServerTestBase.cs b/source/Jobbr.Server.IntegrationTests/Integration/RunningJobbrServerTestBase.cs new file mode 100644 index 0000000..a5350ae --- /dev/null +++ b/source/Jobbr.Server.IntegrationTests/Integration/RunningJobbrServerTestBase.cs @@ -0,0 +1,9 @@ +namespace Jobbr.Server.IntegrationTests.Integration +{ + public class RunningJobbrServerTestBase : JobbrServerTestBase + { + public RunningJobbrServerTestBase() : base(GivenAStartedServer) + { + } + } +} \ No newline at end of file diff --git a/source/Jobbr.Server/Builder/NoExecutor.cs b/source/Jobbr.Server/Builder/NoExecutor.cs index 1a9b1f8..fbe9496 100644 --- a/source/Jobbr.Server/Builder/NoExecutor.cs +++ b/source/Jobbr.Server/Builder/NoExecutor.cs @@ -4,24 +4,44 @@ namespace Jobbr.Server.Builder { + /// + /// Executor that does nothing. + /// public class NoExecutor : IJobExecutor { + /// + /// Does nothing. + /// public void Dispose() { } + /// + /// Does nothing. + /// public void Start() { } + /// + /// Does nothing. + /// public void Stop() { } + /// + /// Does nothing. + /// public void OnPlanChanged(List newPlan) { } + /// + /// Does nothing. + /// + /// Job ID. + /// Always return false. public bool OnJobRunCanceled(long id) { return false; diff --git a/source/Jobbr.Server/ComponentServices/Execution/MappingProfile.cs b/source/Jobbr.Server/ComponentServices/Execution/MappingProfile.cs index b885c87..0a15072 100644 --- a/source/Jobbr.Server/ComponentServices/Execution/MappingProfile.cs +++ b/source/Jobbr.Server/ComponentServices/Execution/MappingProfile.cs @@ -4,8 +4,14 @@ namespace Jobbr.Server.ComponentServices.Execution { + /// + /// AutoMapper mapping profile. + /// internal class MappingProfile : Profile { + /// + /// Initializes a new instance of the class. + /// public MappingProfile() { CreateMap() diff --git a/source/Jobbr.Server/ComponentServices/Management/JobManagementService.cs b/source/Jobbr.Server/ComponentServices/Management/JobManagementService.cs index 3e9e30f..b6241ef 100644 --- a/source/Jobbr.Server/ComponentServices/Management/JobManagementService.cs +++ b/source/Jobbr.Server/ComponentServices/Management/JobManagementService.cs @@ -20,6 +20,13 @@ internal class JobManagementService : IJobManagementService private readonly IMapper _mapper; + /// + /// Initializes a new instance of the class. + /// + /// Job trigger service. + /// Job service. + /// Job run service. + /// The mapper. public JobManagementService(ITriggerService triggerService, IJobService jobService, IJobRunService jobRunService, IMapper mapper) { _triggerService = triggerService; @@ -28,6 +35,10 @@ public JobManagementService(ITriggerService triggerService, IJobService jobServi _mapper = mapper; } + /// + /// Add new . + /// + /// to add. public void AddJob(Job job) { var model = _mapper.Map(job); @@ -36,6 +47,10 @@ public void AddJob(Job job) job.Id = newJOb.Id; } + /// + /// Update . + /// + /// to update. public void UpdateJob(Job job) { var model = _mapper.Map(job); @@ -43,6 +58,11 @@ public void UpdateJob(Job job) _jobService.Update(model); } + /// + /// Delete . Unimplemented. + /// + /// Target ID. + /// Throws always. public void DeleteJob(long jobId) { // TODO: implement :) @@ -50,6 +70,11 @@ public void DeleteJob(long jobId) throw new NotImplementedException(); } + /// + /// Add a recurring job trigger. + /// + /// Target ID. + /// The . public void AddTrigger(long jobId, RecurringTrigger trigger) { var model = _mapper.Map(trigger); @@ -60,6 +85,11 @@ public void AddTrigger(long jobId, RecurringTrigger trigger) trigger.JobId = jobId; } + /// + /// Add a scheduled job trigger. + /// + /// Target ID. + /// The . public void AddTrigger(long jobId, ScheduledTrigger trigger) { var model = _mapper.Map(trigger); @@ -70,6 +100,11 @@ public void AddTrigger(long jobId, ScheduledTrigger trigger) trigger.JobId = jobId; } + /// + /// Add an instant job trigger. + /// + /// Target ID. + /// The . public void AddTrigger(long jobId, InstantTrigger trigger) { var model = _mapper.Map(trigger); @@ -80,26 +115,51 @@ public void AddTrigger(long jobId, InstantTrigger trigger) trigger.JobId = jobId; } + /// + /// Disable job trigger. + /// + /// Target ID. + /// The trigger ID. public void DisableTrigger(long jobId, long triggerId) { _triggerService.Disable(jobId, triggerId); } + /// + /// Enable job trigger. + /// + /// Target ID. + /// The trigger ID. public void EnableTrigger(long jobId, long triggerId) { _triggerService.Enable(jobId, triggerId); } + /// + /// Delete job trigger. + /// + /// Target ID. + /// The trigger ID. public void DeleteTrigger(long jobId, long triggerId) { _triggerService.Delete(jobId, triggerId); } + /// + /// Update trigger definition. + /// + /// Target ID. + /// The trigger ID. + /// New definition. public void UpdateTriggerDefinition(long jobId, long triggerId, string definition) { _triggerService.Update(jobId, triggerId, definition); } + /// + /// Update . + /// + /// The target trigger. public void Update(RecurringTrigger trigger) { var triggerModel = _mapper.Map(trigger); @@ -107,6 +167,10 @@ public void Update(RecurringTrigger trigger) _triggerService.Update(triggerModel); } + /// + /// Update . + /// + /// The target trigger. public void Update(ScheduledTrigger trigger) { var triggerModel = _mapper.Map(trigger); @@ -114,16 +178,31 @@ public void Update(ScheduledTrigger trigger) _triggerService.Update(triggerModel); } + /// + /// Update trigger start time. + /// + /// The target job ID. + /// Target trigger ID. + /// The new start time in UTC. public void UpdateTriggerStartTime(long jobId, long triggerId, DateTime startDateTimeUtc) { _triggerService.Update(jobId, triggerId, startDateTimeUtc); } + /// + /// Delete job run. + /// + /// Target job run ID. public void DeleteJobRun(long jobRunId) { _jobRunService.Delete(jobRunId); } + /// + /// Get . + /// + /// Target job run ID. + /// List of s. public List GetArtefactForJob(long jobRunId) { var artefacts = _jobRunService.GetArtefactsByJobRunId(jobRunId); @@ -131,6 +210,12 @@ public List GetArtefactForJob(long jobRunId) return _mapper.Map>(artefacts); } + /// + /// Get job artifact as a stream. + /// + /// Target job run ID. + /// Filename. + /// A of the artifact. public Stream GetArtefactAsStream(long jobRunId, string filename) { return _jobRunService.GetArtefactAsStream(jobRunId, filename); diff --git a/source/Jobbr.Server/ComponentServices/Management/JobQueryService.cs b/source/Jobbr.Server/ComponentServices/Management/JobQueryService.cs index 4e704ea..17ff085 100644 --- a/source/Jobbr.Server/ComponentServices/Management/JobQueryService.cs +++ b/source/Jobbr.Server/ComponentServices/Management/JobQueryService.cs @@ -8,17 +8,30 @@ namespace Jobbr.Server.ComponentServices.Management { + /// + /// Internal class for querying job information. + /// internal class JobQueryService : IQueryService { private readonly IJobbrRepository _repository; private readonly IMapper _mapper; + /// + /// Initializes a new instance of the class. + /// + /// The Jobbr repository for querying. + /// Object mapper. public JobQueryService(IJobbrRepository repository, IMapper mapper) { _repository = repository; _mapper = mapper; } + /// + /// Get a by job ID. + /// + /// ID. + /// The target . public Job GetJobById(long id) { var job = _repository.GetJob(id); @@ -26,6 +39,11 @@ public Job GetJobById(long id) return _mapper.Map(job); } + /// + /// Get a by unique name. + /// + /// 's unique name. + /// The target . public Job GetJobByUniqueName(string uniqueName) { var job = _repository.GetJobByUniqueName(uniqueName); @@ -33,6 +51,17 @@ public Job GetJobByUniqueName(string uniqueName) return _mapper.Map(job); } + /// + /// Get a list of s. + /// + /// Page of s. + /// Page size. + /// type filter. + /// Unique name filter. + /// Search query. + /// If deleted jobs should be included. + /// Sort. + /// Paged result. public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { var jobs = _repository.GetJobs(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); @@ -46,6 +75,16 @@ public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeF }; } + /// + /// Get a list of s. + /// + /// Page of s. + /// Page size. + /// type filter. + /// Unique name filter. + /// Search query. + /// Sort. + /// Paged result. public PagedResult GetActiveTriggers(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, params string[] sort) { var triggers = _repository.GetActiveTriggers(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, sort); @@ -59,6 +98,12 @@ public PagedResult GetActiveTriggers(int page = 1, int pageSize = 5 }; } + /// + /// Get with job and trigger ID. + /// + /// ID. + /// Trigger ID. + /// Target . public IJobTrigger GetTriggerById(long jobId, long triggerId) { var trigger = _repository.GetTriggerById(jobId, triggerId); @@ -66,6 +111,14 @@ public IJobTrigger GetTriggerById(long jobId, long triggerId) return _mapper.Map(trigger); } + /// + /// Get a list of s with ID. + /// + /// ID. + /// Page of s. + /// Page size. + /// If deleted triggers are included. + /// Paged result. public PagedResult GetTriggersByJobId(long jobId, int page, int pageSize = 50, bool showDeleted = false) { var triggers = _repository.GetTriggersByJobId(jobId, page, pageSize, showDeleted); @@ -79,6 +132,11 @@ public PagedResult GetTriggersByJobId(long jobId, int page, int pag }; } + /// + /// Get by ID. + /// + /// ID. + /// Target . public JobRun GetJobRunById(long id) { var jobRun = _repository.GetJobRunById(id); @@ -86,6 +144,17 @@ public JobRun GetJobRunById(long id) return _mapper.Map(jobRun); } + /// + /// Get a list of s based on parameters. + /// + /// Page number. + /// Page size. + /// Job type filter. + /// Filter for unique names. + /// Search query. + /// Show deleted s. + /// Sort. + /// Paged result of s. public PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { var jobruns = _repository.GetJobRuns(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); @@ -99,6 +168,15 @@ public PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jo }; } + /// + /// Get job runs by ID. + /// + /// ID. + /// Page number. + /// Page size. + /// If deleted job runs should be included. + /// Sort. + /// s as a paged result. public PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) { var jobruns = _repository.GetJobRunsByJobId(jobId, page, pageSize, showDeleted, sort); @@ -112,6 +190,17 @@ public PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSi }; } + /// + /// Get s by user ID. + /// + /// User ID. + /// Page number. + /// Page size. + /// Job type filter. + /// Job unique name filter. + /// Show deleted s. + /// Sort. + /// Paged result of s. public PagedResult GetJobRunsByUserId(string userId, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) { var jobruns = _repository.GetJobRunsByUserId(userId, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); @@ -125,6 +214,16 @@ public PagedResult GetJobRunsByUserId(string userId, int page = 1, int p }; } + /// + /// Get s by trigger ID. + /// + /// Job ID. + /// Trigger ID. + /// Page number. + /// Page size. + /// Show deleted s. + /// Sort. + /// s as a paged result. public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) { var jobruns = _repository.GetJobRunsByTriggerId(jobId, triggerId, page, pageSize, showDeleted, sort); @@ -138,6 +237,17 @@ public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int }; } + /// + /// Get s by user display name. + /// + /// User display name. + /// Page number. + /// Page size. + /// type filter. + /// unique name filter. + /// Show deleted s. + /// Sort. + /// s as a paged result. public PagedResult GetJobRunsByUserDisplayName(string userDisplayName, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) { var jobruns = _repository.GetJobRunsByUserDisplayName(userDisplayName, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); @@ -151,6 +261,18 @@ public PagedResult GetJobRunsByUserDisplayName(string userDisplayName, i }; } + /// + /// Get s by state. + /// + /// Job run state. + /// Page number. + /// Page size. + /// Job type filter. + /// Job unique name filter. + /// Search query. + /// If deleted s should be included. + /// Sort. + /// Paged result of s. public PagedResult GetJobRunsByState(JobRunStates state, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { var jobruns = _repository.GetJobRunsByState((ComponentModel.JobStorage.Model.JobRunStates)state, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); @@ -164,6 +286,18 @@ public PagedResult GetJobRunsByState(JobRunStates state, int page = 1, i }; } + /// + /// Get s by states. + /// + /// List of job run states. + /// Page number. + /// Page size. + /// Job type filter. + /// Job unique name filter. + /// Search query. + /// If deleted s should be included. + /// Sort. + /// Paged result of s. public PagedResult GetJobRunsByStates(JobRunStates[] states, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { var statesCast = states.Select(s => (ComponentModel.JobStorage.Model.JobRunStates)s).ToArray(); @@ -179,6 +313,13 @@ public PagedResult GetJobRunsByStates(JobRunStates[] states, int page = }; } + /// + /// Last by trigger ID. + /// + /// ID. + /// Trigger ID. + /// Timestamp in UTC. + /// Last with the trigger ID. public JobRun GetLastJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { var jobrun = _repository.GetLastJobRunByTriggerId(jobId, triggerId, utcNow); @@ -186,6 +327,13 @@ public JobRun GetLastJobRunByTriggerId(long jobId, long triggerId, DateTime utcN return _mapper.Map(jobrun); } + /// + /// Next by trigger ID. + /// + /// ID. + /// Trigger ID. + /// Timestamp in UTC. + /// Next with the trigger ID. public JobRun GetNextJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { var jobrun = _repository.GetNextJobRunByTriggerId(jobId, triggerId, utcNow); diff --git a/source/Jobbr.Server/ComponentServices/Management/ServerManagementService.cs b/source/Jobbr.Server/ComponentServices/Management/ServerManagementService.cs index 0a29cfb..70a0e22 100644 --- a/source/Jobbr.Server/ComponentServices/Management/ServerManagementService.cs +++ b/source/Jobbr.Server/ComponentServices/Management/ServerManagementService.cs @@ -4,12 +4,24 @@ namespace Jobbr.Server.ComponentServices.Management { + /// + /// Service for server management. + /// public class ServerManagementService : IServerManagementService { + /// + /// The current maximum concurrent jobs. + /// public int MaxConcurrentJobs { get; set; } + /// + /// The current server process start time as UTC. + /// public DateTime StartTime => Process.GetCurrentProcess().StartTime.ToUniversalTime(); + /// + /// Shutdown. Does nothing. + /// public void Shutdown() { } diff --git a/source/Jobbr.Server/Core/IJobService.cs b/source/Jobbr.Server/Core/IJobService.cs index a949460..91458a2 100644 --- a/source/Jobbr.Server/Core/IJobService.cs +++ b/source/Jobbr.Server/Core/IJobService.cs @@ -2,6 +2,9 @@ namespace Jobbr.Server.Core { + /// + /// Interface for services. + /// public interface IJobService { /// diff --git a/source/Jobbr.Server/Core/Messaging/JobRunCompletedMessage.cs b/source/Jobbr.Server/Core/Messaging/JobRunCompletedMessage.cs index f70eeb9..a70de3c 100644 --- a/source/Jobbr.Server/Core/Messaging/JobRunCompletedMessage.cs +++ b/source/Jobbr.Server/Core/Messaging/JobRunCompletedMessage.cs @@ -2,15 +2,27 @@ namespace Jobbr.Server.Core.Messaging { + /// + /// Message for a completed job run. + /// public class JobRunCompletedMessage : TinyMessageBase { - public JobRunCompletedMessage(object sender) - : base(sender) + /// + /// Initializes a new instance of the class. + /// + /// Message sender. + public JobRunCompletedMessage(object sender) : base(sender) { } + /// + /// Job run ID. + /// public long Id { get; set; } + /// + /// If job run was successful. + /// public bool IsSuccessful { get; set; } } } \ No newline at end of file diff --git a/source/Jobbr.Server/Core/Messaging/TriggerAddedMessage.cs b/source/Jobbr.Server/Core/Messaging/TriggerAddedMessage.cs index 06c1792..66ef008 100644 --- a/source/Jobbr.Server/Core/Messaging/TriggerAddedMessage.cs +++ b/source/Jobbr.Server/Core/Messaging/TriggerAddedMessage.cs @@ -2,15 +2,28 @@ namespace Jobbr.Server.Core.Messaging { + /// + /// TinyMessenger message class that is used when a job trigger is added. + /// internal class TriggerAddedMessage : GenericTinyMessage { - public TriggerAddedMessage(object sender, TriggerKey content) - : base(sender, content) + /// + /// Initializes a new instance of the class. + /// + /// Message sender. + /// Message content. + public TriggerAddedMessage(object sender, TriggerKey content) : base(sender, content) { } + /// + /// Job trigger ID. + /// public long TriggerId => Content.TriggerId; + /// + /// Job ID. + /// public long JobId => Content.JobId; } } \ No newline at end of file diff --git a/source/Jobbr.Server/Core/Messaging/TriggerKey.cs b/source/Jobbr.Server/Core/Messaging/TriggerKey.cs index 6bce7fc..99eac15 100644 --- a/source/Jobbr.Server/Core/Messaging/TriggerKey.cs +++ b/source/Jobbr.Server/Core/Messaging/TriggerKey.cs @@ -1,9 +1,18 @@ namespace Jobbr.Server.Core.Messaging { + /// + /// Trigger key for messaging. + /// internal class TriggerKey { + /// + /// Job ID. + /// public long JobId { get; set; } + /// + /// Trigger ID. + /// public long TriggerId { get; set; } } } \ No newline at end of file diff --git a/source/Jobbr.Server/Core/Messaging/TriggerStateChangedMessage.cs b/source/Jobbr.Server/Core/Messaging/TriggerStateChangedMessage.cs index d7aafb5..363a27d 100644 --- a/source/Jobbr.Server/Core/Messaging/TriggerStateChangedMessage.cs +++ b/source/Jobbr.Server/Core/Messaging/TriggerStateChangedMessage.cs @@ -2,15 +2,28 @@ namespace Jobbr.Server.Core.Messaging { + /// + /// Trigger state changed message. + /// internal class TriggerStateChangedMessage : GenericTinyMessage { - public TriggerStateChangedMessage(object sender, TriggerKey content) - : base(sender, content) + /// + /// Initializes a new instance of the class. + /// + /// The sender. + /// The trigger information for the message. + public TriggerStateChangedMessage(object sender, TriggerKey content) : base(sender, content) { } + /// + /// Job ID. + /// public long JobId => Content.JobId; + /// + /// Trigger ID. + /// public long TriggerId => Content.TriggerId; } } \ No newline at end of file diff --git a/source/Jobbr.Server/Core/Messaging/TriggerUpdatedMessage.cs b/source/Jobbr.Server/Core/Messaging/TriggerUpdatedMessage.cs index 3f5a9cb..d6d0b20 100644 --- a/source/Jobbr.Server/Core/Messaging/TriggerUpdatedMessage.cs +++ b/source/Jobbr.Server/Core/Messaging/TriggerUpdatedMessage.cs @@ -2,15 +2,28 @@ namespace Jobbr.Server.Core.Messaging { + /// + /// Trigger updated message. + /// internal class TriggerUpdatedMessage : GenericTinyMessage { - public TriggerUpdatedMessage(object sender, TriggerKey content) - : base(sender, content) + /// + /// Initializes a new instance of the class. + /// + /// Message sender. + /// The trigger information for the message. + public TriggerUpdatedMessage(object sender, TriggerKey content) : base(sender, content) { } + /// + /// Job ID. + /// public long JobId => Content.JobId; + /// + /// Trigger ID. + /// public long TriggerId => Content.TriggerId; } } \ No newline at end of file diff --git a/source/Jobbr.Server/Core/Models/JobArtefactModel.cs b/source/Jobbr.Server/Core/Models/JobArtefactModel.cs index 5c1b16f..ddce778 100644 --- a/source/Jobbr.Server/Core/Models/JobArtefactModel.cs +++ b/source/Jobbr.Server/Core/Models/JobArtefactModel.cs @@ -1,11 +1,23 @@ namespace Jobbr.Server.Core.Models { + /// + /// Model class for job artifacts. + /// public class JobArtefactModel { + /// + /// Artifact file name. + /// public string FileName { get; set; } + /// + /// MIME type. MIME is a two-part identifier for file formats. + /// public string MimeType { get; set; } + /// + /// Artifact size. + /// public long Size { get; set; } } } diff --git a/source/Jobbr.Server/Core/Models/JobModel.cs b/source/Jobbr.Server/Core/Models/JobModel.cs index d33675d..a7b6771 100644 --- a/source/Jobbr.Server/Core/Models/JobModel.cs +++ b/source/Jobbr.Server/Core/Models/JobModel.cs @@ -2,24 +2,54 @@ namespace Jobbr.Server.Core.Models { + /// + /// Model class for jobs. + /// public class JobModel { + /// + /// Job ID. + /// public long Id { get; set; } + /// + /// Unique name for the job. + /// public string UniqueName { get; set; } + /// + /// Title. + /// public string Title { get; set; } + /// + /// Parameters. + /// public string Parameters { get; set; } + /// + /// Type. + /// public string Type { get; set; } + /// + /// The last time the job information was updated in UTC. + /// public DateTime? UpdatedDateTimeUtc { get; set; } + /// + /// Creation time in UTC. + /// public DateTime? CreatedDateTimeUtc { get; set; } + /// + /// If job has been deleted. + /// public bool Deleted { get; set; } + /// + /// Maximum amount of concurrent job runs allowed. + /// public int MaxConcurrentJobRuns { get; set; } } } \ No newline at end of file diff --git a/source/Jobbr.Server/Core/Models/JobRunStates.cs b/source/Jobbr.Server/Core/Models/JobRunStates.cs index b9aa026..c35ef82 100644 --- a/source/Jobbr.Server/Core/Models/JobRunStates.cs +++ b/source/Jobbr.Server/Core/Models/JobRunStates.cs @@ -1,5 +1,8 @@ namespace Jobbr.Server.Core.Models { + /// + /// Run states for the job run. + /// public enum JobRunStates { /// diff --git a/source/Jobbr.Server/Core/Models/ModelToStorageMappingProfile.cs b/source/Jobbr.Server/Core/Models/ModelToStorageMappingProfile.cs index 5146a11..b5c972d 100644 --- a/source/Jobbr.Server/Core/Models/ModelToStorageMappingProfile.cs +++ b/source/Jobbr.Server/Core/Models/ModelToStorageMappingProfile.cs @@ -3,14 +3,19 @@ namespace Jobbr.Server.Core.Models { + /// + /// AutoMapper profile for model classes. + /// internal class ModelToStorageMappingProfile : Profile { + /// + /// Initializes a new instance of the class. + /// public ModelToStorageMappingProfile() { CreateMap(); CreateMap(); CreateMap(); - CreateMap(); } } diff --git a/source/Jobbr.Server/Core/Models/StorageToModelMappingProfile.cs b/source/Jobbr.Server/Core/Models/StorageToModelMappingProfile.cs index 3db7e1d..170515d 100644 --- a/source/Jobbr.Server/Core/Models/StorageToModelMappingProfile.cs +++ b/source/Jobbr.Server/Core/Models/StorageToModelMappingProfile.cs @@ -3,8 +3,14 @@ namespace Jobbr.Server.Core.Models { + /// + /// AutoMapper profile for artifacts. + /// internal class StorageToModelMappingProfile : Profile { + /// + /// Initializes a new instance of the class. + /// public StorageToModelMappingProfile() { CreateMap(); diff --git a/source/Jobbr.Server/Extensions/AssemblyExtensions.cs b/source/Jobbr.Server/Extensions/AssemblyExtensions.cs index 54fc011..bd7dee6 100644 --- a/source/Jobbr.Server/Extensions/AssemblyExtensions.cs +++ b/source/Jobbr.Server/Extensions/AssemblyExtensions.cs @@ -1,10 +1,17 @@ -using System; -using System.Reflection; +using System.Reflection; namespace Jobbr.Server.Extensions { + /// + /// Extension methods for . + /// public static class AssemblyExtensions { + /// + /// Get the version of the . + /// + /// Target . + /// Version. public static string GetVersion(this Assembly assembly) { var versionAttribute = assembly.GetCustomAttribute(); diff --git a/source/Jobbr.Server/JobRegistry/TriggerExtensions.cs b/source/Jobbr.Server/JobRegistry/TriggerExtensions.cs index e9e48fc..7ada33e 100644 --- a/source/Jobbr.Server/JobRegistry/TriggerExtensions.cs +++ b/source/Jobbr.Server/JobRegistry/TriggerExtensions.cs @@ -3,8 +3,17 @@ namespace Jobbr.Server.JobRegistry { + /// + /// Extension methods for job triggers. + /// public static class TriggerExtensions { + /// + /// Checks if two trigger instances are actually the same instance. + /// + /// Target trigger. + /// Comparison trigger. + /// Returns true if the instances are same and false if not. public static bool IsTriggerEqual(this JobTriggerBase trigger, JobTriggerBase other) { if (ReferenceEquals(trigger, other)) diff --git a/source/Jobbr.Server/JobbrServer.cs b/source/Jobbr.Server/JobbrServer.cs index 9322d8b..f50ef9f 100644 --- a/source/Jobbr.Server/JobbrServer.cs +++ b/source/Jobbr.Server/JobbrServer.cs @@ -31,11 +31,6 @@ public class JobbrServer : IDisposable private bool _isRunning; - /// - /// The state of the Jobbr server. - /// - public JobbrState State { get; private set; } - /// /// Initializes a new instance of the class. /// @@ -55,6 +50,11 @@ public JobbrServer(ILoggerFactory loggerFactory, IJobScheduler scheduler, IJobEx messageDispatcher.WireUp(); } + /// + /// The state of the Jobbr server. + /// + public JobbrState State { get; private set; } + /// /// Start the Jobbr server synchronously. /// diff --git a/source/Jobbr.Server/JobbrState.cs b/source/Jobbr.Server/JobbrState.cs index 433b10f..d2c8fd4 100644 --- a/source/Jobbr.Server/JobbrState.cs +++ b/source/Jobbr.Server/JobbrState.cs @@ -1,5 +1,8 @@ namespace Jobbr.Server { + /// + /// Jobbr execution state. + /// public enum JobbrState { Unknown = 0, diff --git a/source/Jobbr.Server/Scheduling/BuilderExtension.cs b/source/Jobbr.Server/Scheduling/BuilderExtension.cs index 206b29d..e5e594b 100644 --- a/source/Jobbr.Server/Scheduling/BuilderExtension.cs +++ b/source/Jobbr.Server/Scheduling/BuilderExtension.cs @@ -3,13 +3,25 @@ namespace Jobbr.Server.Scheduling { + /// + /// Extensions for . + /// internal static class BuilderExtension { + /// + /// Add a to the builder without configurations. + /// + /// Target builder. public static void AddDefaultScheduler(this IJobbrBuilder builder) { - AddDefaultScheduler(builder, configuration => { }); + AddDefaultScheduler(builder, _ => { }); } + /// + /// Add a to the builder with configurations. + /// + /// Target builder. + /// Configurations. public static void AddDefaultScheduler(this IJobbrBuilder builder, Action config) { var defaultConfig = new DefaultSchedulerConfiguration(); diff --git a/source/Jobbr.Server/Scheduling/DefaultScheduler.cs b/source/Jobbr.Server/Scheduling/DefaultScheduler.cs index b217188..3bb9813 100644 --- a/source/Jobbr.Server/Scheduling/DefaultScheduler.cs +++ b/source/Jobbr.Server/Scheduling/DefaultScheduler.cs @@ -9,6 +9,9 @@ namespace Jobbr.Server.Scheduling { + /// + /// Default job scheduler. + /// public class DefaultScheduler : IJobScheduler { private readonly ILogger _logger; @@ -24,6 +27,18 @@ public class DefaultScheduler : IJobScheduler private List _currentPlan = new (); + /// + /// Initializes a new instance of the class. + /// + /// The logger factory. + /// Jobbr repository. + /// Job executor. + /// Instant job run planner. + /// Scheduled job run planner. + /// Recurring job run planner. + /// Scheduler configuration. + /// Periodic timer. + /// DateTime provider. public DefaultScheduler(ILoggerFactory loggerFactory, IJobbrRepository jobbrRepository, IJobExecutor executor, IInstantJobRunPlaner instantJobRunPlanner, IScheduledJobRunPlaner scheduledJobRunPlanner, IRecurringJobRunPlaner recurringJobRunPlanner, DefaultSchedulerConfiguration schedulerConfiguration, IPeriodicTimer periodicTimer, IDateTimeProvider dateTimeProvider) { @@ -40,10 +55,12 @@ public DefaultScheduler(ILoggerFactory loggerFactory, IJobbrRepository jobbrRepo _periodicTimer.Setup(EvaluateRecurringTriggers); } + /// public void Dispose() { } + /// public void Start() { SetScheduledJobRunsFromPastToOmitted(); @@ -55,11 +72,13 @@ public void Start() _periodicTimer.Start(); } + /// public void Stop() { _periodicTimer.Stop(); } + /// public void OnTriggerDefinitionUpdated(long jobId, long triggerId) { lock (_evaluateTriggersLock) @@ -96,6 +115,7 @@ public void OnTriggerDefinitionUpdated(long jobId, long triggerId) } } + /// public void OnTriggerStateUpdated(long jobId, long triggerId) { lock (_evaluateTriggersLock) @@ -138,6 +158,7 @@ public void OnTriggerStateUpdated(long jobId, long triggerId) } } + /// public void OnTriggerAdded(long jobId, long triggerId) { lock (_evaluateTriggersLock) @@ -168,6 +189,7 @@ public void OnTriggerAdded(long jobId, long triggerId) } } + /// public void OnJobRunEnded(long id) { lock (_evaluateTriggersLock) diff --git a/source/Jobbr.Server/Scheduling/DefaultSchedulerConfiguration.cs b/source/Jobbr.Server/Scheduling/DefaultSchedulerConfiguration.cs index e9ecbc4..10d8791 100644 --- a/source/Jobbr.Server/Scheduling/DefaultSchedulerConfiguration.cs +++ b/source/Jobbr.Server/Scheduling/DefaultSchedulerConfiguration.cs @@ -2,6 +2,9 @@ namespace Jobbr.Server.Scheduling { + /// + /// Configuration for . + /// public class DefaultSchedulerConfiguration : IFeatureConfiguration { /// diff --git a/source/Jobbr.Server/Scheduling/FixedMinuteTimer.cs b/source/Jobbr.Server/Scheduling/FixedMinuteTimer.cs index d008dfe..5ae1fc6 100644 --- a/source/Jobbr.Server/Scheduling/FixedMinuteTimer.cs +++ b/source/Jobbr.Server/Scheduling/FixedMinuteTimer.cs @@ -3,38 +3,51 @@ namespace Jobbr.Server.Scheduling { + /// + /// Fixed minute timer. + /// internal class FixedMinuteTimer : IPeriodicTimer, IDisposable { private Timer _timer; + private Action _callback; - private Action callback; - + /// + /// Initializes a new instance of the class. + /// public FixedMinuteTimer() { - _timer = new Timer(state => callback()); + _timer = new Timer(_ => _callback()); } + /// public void Setup(Action value) { - callback = value; + _callback = value; } + /// public void Start() { _timer.Change(TimeSpan.FromMinutes(1), TimeSpan.FromMinutes(1)); } + /// public void Stop() { _timer.Change(int.MaxValue, int.MaxValue); } + /// public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } + /// + /// Conditional dispose. + /// + /// Dispose condition. protected virtual void Dispose(bool isDisposing) { if (isDisposing) diff --git a/source/Jobbr.Server/Scheduling/IDateTimeProvider.cs b/source/Jobbr.Server/Scheduling/IDateTimeProvider.cs index 726492f..4d8d5b8 100644 --- a/source/Jobbr.Server/Scheduling/IDateTimeProvider.cs +++ b/source/Jobbr.Server/Scheduling/IDateTimeProvider.cs @@ -2,8 +2,15 @@ namespace Jobbr.Server.Scheduling { + /// + /// DateTime provider. + /// public interface IDateTimeProvider { + /// + /// Get's current time in UTC. + /// + /// Current time in UTC. DateTime GetUtcNow(); } } \ No newline at end of file diff --git a/source/Jobbr.Server/Scheduling/IJobScheduler.cs b/source/Jobbr.Server/Scheduling/IJobScheduler.cs index d4d8d38..2f0c839 100644 --- a/source/Jobbr.Server/Scheduling/IJobScheduler.cs +++ b/source/Jobbr.Server/Scheduling/IJobScheduler.cs @@ -2,18 +2,46 @@ namespace Jobbr.Server.Scheduling { + /// + /// Interface for job schedulers. + /// public interface IJobScheduler : IDisposable { + /// + /// Start scheduler. + /// void Start(); + /// + /// Stop scheduler. + /// void Stop(); + /// + /// Event handler for updated trigger definitions. + /// + /// Job ID. + /// Trigger ID. void OnTriggerDefinitionUpdated(long jobId, long triggerId); + /// + /// Event handler for updated trigger states. + /// + /// Job ID. + /// Trigger ID. void OnTriggerStateUpdated(long jobId, long triggerId); + /// + /// Event handler for trigger adding events. + /// + /// Job ID. + /// Trigger ID. void OnTriggerAdded(long jobId, long triggerId); + /// + /// Event handler for job run end event. + /// + /// Job run ID. void OnJobRunEnded(long id); } } \ No newline at end of file diff --git a/source/Jobbr.Server/Scheduling/IPeriodicTimer.cs b/source/Jobbr.Server/Scheduling/IPeriodicTimer.cs index 28b91aa..15d2988 100644 --- a/source/Jobbr.Server/Scheduling/IPeriodicTimer.cs +++ b/source/Jobbr.Server/Scheduling/IPeriodicTimer.cs @@ -2,12 +2,25 @@ namespace Jobbr.Server.Scheduling { + /// + /// Interface for periodic timers. + /// public interface IPeriodicTimer { + /// + /// Setup timer. + /// + /// Timer event as . void Setup(Action value); + /// + /// Start timer. + /// void Start(); + /// + /// Stop timer. + /// void Stop(); } } \ No newline at end of file diff --git a/source/Jobbr.Server/Scheduling/MaxConcurrentJobRunPlaner.cs b/source/Jobbr.Server/Scheduling/MaxConcurrentJobRunPlaner.cs index f9c02f1..077ab6e 100644 --- a/source/Jobbr.Server/Scheduling/MaxConcurrentJobRunPlaner.cs +++ b/source/Jobbr.Server/Scheduling/MaxConcurrentJobRunPlaner.cs @@ -5,8 +5,17 @@ namespace Jobbr.Server.Scheduling { + /// + /// Maximum concurrent job runs planner. + /// internal static class MaxConcurrentJobRunPlaner { + /// + /// Get all the possible planned job runs. + /// + /// Current plan. + /// Jobbr repository. + /// List of all the possible planned job runs. public static List GetPossiblePlannedJobRuns(IList currentPlan, IJobbrRepository repository) { var possibleRunsPerJob = GetPossibleRunsPerJob(currentPlan, repository); @@ -16,8 +25,7 @@ public static List GetPossiblePlannedJobRuns(IList GetPossibleRunsPerJob(IEnumerable currentPlan, - IJobbrRepository repository) + private static Dictionary GetPossibleRunsPerJob(IEnumerable currentPlan, IJobbrRepository repository) { var allRunningJobIds = repository.GetRunningJobs().Select(j => j.Job.Id).ToList(); var allPlannedJobIds = currentPlan.Select(c => c.JobId).ToList(); @@ -40,8 +48,7 @@ private static Dictionary GetPossibleRunsPerJob(IEnumerable> GetOrderedScheduledPlanItems( - IEnumerable currentPlan) + private static Dictionary> GetOrderedScheduledPlanItems(IEnumerable currentPlan) { return (from item in currentPlan orderby item.PlannedStartDateTimeUtc diff --git a/source/Jobbr.Server/Scheduling/Planer/PlanAction.cs b/source/Jobbr.Server/Scheduling/Planer/PlanAction.cs index 385bc7f..d490d6a 100644 --- a/source/Jobbr.Server/Scheduling/Planer/PlanAction.cs +++ b/source/Jobbr.Server/Scheduling/Planer/PlanAction.cs @@ -1,5 +1,8 @@ namespace Jobbr.Server.Scheduling.Planer { + /// + /// Plan action. + /// internal enum PlanAction { Obsolete, diff --git a/source/Jobbr.Server/Scheduling/Planer/PlanResult.cs b/source/Jobbr.Server/Scheduling/Planer/PlanResult.cs index a6cccc5..d839368 100644 --- a/source/Jobbr.Server/Scheduling/Planer/PlanResult.cs +++ b/source/Jobbr.Server/Scheduling/Planer/PlanResult.cs @@ -2,14 +2,32 @@ namespace Jobbr.Server.Scheduling.Planer { + /// + /// The result of a plan. + /// public struct PlanResult { + /// + /// Plan action. + /// internal PlanAction Action; + + /// + /// Expected start date of the plan in UTC. + /// internal DateTime? ExpectedStartDateUtc; + /// + /// Creates a from a . + /// + /// Plan action to create the result from. + /// A created from the . internal static PlanResult FromAction(PlanAction action) { - return new PlanResult { Action = action }; + return new PlanResult + { + Action = action + }; } } } \ No newline at end of file diff --git a/source/Jobbr.Server/Scheduling/ScheduledPlanItem.cs b/source/Jobbr.Server/Scheduling/ScheduledPlanItem.cs index 21baaf7..d01f21c 100644 --- a/source/Jobbr.Server/Scheduling/ScheduledPlanItem.cs +++ b/source/Jobbr.Server/Scheduling/ScheduledPlanItem.cs @@ -2,14 +2,29 @@ namespace Jobbr.Server.Scheduling { + /// + /// Scheduled plan item. + /// internal class ScheduledPlanItem { + /// + /// Item ID. + /// public long Id { get; set; } + /// + /// Planned start timestamp. + /// public DateTime PlannedStartDateTimeUtc { get; set; } + /// + /// Trigger ID. + /// public long TriggerId { get; set; } + /// + /// Job ID. + /// public long JobId { get; set; } } } \ No newline at end of file diff --git a/source/Jobbr.Server/Scheduling/UtcNowTimeProvider.cs b/source/Jobbr.Server/Scheduling/UtcNowTimeProvider.cs index a4d0211..4b51a12 100644 --- a/source/Jobbr.Server/Scheduling/UtcNowTimeProvider.cs +++ b/source/Jobbr.Server/Scheduling/UtcNowTimeProvider.cs @@ -2,8 +2,12 @@ namespace Jobbr.Server.Scheduling { + /// + /// UTC time provider. + /// internal class UtcNowTimeProvider : IDateTimeProvider { + /// DateTime IDateTimeProvider.GetUtcNow() => DateTime.UtcNow; } } \ No newline at end of file diff --git a/source/Jobbr.Server/Storage/ExtensionMethods.cs b/source/Jobbr.Server/Storage/ExtensionMethods.cs index c6fdfbd..3d43d9e 100644 --- a/source/Jobbr.Server/Storage/ExtensionMethods.cs +++ b/source/Jobbr.Server/Storage/ExtensionMethods.cs @@ -3,14 +3,22 @@ namespace Jobbr.Server.Storage { + /// + /// Helper class for generic extension methods. + /// internal static class ExtensionMethods { - // Deep clone + /// + /// Deep clone an object. + /// + /// Object type. + /// Object instance. + /// A deep clone of the given object. public static T Clone(this T a) { if (a == null) { - return default(T); + return default; } using (MemoryStream stream = new MemoryStream()) diff --git a/source/Jobbr.Server/Storage/IJobbrRepository.cs b/source/Jobbr.Server/Storage/IJobbrRepository.cs index 4a79609..34c4b8b 100644 --- a/source/Jobbr.Server/Storage/IJobbrRepository.cs +++ b/source/Jobbr.Server/Storage/IJobbrRepository.cs @@ -5,74 +5,309 @@ namespace Jobbr.Server.Storage { + /// + /// Jobbr repository. + /// public interface IJobbrRepository { + /// + /// Search jobs. + /// + /// Page number. + /// Page size. + /// Job type filter. + /// Job unique name filter. + /// Query. + /// If deleted jobs should be included. + /// Sort. + /// A paged list result of jobs matching the search criteria. PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort); + /// + /// Get job based on ID. + /// + /// Job ID. + /// Job matching the ID. Job GetJob(long id); + /// + /// Update job run progress. + /// + /// Job run ID. + /// Progress amount. void UpdateJobRunProgress(long jobRunId, double progress); + /// + /// Set process ID for job run. + /// + /// Job run. + /// Process ID. void SetPidForJobRun(JobRun jobRun, int id); + /// + /// Get job run based on ID. + /// + /// Job run ID. + /// Found . JobRun GetJobRun(long id); + /// + /// Save and add a recurring trigger to a . + /// + /// Job ID. + /// Trigger to save. void SaveAddTrigger(long jobId, RecurringTrigger trigger); + /// + /// Update planned start time (UTC). + /// + /// Job run ID. + /// New planned start time in UTC. void UpdatePlannedStartDateTimeUtc(long jobRunId, DateTime plannedStartDateTimeUtc); + /// + /// Save and add a scheduled trigger to a . + /// + /// Job ID. + /// Trigger to save. void SaveAddTrigger(long jobId, ScheduledTrigger trigger); + /// + /// Save and add an instant trigger to a . + /// + /// Job ID. + /// Trigger to save. void SaveAddTrigger(long jobId, InstantTrigger trigger); + /// + /// Enable a trigger. + /// + /// Job ID. + /// Trigger ID. void EnableTrigger(long jobId, long triggerId); + /// + /// Get active triggers. + /// + /// Page number. + /// Page size. + /// Job type filter. + /// Job unique name filter. + /// Query. + /// Sort. + /// Paged result of active triggers. PagedResult GetActiveTriggers(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, params string[] sort); + /// + /// Update a trigger. + /// + /// Job ID. + /// Trigger info. + /// If info has been changed. + /// The trigger that was updated. JobTriggerBase SaveUpdateTrigger(long jobId, JobTriggerBase trigger, out bool hadChanges); + /// + /// Get running jobs. + /// + /// Job ID. + /// Trigger ID. + /// List of running jobs. IEnumerable GetRunningJobs(long triggerJobId, long triggerId); + /// + /// Get all running jobs. + /// + /// All running jobs. IEnumerable GetRunningJobs(); + /// + /// Get job runs within certain states. + /// + /// Minimum state. + /// Maximum state. + /// List of job runs that are between the states. IEnumerable GetJobRunsByStateRange(JobRunStates minState, JobRunStates maxState); + /// + /// Add a . + /// + /// Job to add. void AddJob(Job job); + /// + /// Save a new job run. + /// + /// Job. + /// Job trigger. + /// Planned start time in UTC. + /// The new . JobRun SaveNewJobRun(Job job, JobTriggerBase trigger, DateTime plannedStartDateTimeUtc); + /// + /// Disable trigger. + /// + /// Job ID. + /// Trigger ID. void DisableTrigger(long jobId, long triggerId); + /// + /// Delete trigger. + /// + /// Job ID. + /// Trigger ID. void DeleteTrigger(long jobId, long triggerId); + /// + /// Update job run. + /// + /// Updated information. void Update(JobRun jobRun); + /// + /// Get job run. + /// + /// Job run ID. + /// Found job run. JobRun GetJobRunById(long jobRunId); + /// + /// Get trigger with ID. + /// + /// Job ID. + /// Trigger ID. + /// The job trigger. JobTriggerBase GetTriggerById(long jobId, long triggerId); + /// + /// Get triggers by job ID. + /// + /// Job ID. + /// Page number. + /// Page size. + /// Include deleted triggers. + /// Paged result of triggers. PagedResult GetTriggersByJobId(long jobId, int page, int pageSize = 50, bool showDeleted = false); + /// + /// Get job by it's unique name. + /// + /// Unique name. + /// The target job. Job GetJobByUniqueName(string identifier); + /// + /// Delete job run. + /// + /// Job run to delete. void Delete(JobRun jobRun); + /// + /// Search job runs. + /// + /// Page number. + /// Page size. + /// Job type filter. + /// Job unique name filter. + /// Query. + /// Include deleted job runs. + /// Sort. + /// A paged list of search result job runs. PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort); + /// + /// Search job runs with job ID. + /// + /// Job ID. + /// Page number. + /// Page size. + /// Include deleted job runs. + /// Sort. + /// A paged list of search result job runs. PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort); + /// + /// Search job runs with trigger ID. + /// + /// Job ID. + /// Trigger ID. + /// Page number. + /// Page size. + /// Include deleted job runs. + /// Sort. + /// A paged list of search result job runs. PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort); + /// + /// Search job runs with user ID. + /// + /// User ID. + /// Page number. + /// Page size. + /// Type filter for job. + /// Unique name filter for job. + /// Include deleted job runs. + /// Sort. + /// A paged list of search result job runs. PagedResult GetJobRunsByUserId(string userId, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort); + /// + /// Search job runs with user display name. + /// + /// User display name. + /// Page number. + /// Page size. + /// Type filter for job. + /// Unique name filter for job. + /// Include deleted job runs. + /// Sort. + /// A paged list of search result job runs. PagedResult GetJobRunsByUserDisplayName(string userDisplayName, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort); + /// + /// Search job runs with state. + /// + /// Job run state. + /// Page number. + /// Page size. + /// Type filter for job. + /// Unique name filter for job. + /// Query. + /// Include deleted job runs. + /// Sort. + /// A paged list of search result job runs. PagedResult GetJobRunsByState(JobRunStates state, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort); + /// + /// Search job runs with states. + /// + /// Job run states. + /// Page number. + /// Page size. + /// Type filter for job. + /// Unique name filter for job. + /// Query. + /// Include deleted job runs. + /// Sort. + /// A paged list of search result job runs. PagedResult GetJobRunsByStates(JobRunStates[] states, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort); + /// + /// Get last job run by trigger ID. + /// + /// Job ID. + /// Trigger ID. + /// UTC time. + /// The last job run matching the search terms. JobRun GetLastJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow); + /// + /// Get next job run by trigger ID. + /// + /// Job ID. + /// Trigger ID. + /// UTC time. + /// The next job run matching the search terms. JobRun GetNextJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow); } } \ No newline at end of file diff --git a/source/Jobbr.Server/Storage/InMemoryArtefactsStorage.cs b/source/Jobbr.Server/Storage/InMemoryArtefactsStorage.cs index e2a2f52..bd7cfa8 100644 --- a/source/Jobbr.Server/Storage/InMemoryArtefactsStorage.cs +++ b/source/Jobbr.Server/Storage/InMemoryArtefactsStorage.cs @@ -7,10 +7,19 @@ namespace Jobbr.Server.Storage { + /// + /// In-memory artifact storage. Intended for backup use. + /// public class InMemoryArtefactsStorage : IArtefactsStorageProvider { private readonly IDictionary> _files = new Dictionary>(); + /// + /// Save artifact. + /// + /// Container name. + /// File name. + /// Artifact content to save. public void Save(string container, string fileName, Stream content) { if (_files.ContainsKey(container) == false) @@ -35,6 +44,13 @@ public void Save(string container, string fileName, Stream content) list.Add(item); } + /// + /// Load artifact. + /// + /// Container name. + /// File name. + /// Artifact as a stream. + /// File not found. public Stream Load(string container, string fileName) { var filesInContainer = GetFilesFromContainer(container); @@ -49,6 +65,11 @@ public Stream Load(string container, string fileName) return new MemoryStream(file.Data); } + /// + /// Get all container artifacts. + /// + /// Container name. + /// List of artifacts. public List GetArtefacts(string container) { var filesInContainer = GetFilesFromContainer(container); diff --git a/source/Jobbr.Server/Storage/InMemoryJobStorageProvider.cs b/source/Jobbr.Server/Storage/InMemoryJobStorageProvider.cs index 9c55205..3ea5391 100644 --- a/source/Jobbr.Server/Storage/InMemoryJobStorageProvider.cs +++ b/source/Jobbr.Server/Storage/InMemoryJobStorageProvider.cs @@ -7,6 +7,9 @@ namespace Jobbr.Server.Storage { + /// + /// In-memory job storage provider. + /// public class InMemoryJobStorageProvider : IJobStorageProvider { private readonly IDictionary>> _triggerOrderByMapping = new Dictionary>> @@ -41,19 +44,23 @@ public class InMemoryJobStorageProvider : IJobStorageProvider { nameof(JobRun.EstimatedEndDateTimeUtc), e => e.EstimatedEndDateTimeUtc } }; - private readonly List _localTriggers = new List(); - - private readonly List _localJobs = new List(); - - private readonly List _localJobRuns = new List(); - + private readonly List _localTriggers = new (); + private readonly List _localJobs = new (); + private readonly List _localJobRuns = new (); + + /// + /// Get job triggers by job ID. + /// + /// Job ID. + /// Page number. + /// Page size. + /// Include deleted job triggers. + /// Paged list of job triggers. public PagedResult GetTriggersByJobId(long jobId, int page = 1, int pageSize = 50, bool showDeleted = false) { var enumerable = _localTriggers.Where(t => t.JobId == jobId); - int totalItems; - - enumerable = ApplyFiltersAndPaging(page, pageSize, null, null, null, enumerable, out totalItems); + enumerable = ApplyFiltersAndPaging(page, pageSize, null, null, null, enumerable, out var totalItems); var list = enumerable.ToList().Clone(); @@ -66,13 +73,21 @@ public PagedResult GetTriggersByJobId(long jobId, int page = 1, }; } + /// + /// Get active triggers. + /// + /// Page number. + /// Page size. + /// Job type. + /// Job unique name. + /// Query. + /// Sort. + /// A paged list result of active triggers. public PagedResult GetActiveTriggers(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, params string[] sort) { var enumerable = _localTriggers.Where(t => t.IsActive); - int totalItems; - - enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, enumerable, out totalItems); + enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, enumerable, out var totalItems); if (sort == null || sort.Length == 0) { @@ -94,11 +109,20 @@ public PagedResult GetActiveTriggers(int page = 1, int pageSize }; } + /// + /// Get job runs. + /// + /// Page number. + /// Page size. + /// Job type filter. + /// Job unique name filter. + /// Query. + /// Included deleted job runs in the result. + /// Sort. + /// Paged result of job runs. public PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { - int totalItems; - - var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, _localJobRuns, out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, _localJobRuns, out var totalItems); if (sort == null || sort.Length == 0) { @@ -118,11 +142,18 @@ public PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jo }; } + /// + /// Get job runs by job ID. + /// + /// Job ID. + /// Page number. + /// Page size. + /// Include deleted job runs. + /// Sort. + /// Paged result of job runs. public PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) { - int totalItems; - - var enumerable = ApplyFiltersAndPaging(page, pageSize, null, null, null, _localJobRuns, out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, null, null, null, _localJobRuns, out var totalItems); if (sort == null || sort.Length == 0) { @@ -142,11 +173,19 @@ public PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSi }; } + /// + /// Get job runs by trigger ID. + /// + /// Job ID. + /// Trigger ID. + /// Page number. + /// Page size. + /// Include deleted job runs in the result. + /// Sort. + /// Paged result of job runs. public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) { - int totalItems; - - var enumerable = ApplyFiltersAndPaging(page, pageSize, null, null, null, _localJobRuns.Where(p => p.Trigger.Id == triggerId), out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, null, null, null, _localJobRuns.Where(p => p.Trigger.Id == triggerId), out var totalItems); if (sort == null || sort.Length == 0) { @@ -166,26 +205,56 @@ public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int }; } + /// + /// Get trigger by ID. + /// + /// Job ID. + /// Trigger ID. + /// Found job trigger. public JobTriggerBase GetTriggerById(long jobId, long triggerId) { return _localTriggers.FirstOrDefault(t => t.Id == triggerId).Clone(); } + /// + /// Get last job run by trigger ID. + /// + /// Job ID. + /// Trigger ID. + /// Current time in UTC. + /// Last job run. public JobRun GetLastJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { return _localJobRuns.FirstOrDefault(jr => jr.Trigger.Id == triggerId && jr.ActualEndDateTimeUtc < utcNow).Clone(); } + /// + /// Get next job run by trigger ID. + /// + /// Job ID. + /// Trigger ID. + /// Current time in UTC. + /// Next job run. public JobRun GetNextJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { return _localJobRuns.FirstOrDefault(jr => jr.Trigger.Id == triggerId && jr.PlannedStartDateTimeUtc >= utcNow).Clone(); } + /// + /// Get job runs by state. + /// + /// State. + /// Page number. + /// Page size. + /// Job type filter. + /// Job unique name filter. + /// Query. + /// Include deleted job runs in the result. + /// Sort. + /// Paged result of job runs. public PagedResult GetJobRunsByState(JobRunStates state, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { - int totalItems; - - var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, _localJobRuns.Where(p => p.State == state), out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, _localJobRuns.Where(p => p.State == state), out var totalItems); if (sort == null || sort.Length == 0) { @@ -205,6 +274,18 @@ public PagedResult GetJobRunsByState(JobRunStates state, int page = 1, i }; } + /// + /// Get job runs by states. + /// + /// States. + /// Page number. + /// Page size. + /// Job type filter. + /// Job unique name filter. + /// Query. + /// Include deleted job runs in the result. + /// Sort. + /// Paged result of job runs. public PagedResult GetJobRunsByStates(JobRunStates[] states, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { int totalItems; @@ -229,6 +310,17 @@ public PagedResult GetJobRunsByStates(JobRunStates[] states, int page = }; } + /// + /// Get job runs by user ID. + /// + /// User ID. + /// Page number. + /// Page size. + /// Job type filter. + /// Job unique name filter. + /// Include deleted job runs in the result. + /// Sort. + /// Found job runs as a paged list. public PagedResult GetJobRunsByUserId(string userId, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) { int totalItems; @@ -253,11 +345,20 @@ public PagedResult GetJobRunsByUserId(string userId, int page = 1, int p }; } + /// + /// Get job runs by user display name. + /// + /// User display name. + /// Page number. + /// Page size. + /// Job type filter. + /// Job unique name filter. + /// Include deleted job runs in the result. + /// Sort. + /// Found job runs as a paged result. public PagedResult GetJobRunsByUserDisplayName(string userDisplayName, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) { - int totalItems; - - var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, null, _localJobRuns.Where(p => string.Equals(p.Trigger.UserDisplayName, userDisplayName, StringComparison.OrdinalIgnoreCase)), out totalItems); + var enumerable = ApplyFiltersAndPaging(page, pageSize, jobTypeFilter, jobUniqueNameFilter, null, _localJobRuns.Where(p => string.Equals(p.Trigger.UserDisplayName, userDisplayName, StringComparison.OrdinalIgnoreCase)), out var totalItems); if (sort == null || sort.Length == 0) { @@ -277,6 +378,17 @@ public PagedResult GetJobRunsByUserDisplayName(string userDisplayName, i }; } + /// + /// Search jobs. + /// + /// Page number. + /// Page size. + /// Job type filter. + /// Job unique name filter. + /// Query. + /// Include deleted jobs. + /// Sort. + /// Found jobs as a paged result. public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { int totalItems; @@ -301,21 +413,40 @@ public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeF }; } + /// + /// Get by job ID. + /// + /// Job ID. + /// The job. public Job GetJobById(long id) { return _localJobs.FirstOrDefault(j => j.Id == id).Clone(); } + /// + /// Get job by unique name. + /// + /// Unique name. + /// The found job. public Job GetJobByUniqueName(string identifier) { return _localJobs.FirstOrDefault(j => string.Equals(j.UniqueName, identifier, StringComparison.OrdinalIgnoreCase)).Clone(); } + /// + /// Get job run by job run ID. + /// + /// Job run ID. + /// Found job run or null. public JobRun GetJobRunById(long id) { return _localJobRuns.FirstOrDefault(j => j.Id == id).Clone(); } + /// + /// Add job. + /// + /// Job to add. public void AddJob(Job job) { var maxJobId = _localJobs.Count + 1; @@ -323,6 +454,11 @@ public void AddJob(Job job) _localJobs.Add(job); } + /// + /// Add recurring trigger. + /// + /// Job ID. + /// Trigger to add. public void AddTrigger(long jobId, RecurringTrigger trigger) { var newTriggerId = _localTriggers.Count + 1; @@ -331,6 +467,11 @@ public void AddTrigger(long jobId, RecurringTrigger trigger) _localTriggers.Add(trigger); } + /// + /// Add instant trigger. + /// + /// Job ID. + /// Trigger to add. public void AddTrigger(long jobId, InstantTrigger trigger) { var newTriggerId = _localTriggers.Count + 1; @@ -339,6 +480,11 @@ public void AddTrigger(long jobId, InstantTrigger trigger) _localTriggers.Add(trigger); } + /// + /// Add scheduled trigger. + /// + /// Job ID. + /// Trigger to add. public void AddTrigger(long jobId, ScheduledTrigger trigger) { var newTriggerId = _localTriggers.Count + 1; @@ -347,6 +493,10 @@ public void AddTrigger(long jobId, ScheduledTrigger trigger) _localTriggers.Add(trigger); } + /// + /// Add job run. + /// + /// Job run to add. public void AddJobRun(JobRun jobRun) { var maxJobRunId = _localJobRuns.Count + 1; @@ -356,77 +506,137 @@ public void AddJobRun(JobRun jobRun) _localJobRuns.Add(jobRun); } + /// + /// Disable trigger. + /// + /// Job ID. + /// Trigger ID. public void DisableTrigger(long jobId, long triggerId) { var trigger = _localTriggers.Single(t => t.Id == triggerId); trigger.IsActive = false; } + /// + /// Enable trigger. + /// + /// Job ID. + /// Trigger ID. public void EnableTrigger(long jobId, long triggerId) { var trigger = _localTriggers.Single(t => t.Id == triggerId); trigger.IsActive = true; } + /// + /// Delete trigger. Unimplemented. + /// + /// Job ID. + /// Trigger ID. + /// Throws always. public void DeleteTrigger(long jobId, long triggerId) { throw new NotImplementedException(); } + /// + /// Delete job. Unimplemented. + /// + /// Job ID. + /// Throws always. public void DeleteJob(long jobId) { throw new NotImplementedException(); } + /// + /// Update job run. + /// + /// New job run data. public void Update(JobRun jobRun) { _localJobRuns.Remove(_localJobRuns.FirstOrDefault(jr => jr.Id == jobRun.Id)); _localJobRuns.Add(jobRun); } + /// + /// Update job run progress. + /// + /// Job run ID. + /// Job run progress. public void UpdateProgress(long jobRunId, double? progress) { var jobRun = _localJobRuns.First(p => p.Id == jobRunId); jobRun.Progress = progress; } + /// + /// Apply retention. Unimplemented. + /// + /// Offset. + /// Throws always. public void ApplyRetention(DateTimeOffset date) { throw new NotImplementedException(); } + /// + /// Update job. + /// + /// New job information. public void Update(Job job) { _localJobs.Remove(_localJobs.FirstOrDefault(j => j.Id == job.Id)); _localJobs.Add(job); } + /// + /// Update an instant trigger. + /// + /// Job ID. + /// Trigger to update. public void Update(long jobId, InstantTrigger trigger) { _localTriggers.Remove(_localTriggers.FirstOrDefault(j => j.Id == trigger.Id)); _localTriggers.Add(trigger); } + /// + /// Update a scheduled trigger. + /// + /// Job ID. + /// Trigger to update. public void Update(long jobId, ScheduledTrigger trigger) { _localTriggers.Remove(_localTriggers.FirstOrDefault(j => j.Id == trigger.Id)); _localTriggers.Add(trigger); } + /// + /// Update a recurring trigger. + /// + /// Job ID. + /// Trigger to update. public void Update(long jobId, RecurringTrigger trigger) { _localTriggers.Remove(_localTriggers.FirstOrDefault(j => j.Id == trigger.Id)); _localTriggers.Add(trigger); } + /// + /// If in-memory provider is available. + /// + /// If available. public bool IsAvailable() { return true; } -#pragma warning disable CA1024 // Use properties where appropriate. + /// + /// Get jobs count in storage. + /// + /// Jobs count. public long GetJobsCount() -#pragma warning restore CA1024 // Use properties where appropriate. { return _localJobs.Count; } diff --git a/source/Jobbr.Server/Storage/JobbrRepository.cs b/source/Jobbr.Server/Storage/JobbrRepository.cs index a760fa7..87caef2 100644 --- a/source/Jobbr.Server/Storage/JobbrRepository.cs +++ b/source/Jobbr.Server/Storage/JobbrRepository.cs @@ -6,32 +6,44 @@ namespace Jobbr.Server.Storage { + /// + /// Jobbr repository implementation. + /// public class JobbrRepository : IJobbrRepository { private readonly ILogger _logger; private readonly IJobStorageProvider _jobStorageProvider; + /// + /// Initializes a new instance of the class. + /// + /// The logger factory. + /// Job storage provider. public JobbrRepository(ILoggerFactory loggerFactory, IJobStorageProvider jobStorageProvider) { _logger = loggerFactory.CreateLogger(); _jobStorageProvider = jobStorageProvider; } + /// public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { return _jobStorageProvider.GetJobs(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); } + /// public Job GetJob(long id) { return _jobStorageProvider.GetJobById(id); } + /// public void UpdateJobRunProgress(long jobRunId, double progress) { _jobStorageProvider.UpdateProgress(jobRunId, progress); } + /// public void SetPidForJobRun(JobRun jobRun, int id) { jobRun.Pid = id; @@ -39,16 +51,19 @@ public void SetPidForJobRun(JobRun jobRun, int id) _jobStorageProvider.Update(jobRun); } + /// public JobRun GetJobRun(long id) { return _jobStorageProvider.GetJobRunById(id); } + /// public void SaveAddTrigger(long jobId, RecurringTrigger trigger) { _jobStorageProvider.AddTrigger(jobId, trigger); } + /// public void UpdatePlannedStartDateTimeUtc(long jobRunId, DateTime plannedStartDateTimeUtc) { var jobRun = _jobStorageProvider.GetJobRunById(jobRunId); @@ -57,31 +72,37 @@ public void UpdatePlannedStartDateTimeUtc(long jobRunId, DateTime plannedStartDa Update(jobRun); } + /// public void SaveAddTrigger(long jobId, ScheduledTrigger trigger) { _jobStorageProvider.AddTrigger(jobId, trigger); } + /// public void SaveAddTrigger(long jobId, InstantTrigger trigger) { _jobStorageProvider.AddTrigger(jobId, trigger); } + /// public PagedResult GetJobRunsByStates(JobRunStates[] states, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { return _jobStorageProvider.GetJobRunsByStates(states, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); } + /// public JobRun GetLastJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { return _jobStorageProvider.GetLastJobRunByTriggerId(jobId, triggerId, utcNow); } + /// public JobRun GetNextJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) { return _jobStorageProvider.GetNextJobRunByTriggerId(jobId, triggerId, utcNow); } + /// public void EnableTrigger(long jobId, long triggerId) { // TODO: Move this logic to the storage adapter which can implement this more efficient @@ -90,6 +111,7 @@ public void EnableTrigger(long jobId, long triggerId) _jobStorageProvider.EnableTrigger(jobId, triggerId); } + /// public PagedResult GetActiveTriggers(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, params string[] sort) { try @@ -110,6 +132,7 @@ public PagedResult GetActiveTriggers(int page = 1, int pageSize } } + /// public JobTriggerBase SaveUpdateTrigger(long jobId, JobTriggerBase trigger, out bool hadChanges) { var triggerFromDb = _jobStorageProvider.GetTriggerById(jobId, trigger.Id); @@ -148,16 +171,19 @@ public JobTriggerBase SaveUpdateTrigger(long jobId, JobTriggerBase trigger, out return triggerFromDb; } + /// public PagedResult GetJobRunsByState(JobRunStates state, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { return _jobStorageProvider.GetJobRunsByState(state, page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); } + /// public void AddJob(Job job) { _jobStorageProvider.AddJob(job); } + /// public JobRun SaveNewJobRun(Job job, JobTriggerBase trigger, DateTime plannedStartDateTimeUtc) { var jobRun = new JobRun @@ -175,66 +201,79 @@ public JobRun SaveNewJobRun(Job job, JobTriggerBase trigger, DateTime plannedSta return jobRun; } + /// public void DisableTrigger(long jobId, long triggerId) { _jobStorageProvider.DisableTrigger(jobId, triggerId); } + /// public void DeleteTrigger(long jobId, long triggerId) { _jobStorageProvider.DeleteTrigger(jobId, triggerId); } + /// public void Update(JobRun jobRun) { _jobStorageProvider.Update(jobRun); } + /// public JobRun GetJobRunById(long jobRunId) { return _jobStorageProvider.GetJobRunById(jobRunId); } + /// public PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) { return _jobStorageProvider.GetJobRunsByJobId(jobId, page, pageSize, showDeleted, sort); } + /// public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) { return _jobStorageProvider.GetJobRunsByTriggerId(jobId, triggerId, page, pageSize, showDeleted, sort); } + /// public JobTriggerBase GetTriggerById(long jobId, long triggerId) { return _jobStorageProvider.GetTriggerById(jobId, triggerId); } + /// public PagedResult GetTriggersByJobId(long jobId, int page = 1, int pageSize = 50, bool showDeleted = false) { return _jobStorageProvider.GetTriggersByJobId(jobId, page, pageSize, showDeleted); } + /// public PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) { return _jobStorageProvider.GetJobRuns(page, pageSize, jobTypeFilter, jobUniqueNameFilter, query, showDeleted, sort); } + /// public PagedResult GetJobRunsByUserId(string userId, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) { return _jobStorageProvider.GetJobRunsByUserId(userId, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); } + /// public PagedResult GetJobRunsByUserDisplayName(string userDisplayName, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) { return _jobStorageProvider.GetJobRunsByUserDisplayName(userDisplayName, page, pageSize, jobTypeFilter, jobUniqueNameFilter, showDeleted, sort); } + /// public Job GetJobByUniqueName(string identifier) { return _jobStorageProvider.GetJobByUniqueName(identifier); } + /// public void Delete(JobRun jobRun) { var jobRunFromStorage = _jobStorageProvider.GetJobRunById(jobRun.Id); @@ -243,6 +282,7 @@ public void Delete(JobRun jobRun) _jobStorageProvider.Update(jobRunFromStorage); } + /// public IEnumerable GetRunningJobs() { var minState = (int)JobRunStates.Scheduled + 1; @@ -256,6 +296,7 @@ public IEnumerable GetRunningJobs() } } + /// public IEnumerable GetRunningJobs(long triggerJobId, long triggerId) { var runningJobs = GetRunningJobs(); @@ -269,6 +310,7 @@ public IEnumerable GetRunningJobs(long triggerJobId, long triggerId) } } + /// public IEnumerable GetJobRunsByStateRange(JobRunStates minState, JobRunStates maxState) { if (maxState < minState) From 1ad492ee036ce2150261d4cfe4b88cbc1182e012 Mon Sep 17 00:00:00 2001 From: Roope Kivioja Date: Fri, 6 Jan 2023 16:30:12 +0100 Subject: [PATCH 28/41] Update devsupport module --- source/submodules/devsupport | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/submodules/devsupport b/source/submodules/devsupport index a48352c..0d47c19 160000 --- a/source/submodules/devsupport +++ b/source/submodules/devsupport @@ -1 +1 @@ -Subproject commit a48352cdc76fcdb0b6426fe62e1ee30d3efee7de +Subproject commit 0d47c199f93b0be8ea00443702bc44797d2e1549 From 3cfd45a7104f58e667c8c0dd0fc2145d8c16bd7f Mon Sep 17 00:00:00 2001 From: Mara Huminiuc Date: Thu, 5 Jan 2023 18:17:03 +0100 Subject: [PATCH 29/41] Align nuget packages versions --- .../Jobbr.Server.IntegrationTests.csproj | 13 --------- .../Registration/BuilderTests.cs | 3 +- .../Jobbr.Server.UnitTests.csproj | 1 - source/Jobbr.Server.nuspec | 29 ++++++++++--------- source/Jobbr.Server/Jobbr.Server.csproj | 5 +--- 5 files changed, 18 insertions(+), 33 deletions(-) diff --git a/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj b/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj index 5726ab0..71baea2 100644 --- a/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj +++ b/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj @@ -25,22 +25,10 @@ - - - - - - - - - - - - @@ -52,7 +40,6 @@ - diff --git a/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs b/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs index 08ab200..cb46b0d 100644 --- a/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs @@ -11,6 +11,7 @@ using Jobbr.Server.IntegrationTests.Integration; using Jobbr.Server.JobRegistry; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; @@ -24,7 +25,7 @@ public class BuilderTests [TestInitialize] public void Initialize() { - _loggerFactory = new LoggerFactory(); + _loggerFactory = new NullLoggerFactory(); } [TestCleanup] diff --git a/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj b/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj index acf266a..d32b197 100644 --- a/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj +++ b/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj @@ -22,7 +22,6 @@ - diff --git a/source/Jobbr.Server.nuspec b/source/Jobbr.Server.nuspec index 53f4e82..a5abedc 100644 --- a/source/Jobbr.Server.nuspec +++ b/source/Jobbr.Server.nuspec @@ -11,20 +11,21 @@ Jobbr is a non-invasive .NET JobServer Copyright 2022 images\icon.png - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index b3e6bd1..ae5cd12 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -19,9 +19,6 @@ pdbonly - - - CustomDictionary.xml @@ -34,7 +31,7 @@ - + From b256a94d89bb29babce302e276f0dbb5d514966e Mon Sep 17 00:00:00 2001 From: Mara Huminiuc Date: Tue, 10 Jan 2023 10:23:16 +0100 Subject: [PATCH 30/41] Use NullLoggerFactory.Instance for consistency --- appveyor.yml | 2 +- .../Components/JobRunService/ProgressUpdateTests.cs | 6 +++--- .../Components/Scheduler/TestBase.cs | 6 +++--- .../Integration/JobbrServerTestBase.cs | 2 +- .../Integration/Startup/BadEnvironmentTests.cs | 6 +++--- .../Integration/Startup/ConfigurationValidationTests.cs | 8 ++++---- source/Jobbr.Server.IntegrationTests/PackagingTests.cs | 2 ++ .../Registration/BuilderTests.cs | 2 +- source/Jobbr.Server.nuspec | 2 ++ source/Jobbr.Server/Jobbr.Server.csproj | 2 +- 10 files changed, 21 insertions(+), 17 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 3bbdf6a..37ed6b3 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,7 +24,7 @@ assembly_info: before_build: - nuget restore source/Jobbr.Server.sln - - ps: C:\ProgramData\chocolatey\lib\GitVersion.Portable\tools\GitVersion.exe /l console /output buildserver /updateAssemblyInfo + - ps: C:\ProgramData\chocolatey\lib\GitVersion.Portable\tools\GitVersion.exe /l console /output buildserver /updateprojectfiles platform: Any CPU configuration: Release diff --git a/source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressUpdateTests.cs b/source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressUpdateTests.cs index 3653767..6a052d5 100644 --- a/source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressUpdateTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/JobRunService/ProgressUpdateTests.cs @@ -19,13 +19,13 @@ public class ProgressUpdateTests public ProgressUpdateTests() { - var autoMapperConfig = new AutoMapperConfigurationFactory(new NullLoggerFactory()).GetNew(); + var autoMapperConfig = new AutoMapperConfigurationFactory(NullLoggerFactory.Instance).GetNew(); - _repo = new JobbrRepository(new NullLoggerFactory(), new InMemoryJobStorageProvider()); + _repo = new JobbrRepository(NullLoggerFactory.Instance, new InMemoryJobStorageProvider()); _messengerHub = new TinyMessengerHub(); - _service = new Server.Core.JobRunService(new NullLoggerFactory(), _messengerHub, _repo, null, autoMapperConfig.CreateMapper()); + _service = new Server.Core.JobRunService(NullLoggerFactory.Instance, _messengerHub, _repo, null, autoMapperConfig.CreateMapper()); } [TestMethod] diff --git a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/TestBase.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/TestBase.cs index d4dd6ac..0cf10a4 100644 --- a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/TestBase.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/TestBase.cs @@ -21,7 +21,7 @@ public class TestBase public TestBase() { - repository = new JobbrRepository(new NullLoggerFactory(), new InMemoryJobStorageProvider()); + repository = new JobbrRepository(NullLoggerFactory.Instance, new InMemoryJobStorageProvider()); var executorMock = new Mock(); executorMock.Setup(e => e.OnPlanChanged(It.IsNotNull>())).Callback>(p => lastIssuedPlan = p); @@ -34,9 +34,9 @@ public TestBase() repository.AddJob(job); demoJob1Id = job.Id; - scheduler = new DefaultScheduler(new NullLoggerFactory(), repository, executorMock.Object, + scheduler = new DefaultScheduler(NullLoggerFactory.Instance, repository, executorMock.Object, new InstantJobRunPlaner(currentTimeProvider), new ScheduledJobRunPlaner(currentTimeProvider), - new RecurringJobRunPlaner(new NullLoggerFactory(), repository, currentTimeProvider), new DefaultSchedulerConfiguration(), + new RecurringJobRunPlaner(NullLoggerFactory.Instance, repository, currentTimeProvider), new DefaultSchedulerConfiguration(), periodicTimer, currentTimeProvider); } } diff --git a/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs b/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs index 964d5ec..9aba973 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/JobbrServerTestBase.cs @@ -40,7 +40,7 @@ protected static JobbrServer GivenAStartedServer() protected static JobbrServer GivenAServerInstance() { - var builder = new JobbrBuilder(new NullLoggerFactory()); + var builder = new JobbrBuilder(NullLoggerFactory.Instance); builder.RegisterForCollection(typeof(ExposeAllServicesComponent)); diff --git a/source/Jobbr.Server.IntegrationTests/Integration/Startup/BadEnvironmentTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Startup/BadEnvironmentTests.cs index 6ebd610..2b3fd32 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/Startup/BadEnvironmentTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Startup/BadEnvironmentTests.cs @@ -15,7 +15,7 @@ public class BadEnvironmentTests [TestMethod] public void StartingJobber_GetsRunning_WhenStorageProviderTurnsHealthy() { - var builder = new JobbrBuilder(new NullLoggerFactory()); + var builder = new JobbrBuilder(NullLoggerFactory.Instance); builder.Register(typeof(FaultyJobStorageProvider)); var jobbr = builder.Create(); @@ -34,7 +34,7 @@ public void StartingJobber_GetsRunning_WhenStorageProviderTurnsHealthy() [TestMethod] public void StartingJobbr_ComponentFails_IsInErrorState() { - var nullLoggerFactory = new NullLoggerFactory(); + var nullLoggerFactory = NullLoggerFactory.Instance; var builder = new JobbrBuilder(nullLoggerFactory); builder.RegisterForCollection(typeof(FaultyComponent)); @@ -57,7 +57,7 @@ public void StartingJobbr_ComponentFails_IsInErrorState() [ExpectedException(typeof(Exception))] public void StartingJobbr_ComponentFails_ExceptionIsThrown() { - var builder = new JobbrBuilder(new NullLoggerFactory()); + var builder = new JobbrBuilder(NullLoggerFactory.Instance); builder.RegisterForCollection(typeof(FaultyComponent)); var jobbr = builder.Create(); diff --git a/source/Jobbr.Server.IntegrationTests/Integration/Startup/ConfigurationValidationTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Startup/ConfigurationValidationTests.cs index 033f927..0c13c73 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/Startup/ConfigurationValidationTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Startup/ConfigurationValidationTests.cs @@ -63,7 +63,7 @@ public bool Validate(object configuration) [TestMethod] public void ValidatorForSettings_WhenRegistered_IsCalled() { - var builder = new JobbrBuilder(new NullLoggerFactory()); + var builder = new JobbrBuilder(NullLoggerFactory.Instance); builder.Add(new DemoSettings()); var isCalled = false; @@ -80,7 +80,7 @@ public void ValidatorForSettings_WhenRegistered_IsCalled() [TestMethod] public void ValidatorForSettings_WhenCalled_SettingsIsPassedThrough() { - var builder = new JobbrBuilder(new NullLoggerFactory()); + var builder = new JobbrBuilder(NullLoggerFactory.Instance); var demoSettings = new DemoSettings(); object settingsToValidate = null; @@ -101,7 +101,7 @@ public void ValidatorForSettings_WhenCalled_SettingsIsPassedThrough() [ExpectedException(typeof(Exception))] public void ValidatorForSettings_ValidationFails_PreventsStart() { - var builder = new JobbrBuilder(new NullLoggerFactory()); + var builder = new JobbrBuilder(NullLoggerFactory.Instance); builder.Add(new DemoSettings()); @@ -116,7 +116,7 @@ public void ValidatorForSettings_ValidationFails_PreventsStart() [ExpectedException(typeof(Exception))] public void ValidatorForSettings_ThrowsException_PreventsStart() { - var builder = new JobbrBuilder(new NullLoggerFactory()); + var builder = new JobbrBuilder(NullLoggerFactory.Instance); builder.Add(new DemoSettings()); diff --git a/source/Jobbr.Server.IntegrationTests/PackagingTests.cs b/source/Jobbr.Server.IntegrationTests/PackagingTests.cs index 36c654e..4bd1aac 100644 --- a/source/Jobbr.Server.IntegrationTests/PackagingTests.cs +++ b/source/Jobbr.Server.IntegrationTests/PackagingTests.cs @@ -23,6 +23,7 @@ public void Feature_NuSpec_IsCompliant() asserter.Add(new PackageExistsInBothRule("Microsoft.Extensions.Logging.Abstractions")); asserter.Add(new PackageExistsInBothRule("NCrontab")); asserter.Add(new PackageExistsInBothRule("SimpleInjector")); + asserter.Add(new PackageExistsInBothRule("System.Text.Json")); asserter.Add(new PackageExistsInBothRule("TinyMessenger")); asserter.Add(new VersionIsIncludedInRange("Jobbr.ComponentModel.*")); @@ -32,6 +33,7 @@ public void Feature_NuSpec_IsCompliant() asserter.Add(new VersionIsIncludedInRange("Microsoft.Extensions.Logging.Abstractions")); asserter.Add(new VersionIsIncludedInRange("NCrontab")); asserter.Add(new VersionIsIncludedInRange("SimpleInjector")); + asserter.Add(new VersionIsIncludedInRange("System.Text.Json")); asserter.Add(new VersionIsIncludedInRange("TinyMessenger")); asserter.Add(new NoMajorChangesInNuSpec("Jobbr.*")); diff --git a/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs b/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs index cb46b0d..311e1af 100644 --- a/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs @@ -25,7 +25,7 @@ public class BuilderTests [TestInitialize] public void Initialize() { - _loggerFactory = new NullLoggerFactory(); + _loggerFactory = NullLoggerFactory.Instance; } [TestCleanup] diff --git a/source/Jobbr.Server.nuspec b/source/Jobbr.Server.nuspec index a5abedc..bd9f496 100644 --- a/source/Jobbr.Server.nuspec +++ b/source/Jobbr.Server.nuspec @@ -12,6 +12,7 @@ Copyright 2022 images\icon.png + @@ -25,6 +26,7 @@ + diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index ae5cd12..6f04de2 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -35,7 +35,7 @@ - + From 5fcae709dccb0f74e621d213a0bef79fd90052f5 Mon Sep 17 00:00:00 2001 From: Mara Huminiuc Date: Tue, 10 Jan 2023 10:46:29 +0100 Subject: [PATCH 31/41] Remove targetFramework group from nuspec --- source/Jobbr.Server.nuspec | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/source/Jobbr.Server.nuspec b/source/Jobbr.Server.nuspec index bd9f496..4d98749 100644 --- a/source/Jobbr.Server.nuspec +++ b/source/Jobbr.Server.nuspec @@ -12,21 +12,19 @@ Copyright 2022 images\icon.png - - - - - - - - - - - - - - - + + + + + + + + + + + + + From d914b7fdd2c67693b2799bafa92bafc8bbdd61c8 Mon Sep 17 00:00:00 2001 From: Mara Huminiuc Date: Wed, 11 Jan 2023 11:21:47 +0100 Subject: [PATCH 32/41] Fix nuspec specification for NCrontab --- source/Jobbr.Server.nuspec | 4 +++- source/Jobbr.Server/Jobbr.Server.csproj | 3 +++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/source/Jobbr.Server.nuspec b/source/Jobbr.Server.nuspec index 4d98749..d34ff15 100644 --- a/source/Jobbr.Server.nuspec +++ b/source/Jobbr.Server.nuspec @@ -12,6 +12,7 @@ Copyright 2022 images\icon.png + @@ -21,10 +22,11 @@ - + + diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index 6f04de2..e87e4d3 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -2,6 +2,9 @@ {A45F729D-8629-4C7A-96B8-29EAA8D52919} net6.0 + PackageReference + true + true Jobber.Server Zuehlke Technology Group Jobbr.Server From e96b01377436ad582f46f1dedf808689a3d26b6f Mon Sep 17 00:00:00 2001 From: Mara Huminiuc Date: Wed, 11 Jan 2023 11:47:28 +0100 Subject: [PATCH 33/41] Fixed unit test --- .../Jobbr.Server.IntegrationTests.csproj | 5 ++++- source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj | 3 +++ source/Jobbr.Server.nuspec | 2 -- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj b/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj index 71baea2..ff63d31 100644 --- a/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj +++ b/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj @@ -1,7 +1,10 @@  {304D07A5-D6D1-4F48-819E-5D28ED8755AC} - net6.0 + net6.0 + PackageReference + true + true {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages diff --git a/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj b/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj index d32b197..f75bfe9 100644 --- a/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj +++ b/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj @@ -1,6 +1,9 @@  net6.0 + PackageReference + true + true Jobbr.Server.UnitTests Zuehlke Technology Group Copyright © Zuehlke Technology Group 2022 diff --git a/source/Jobbr.Server.nuspec b/source/Jobbr.Server.nuspec index d34ff15..f55153b 100644 --- a/source/Jobbr.Server.nuspec +++ b/source/Jobbr.Server.nuspec @@ -12,7 +12,6 @@ Copyright 2022 images\icon.png - @@ -26,7 +25,6 @@ - From f5fc605ae138a3c807dc3a17526f9f984408fac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Sun, 29 Jan 2023 21:45:12 +0100 Subject: [PATCH 34/41] Align Microsoft dependency versions around .NET 6 --- .../Jobbr.Server.IntegrationTests.csproj | 6 +++--- .../Jobbr.Server.UnitTests.csproj | 4 ++-- source/Jobbr.Server.nuspec | 10 +++++----- source/Jobbr.Server/Jobbr.Server.csproj | 10 +++++----- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj b/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj index ff63d31..5d6e532 100644 --- a/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj +++ b/source/Jobbr.Server.IntegrationTests/Jobbr.Server.IntegrationTests.csproj @@ -28,10 +28,10 @@ - + - + @@ -43,7 +43,7 @@ - + diff --git a/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj b/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj index f75bfe9..79a90df 100644 --- a/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj +++ b/source/Jobbr.Server.UnitTests/Jobbr.Server.UnitTests.csproj @@ -22,10 +22,10 @@ - + - + diff --git a/source/Jobbr.Server.nuspec b/source/Jobbr.Server.nuspec index f55153b..2a4b0db 100644 --- a/source/Jobbr.Server.nuspec +++ b/source/Jobbr.Server.nuspec @@ -9,7 +9,7 @@ GPL-3.0-only true Jobbr is a non-invasive .NET JobServer - Copyright 2022 + Copyright 2023 images\icon.png @@ -18,12 +18,12 @@ - - - + + + - + diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index e87e4d3..68348f8 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -28,13 +28,13 @@ - - - - + + + + - + From b02a3bc71ad1506fa09b4fc65fdd6202da2af999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Tue, 31 Jan 2023 21:38:15 +0100 Subject: [PATCH 35/41] Fix a few warnings --- .../Components/Scheduler/PlanningTests.cs | 226 +++++------ .../Components/Scheduler/SchedulerTests.cs | 86 ++-- .../Components/Scheduler/TestBase.cs | 47 ++- .../Startup/ConfigurationValidationTests.cs | 102 ++--- .../Registration/BuilderTests.cs | 380 +++++++++--------- .../ShouldDateTimeExtensions.cs | 7 +- .../Scheduling/DefaultScheduler.cs | 12 +- source/submodules/devsupport | 2 +- 8 files changed, 438 insertions(+), 424 deletions(-) diff --git a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PlanningTests.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PlanningTests.cs index 25095ee..5e08f06 100644 --- a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PlanningTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/PlanningTests.cs @@ -11,34 +11,34 @@ public class PlanningTests : TestBase { public PlanningTests() { - scheduler.Start(); + Scheduler.Start(); } [TestMethod] public void NewScheduledTrigger_IsAdded_WillBePlanned() { - var scheduledTrigger = new ScheduledTrigger { JobId = demoJob1Id, StartDateTimeUtc = DateTime.UtcNow.AddSeconds(-1), IsActive = true }; - AddAndSignalNewTrigger(demoJob1Id, scheduledTrigger); + var scheduledTrigger = new ScheduledTrigger { JobId = DemoJob1Id, StartDateTimeUtc = DateTime.UtcNow.AddSeconds(-1), IsActive = true }; + AddAndSignalNewTrigger(DemoJob1Id, scheduledTrigger); - Assert.AreEqual(1, lastIssuedPlan.Count, "A scheduled trigger should cause one item in the plan"); + Assert.AreEqual(1, LastIssuedPlan.Count, "A scheduled trigger should cause one item in the plan"); } [TestMethod] public void NewInstantTrigger_IsAdded_WillBePlanned() { - var scheduledTrigger = new InstantTrigger() { JobId = demoJob1Id, IsActive = true }; - AddAndSignalNewTrigger(demoJob1Id, scheduledTrigger); + var scheduledTrigger = new InstantTrigger() { JobId = DemoJob1Id, IsActive = true }; + AddAndSignalNewTrigger(DemoJob1Id, scheduledTrigger); - Assert.AreEqual(1, lastIssuedPlan.Count, "A instant trigger should cause one item in the plan"); + Assert.AreEqual(1, LastIssuedPlan.Count, "A instant trigger should cause one item in the plan"); } [TestMethod] public void NewScheduledTrigger_IsAdded_CreatesANewJobRun() { - var scheduledTrigger = new ScheduledTrigger { JobId = demoJob1Id, StartDateTimeUtc = DateTime.UtcNow.AddSeconds(-1), IsActive = true }; - AddAndSignalNewTrigger(demoJob1Id, scheduledTrigger); + var scheduledTrigger = new ScheduledTrigger { JobId = DemoJob1Id, StartDateTimeUtc = DateTime.UtcNow.AddSeconds(-1), IsActive = true }; + AddAndSignalNewTrigger(DemoJob1Id, scheduledTrigger); - var jobRuns = repository.GetJobRuns(); + var jobRuns = Repository.GetJobRuns(); Assert.AreEqual(1, jobRuns.Items.Count, "A scheduled trigger should create exact one jobrun when added"); Assert.AreEqual(scheduledTrigger.Id, jobRuns.Items.Single().Trigger.Id, "The jobrun should reference the trigger that cause the job to run"); @@ -49,13 +49,13 @@ public void NewScheduledTrigger_IsAdded_IsPlannedOnTime() { var dateTimeUtc = DateTime.UtcNow.AddHours(10); - var scheduledTrigger = new ScheduledTrigger { JobId = demoJob1Id, StartDateTimeUtc = dateTimeUtc, IsActive = true }; - AddAndSignalNewTrigger(demoJob1Id, scheduledTrigger); + var scheduledTrigger = new ScheduledTrigger { JobId = DemoJob1Id, StartDateTimeUtc = dateTimeUtc, IsActive = true }; + AddAndSignalNewTrigger(DemoJob1Id, scheduledTrigger); - var jobRun = repository.GetJobRuns().Items.Single(); + var jobRun = Repository.GetJobRuns().Items.Single(); - Assert.AreEqual(dateTimeUtc, lastIssuedPlan.Single().PlannedStartDateTimeUtc, "The startdate should be considered in the plan"); - Assert.AreEqual(jobRun.Id, lastIssuedPlan.Single().Id, "The startdate should be considered in the plan"); + Assert.AreEqual(dateTimeUtc, LastIssuedPlan.Single().PlannedStartDateTimeUtc, "The startdate should be considered in the plan"); + Assert.AreEqual(jobRun.Id, LastIssuedPlan.Single().Id, "The startdate should be considered in the plan"); } [TestMethod] @@ -63,14 +63,14 @@ public void NewRecurringTriggerWithoutSeconds_IsAdded_IsPlannedOnTime() { var dateTimeUtc = new DateTime(DateTime.UtcNow.Year + 1, 09, 02, 17, 00, 00); - var scheduledTrigger = new RecurringTrigger() { Definition = "* * * * *", JobId = demoJob1Id, StartDateTimeUtc = dateTimeUtc, IsActive = true }; - AddAndSignalNewTrigger(demoJob1Id, scheduledTrigger); + var scheduledTrigger = new RecurringTrigger() { Definition = "* * * * *", JobId = DemoJob1Id, StartDateTimeUtc = dateTimeUtc, IsActive = true }; + AddAndSignalNewTrigger(DemoJob1Id, scheduledTrigger); - var jobRun = repository.GetJobRuns().Items.Single(); + var jobRun = Repository.GetJobRuns().Items.Single(); var expectedTime = dateTimeUtc.AddMinutes(1); - Assert.AreEqual(expectedTime, lastIssuedPlan.Single().PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); - Assert.AreEqual(jobRun.Id, lastIssuedPlan.Single().Id, "The startdate should be considered in the plan"); + Assert.AreEqual(expectedTime, LastIssuedPlan.Single().PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); + Assert.AreEqual(jobRun.Id, LastIssuedPlan.Single().Id, "The startdate should be considered in the plan"); } [TestMethod] @@ -78,14 +78,14 @@ public void NewRecurringTriggerWithSeconds_IsAdded_DoesNotContainsSecondInTrigge { var dateTimeUtc = new DateTime(DateTime.UtcNow.Year + 1, 02, 09, 17, 00, 15); - var scheduledTrigger = new RecurringTrigger() { Definition = "* * * * *", StartDateTimeUtc = dateTimeUtc, JobId = demoJob1Id, IsActive = true }; - AddAndSignalNewTrigger(demoJob1Id, scheduledTrigger); + var scheduledTrigger = new RecurringTrigger { Definition = "* * * * *", StartDateTimeUtc = dateTimeUtc, JobId = DemoJob1Id, IsActive = true }; + AddAndSignalNewTrigger(DemoJob1Id, scheduledTrigger); - var jobRun = repository.GetJobRuns().Items.Single(); + var jobRun = Repository.GetJobRuns().Items.Single(); var expectedTime = dateTimeUtc.AddMinutes(1).AddSeconds(-15); - Assert.AreEqual(expectedTime, lastIssuedPlan.Single().PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); - Assert.AreEqual(jobRun.Id, lastIssuedPlan.Single().Id, "The startdate should be considered in the plan"); + Assert.AreEqual(expectedTime, LastIssuedPlan.Single().PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); + Assert.AreEqual(jobRun.Id, LastIssuedPlan.Single().Id, "The startdate should be considered in the plan"); } [TestMethod] @@ -93,24 +93,24 @@ public void RecurringTrigger_AfterTwoMinutes_IsPlannedMultipleTimes() { var dateTimeUtc = new DateTime(2017, 02, 09, 14, 00, 00); - currentTimeProvider.Set(dateTimeUtc); + CurrentTimeProvider.Set(dateTimeUtc); var scheduledTrigger = new RecurringTrigger { Definition = "* * * * *", - JobId = demoJob1Id, + JobId = DemoJob1Id, StartDateTimeUtc = dateTimeUtc, IsActive = true }; - AddAndSignalNewTrigger(demoJob1Id, scheduledTrigger); + AddAndSignalNewTrigger(DemoJob1Id, scheduledTrigger); - currentTimeProvider.AddMinute(); - periodicTimer.CallbackOnce(); + CurrentTimeProvider.AddMinute(); + PeriodicTimer.CallbackOnce(); - currentTimeProvider.AddMinute(); - periodicTimer.CallbackOnce(); + CurrentTimeProvider.AddMinute(); + PeriodicTimer.CallbackOnce(); - var jobRuns = repository.GetJobRuns(); + var jobRuns = Repository.GetJobRuns(); var expectedTime1 = dateTimeUtc.AddMinutes(1); var expectedTime2 = dateTimeUtc.AddMinutes(2); @@ -118,9 +118,9 @@ public void RecurringTrigger_AfterTwoMinutes_IsPlannedMultipleTimes() Assert.AreEqual(3, jobRuns.Items.Count); - Assert.AreEqual(expectedTime1, lastIssuedPlan[0].PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); - Assert.AreEqual(expectedTime2, lastIssuedPlan[1].PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); - Assert.AreEqual(expectedTime3, lastIssuedPlan[2].PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); + Assert.AreEqual(expectedTime1, LastIssuedPlan[0].PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); + Assert.AreEqual(expectedTime2, LastIssuedPlan[1].PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); + Assert.AreEqual(expectedTime3, LastIssuedPlan[2].PlannedStartDateTimeUtc, "The startdate should match the StartDateTimeUtc + 1 Minute"); } [TestMethod] @@ -129,20 +129,20 @@ public void ScheduledTrigger_HasCompletedJobRun_DoesNotTriggerNewOne() // Note: The Scheduled Trigger needs to be in the past in order to invalidate the job reliable in this testing scenario (Issues with NCrunch, no issues with R# and VS-Runners) var scheduledTrigger = new ScheduledTrigger { - JobId = demoJob1Id, + JobId = DemoJob1Id, StartDateTimeUtc = DateTime.UtcNow.AddSeconds(-1), IsActive = true }; - AddAndSignalNewTrigger(demoJob1Id, scheduledTrigger); + AddAndSignalNewTrigger(DemoJob1Id, scheduledTrigger); // Simulate Job Completeness - var jobRunByScheduledTrigger = repository.GetJobRuns().Items.Single(jr => jr.Trigger.Id == scheduledTrigger.Id); + var jobRunByScheduledTrigger = Repository.GetJobRuns().Items.Single(jr => jr.Trigger.Id == scheduledTrigger.Id); jobRunByScheduledTrigger.State = JobRunStates.Completed; - repository.Update(jobRunByScheduledTrigger); + Repository.Update(jobRunByScheduledTrigger); - scheduler.OnJobRunEnded(jobRunByScheduledTrigger.Id); + Scheduler.OnJobRunEnded(jobRunByScheduledTrigger.Id); - Assert.AreEqual(0, lastIssuedPlan.Count, "A scheduled trigger should not cause any additional jobruns after completion"); + Assert.AreEqual(0, LastIssuedPlan.Count, "A scheduled trigger should not cause any additional jobruns after completion"); } [TestMethod] @@ -151,121 +151,121 @@ public void RecurringTrigger_HasCompletedJobRun_TriggerNewOne() var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", - JobId = demoJob1Id, + JobId = DemoJob1Id, IsActive = true, NoParallelExecution = false, StartDateTimeUtc = DateTime.UtcNow }; - AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); + AddAndSignalNewTrigger(DemoJob1Id, recurringTrigger); // Simulate Job Completeness - var jobRunByScheduledTrigger = repository.GetJobRuns().Items.Single(jr => jr.Trigger.Id == recurringTrigger.Id); + var jobRunByScheduledTrigger = Repository.GetJobRuns().Items.Single(jr => jr.Trigger.Id == recurringTrigger.Id); jobRunByScheduledTrigger.State = JobRunStates.Completed; - repository.Update(jobRunByScheduledTrigger); + Repository.Update(jobRunByScheduledTrigger); - scheduler.OnJobRunEnded(jobRunByScheduledTrigger.Id); + Scheduler.OnJobRunEnded(jobRunByScheduledTrigger.Id); - var jobRun = repository.GetJobRuns(); + var jobRun = Repository.GetJobRuns(); Assert.AreEqual(2, jobRun.Items.Count, "Trigger should have triggered an additional job after completion of the first"); - Assert.AreEqual(1, lastIssuedPlan.Count, "A scheduled trigger should not cause any additional jobruns after completion"); + Assert.AreEqual(1, LastIssuedPlan.Count, "A scheduled trigger should not cause any additional jobruns after completion"); } [TestMethod] public void RecurringTrigger_WithNoTriggerOrJobChanges_DoesTriggerNewOnes() { var initialDate = new DateTime(2017, 02, 01, 15, 42, 12, DateTimeKind.Utc); - currentTimeProvider.Set(initialDate); + CurrentTimeProvider.Set(initialDate); var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", - JobId = demoJob1Id, + JobId = DemoJob1Id, IsActive = true, NoParallelExecution = false }; // This triggers the first job run - AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); + AddAndSignalNewTrigger(DemoJob1Id, recurringTrigger); // wait for additional job run - currentTimeProvider.Set(initialDate.AddHours(2)); - periodicTimer.CallbackOnce(); + CurrentTimeProvider.Set(initialDate.AddHours(2)); + PeriodicTimer.CallbackOnce(); - var jobRun = repository.GetJobRuns(); + var jobRun = Repository.GetJobRuns(); Assert.AreEqual(2, jobRun.Items.Count, "Trigger should continue trigger additional jobruns"); - Assert.AreEqual(2, lastIssuedPlan.Count, "The plan should contain items for all 3 triggers"); + Assert.AreEqual(2, LastIssuedPlan.Count, "The plan should contain items for all 3 triggers"); } [TestMethod] public void NoParallelExecutionDisabled_ForceNewPlanWhileJobIsStillRunning_NextJobRunIsCreated() { var initialDate = new DateTime(2017, 02, 01, 15, 42, 12, DateTimeKind.Utc); - currentTimeProvider.Set(initialDate); + CurrentTimeProvider.Set(initialDate); - var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = demoJob1Id, IsActive = true, NoParallelExecution = false }; - AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); + var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = DemoJob1Id, IsActive = true, NoParallelExecution = false }; + AddAndSignalNewTrigger(DemoJob1Id, recurringTrigger); // Simulate that the jobRun has started - var addedJobRun = repository.GetJobRunsByTriggerId(recurringTrigger.JobId, recurringTrigger.Id).Items.Single(); + var addedJobRun = Repository.GetJobRunsByTriggerId(recurringTrigger.JobId, recurringTrigger.Id).Items.Single(); addedJobRun.State = JobRunStates.Processing; - repository.Update(addedJobRun); + Repository.Update(addedJobRun); // Make sure the cron in the recurring trigger will base on an updated "now" - currentTimeProvider.Set(initialDate.AddHours(2)); - periodicTimer.CallbackOnce(); + CurrentTimeProvider.Set(initialDate.AddHours(2)); + PeriodicTimer.CallbackOnce(); - var jobRuns = repository.GetJobRuns(); + var jobRuns = Repository.GetJobRuns(); Assert.AreEqual(2, jobRuns.Items.Count); - Assert.AreEqual(2, lastIssuedPlan.Count, "Since one JobRun has completed, there should be now 2 jobruns"); - Assert.AreEqual(2, repository.GetJobRuns().Items.Count, "The recurring trigger should should have triggered 2"); + Assert.AreEqual(2, LastIssuedPlan.Count, "Since one JobRun has completed, there should be now 2 jobruns"); + Assert.AreEqual(2, Repository.GetJobRuns().Items.Count, "The recurring trigger should should have triggered 2"); } [TestMethod] public void NoParallelExecutionEnabled_TriggerWhileJobIsStillRunning_NextJobRunIsPrevented() { var initialDate = new DateTime(2017, 02, 01, 15, 42, 12, DateTimeKind.Utc); - currentTimeProvider.Set(initialDate); + CurrentTimeProvider.Set(initialDate); - var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = demoJob1Id, IsActive = true, NoParallelExecution = true }; + var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = DemoJob1Id, IsActive = true, NoParallelExecution = true }; // This triggers the first jobrun - AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); + AddAndSignalNewTrigger(DemoJob1Id, recurringTrigger); // Simulate that the jobRun has started - var addedJobRun = repository.GetJobRunsByTriggerId(recurringTrigger.JobId, recurringTrigger.Id).Items.Single(); + var addedJobRun = Repository.GetJobRunsByTriggerId(recurringTrigger.JobId, recurringTrigger.Id).Items.Single(); addedJobRun.State = JobRunStates.Processing; - repository.Update(addedJobRun); + Repository.Update(addedJobRun); // Make sure the cron in the recurring trigger will base on an updated "now" - currentTimeProvider.Set(initialDate.AddHours(2)); - periodicTimer.CallbackOnce(); + CurrentTimeProvider.Set(initialDate.AddHours(2)); + PeriodicTimer.CallbackOnce(); - var jobRuns = repository.GetJobRuns(); + var jobRuns = Repository.GetJobRuns(); Assert.AreEqual(1, jobRuns.Items.Count, "Creating new jobruns should be prevented if a JobRun is not yet completed for the trigger"); - Assert.AreEqual(1, lastIssuedPlan.Count, "It doesn't mather how often the Callback for recurring trigger scheduling is called, as long as there is a job running, there shoulnd be any additional jobs"); + Assert.AreEqual(1, LastIssuedPlan.Count, "It doesn't mather how often the Callback for recurring trigger scheduling is called, as long as there is a job running, there shoulnd be any additional jobs"); } [TestMethod] public void RecurringTrigger_WhenAddedBeforeStart_ShouldTriggerOneRun() { - scheduler.Stop(); + Scheduler.Stop(); var futureDate = new DateTime(2017, 02, 01, 15, 42, 12, DateTimeKind.Utc); - currentTimeProvider.Set(futureDate); + CurrentTimeProvider.Set(futureDate); - var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = demoJob1Id, IsActive = true }; + var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = DemoJob1Id, IsActive = true }; // This triggers the first job run - repository.AddJob(new Job { Id = demoJob1Id }); - repository.SaveAddTrigger(demoJob1Id, recurringTrigger); + Repository.AddJob(new Job { Id = DemoJob1Id }); + Repository.SaveAddTrigger(DemoJob1Id, recurringTrigger); - scheduler.Start(); + Scheduler.Start(); - var jobRuns = repository.GetJobRuns(); + var jobRuns = Repository.GetJobRuns(); Assert.AreEqual(1, jobRuns.Items.Count, "There should only be one jobrun"); Assert.AreEqual(futureDate.Date, jobRuns.Items[0].PlannedStartDateTimeUtc.Date); @@ -278,22 +278,22 @@ public void RecurringTrigger_WhenAddedBeforeStart_ShouldTriggerOneRun() public void RecurringTrigger_WhileRunIsIncomplete_ShouldNotRaiseNewRunsAtTheSameTime() { var futureDate = new DateTime(2017, 02, 01, 15, 42, 12, DateTimeKind.Utc); - currentTimeProvider.Set(futureDate); + CurrentTimeProvider.Set(futureDate); var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", - JobId = demoJob1Id, + JobId = DemoJob1Id, IsActive = true }; // This triggers the first job run - AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); + AddAndSignalNewTrigger(DemoJob1Id, recurringTrigger); - currentTimeProvider.AddSecond(); - periodicTimer.CallbackOnce(); + CurrentTimeProvider.AddSecond(); + PeriodicTimer.CallbackOnce(); - var jobRuns = repository.GetJobRuns(); + var jobRuns = Repository.GetJobRuns(); Assert.AreEqual(1, jobRuns.Items.Count, "The periodic callback should not create new jobruns if they would start at the same time (== planned starttime has not changed)"); } @@ -302,22 +302,22 @@ public void RecurringTrigger_WhileRunIsIncomplete_ShouldNotRaiseNewRunsAtTheSame public void RecurringTrigger_EndDateInPast_DoesNotTriggerRun() { var currentNow = new DateTime(2017, 02, 01, 15, 42, 00, DateTimeKind.Utc); - currentTimeProvider.Set(currentNow); + CurrentTimeProvider.Set(currentNow); var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", - JobId = demoJob1Id, + JobId = DemoJob1Id, IsActive = true, EndDateTimeUtc = currentNow.AddDays(-1) }; // This triggers the first job run - AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); + AddAndSignalNewTrigger(DemoJob1Id, recurringTrigger); - periodicTimer.CallbackOnce(); + PeriodicTimer.CallbackOnce(); - var jobRuns = repository.GetJobRuns(); + var jobRuns = Repository.GetJobRuns(); Assert.AreEqual(0, jobRuns.Items.Count, "The trigger is not valid anymore and should not trigger a run"); } @@ -326,16 +326,16 @@ public void RecurringTrigger_EndDateInPast_DoesNotTriggerRun() public void RecurringTrigger_StartDateInFuture_FirstRunIsAtStartDate() { var currentNow = new DateTime(2017, 02, 01, 15, 42, 00, DateTimeKind.Utc); - currentTimeProvider.Set(currentNow); + CurrentTimeProvider.Set(currentNow); - var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = demoJob1Id, IsActive = true, StartDateTimeUtc = currentNow.AddDays(1) }; + var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = DemoJob1Id, IsActive = true, StartDateTimeUtc = currentNow.AddDays(1) }; // This triggers the first jobrun - AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); + AddAndSignalNewTrigger(DemoJob1Id, recurringTrigger); - periodicTimer.CallbackOnce(); + PeriodicTimer.CallbackOnce(); - var jobRuns = repository.GetJobRuns(); + var jobRuns = Repository.GetJobRuns(); Assert.AreEqual(1, jobRuns.Items.Count, "A startdate in the future should trigger the run"); Assert.AreEqual(currentNow.AddDays(1).Date, jobRuns.Items[0].PlannedStartDateTimeUtc.Date); @@ -345,16 +345,16 @@ public void RecurringTrigger_StartDateInFuture_FirstRunIsAtStartDate() public void RecurringTrigger_StartDateInPast_FirstRunIsAtCurrentNow() { var currentNow = new DateTime(2017, 02, 01, 15, 42, 00, DateTimeKind.Utc); - currentTimeProvider.Set(currentNow); + CurrentTimeProvider.Set(currentNow); - var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = demoJob1Id, IsActive = true, StartDateTimeUtc = currentNow.AddDays(-1) }; + var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", JobId = DemoJob1Id, IsActive = true, StartDateTimeUtc = currentNow.AddDays(-1) }; // This triggers the first jobrun - AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); + AddAndSignalNewTrigger(DemoJob1Id, recurringTrigger); - periodicTimer.CallbackOnce(); + PeriodicTimer.CallbackOnce(); - var jobRuns = repository.GetJobRuns(); + var jobRuns = Repository.GetJobRuns(); Assert.AreEqual(1, jobRuns.Items.Count, "A startdate in the future should trigger the run"); Assert.AreEqual(currentNow.Date, jobRuns.Items[0].PlannedStartDateTimeUtc.Date); @@ -366,38 +366,38 @@ public void RecurringTrigger_StartAndEndDateCoversNow_DoesNotTriggerRun() var recurringTrigger = new RecurringTrigger { Definition = "* * * * *", - JobId = demoJob1Id, + JobId = DemoJob1Id, IsActive = true, StartDateTimeUtc = DateTime.UtcNow.AddDays(-1), EndDateTimeUtc = DateTime.UtcNow.AddDays(1) }; // This triggers the first job run - AddAndSignalNewTrigger(demoJob1Id, recurringTrigger); + AddAndSignalNewTrigger(DemoJob1Id, recurringTrigger); - periodicTimer.CallbackOnce(); + PeriodicTimer.CallbackOnce(); - var jobRuns = repository.GetJobRuns(); + var jobRuns = Repository.GetJobRuns(); Assert.AreEqual(1, jobRuns.Items.Count, "The trigger should cause a job run because its valid right now"); } private void AddAndSignalNewTrigger(long jobId, InstantTrigger trigger) { - repository.SaveAddTrigger(jobId, trigger); - scheduler.OnTriggerAdded(jobId, trigger.Id); + Repository.SaveAddTrigger(jobId, trigger); + Scheduler.OnTriggerAdded(jobId, trigger.Id); } private void AddAndSignalNewTrigger(long jobId, ScheduledTrigger trigger) { - repository.SaveAddTrigger(jobId, trigger); - scheduler.OnTriggerAdded(jobId, trigger.Id); + Repository.SaveAddTrigger(jobId, trigger); + Scheduler.OnTriggerAdded(jobId, trigger.Id); } private void AddAndSignalNewTrigger(long jobId, RecurringTrigger trigger) { - repository.SaveAddTrigger(jobId, trigger); - scheduler.OnTriggerAdded(jobId, trigger.Id); + Repository.SaveAddTrigger(jobId, trigger); + Scheduler.OnTriggerAdded(jobId, trigger.Id); } } } diff --git a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/SchedulerTests.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/SchedulerTests.cs index fd1ab82..e09cf90 100644 --- a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/SchedulerTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/SchedulerTests.cs @@ -12,7 +12,7 @@ public class SchedulerTests : TestBase public void SchedulerStarts_HasScheduledJobsFromPast_WillSetToOmitted() { var currentTime = new DateTime(2017, 04, 06, 0, 0, 0); - currentTimeProvider.Set(currentTime); + CurrentTimeProvider.Set(currentTime); // Add a couple of jobruns AddJobRun(currentTime.AddDays(-1), JobRunStates.Scheduled); @@ -21,10 +21,10 @@ public void SchedulerStarts_HasScheduledJobsFromPast_WillSetToOmitted() AddJobRun(currentTime.AddDays(-1), JobRunStates.Finishing); AddJobRun(currentTime.AddDays(-1), JobRunStates.Failed); - scheduler.Start(); + Scheduler.Start(); - var schedulerJobRuns = repository.GetJobRunsByState(JobRunStates.Scheduled); - var omittedJobRuns = repository.GetJobRunsByState(JobRunStates.Omitted); + var schedulerJobRuns = Repository.GetJobRunsByState(JobRunStates.Scheduled); + var omittedJobRuns = Repository.GetJobRunsByState(JobRunStates.Omitted); Assert.AreEqual(0, schedulerJobRuns.Items.Count, "The only past scheduled jobrun should have been set to omitted"); Assert.AreEqual(1, omittedJobRuns.Items.Count, "It's assumed that the previous scheduled jobrun is now omitted"); @@ -34,14 +34,14 @@ public void SchedulerStarts_HasScheduledJobsFromPast_WillSetToOmitted() public void SchedulerStarts_HasScheduledJobsInFuture_WillNotTouch() { var currentTime = new DateTime(2017, 04, 06, 0, 0, 0); - currentTimeProvider.Set(currentTime); + CurrentTimeProvider.Set(currentTime); // Add a couple of jobruns AddJobRun(currentTime.AddDays(1), JobRunStates.Scheduled); - scheduler.Start(); + Scheduler.Start(); - var schedulerJobRuns = repository.GetJobRunsByState(JobRunStates.Scheduled); + var schedulerJobRuns = Repository.GetJobRunsByState(JobRunStates.Scheduled); Assert.AreEqual(1, schedulerJobRuns.Items.Count, "A future scheduled jobrun should not be omitted"); } @@ -50,7 +50,7 @@ public void SchedulerStarts_HasScheduledJobsInFuture_WillNotTouch() public void SchedulerStarts_HasSRunningJobsFromPast_WillSetToFailed() { var currentTime = new DateTime(2017, 04, 06, 0, 0, 0); - currentTimeProvider.Set(currentTime); + CurrentTimeProvider.Set(currentTime); // Add a couple of jobruns AddJobRun(currentTime.AddDays(-1), JobRunStates.Preparing); @@ -65,17 +65,17 @@ public void SchedulerStarts_HasSRunningJobsFromPast_WillSetToFailed() AddJobRun(currentTime.AddDays(-1), JobRunStates.Completed); - scheduler.Start(); + Scheduler.Start(); - var failedJobRuns = repository.GetJobRunsByState(JobRunStates.Failed); + var failedJobRuns = Repository.GetJobRunsByState(JobRunStates.Failed); - Assert.AreEqual(9, failedJobRuns.Items.Count, $"Still have jobruns with the following states:\n {string.Join(", ", repository.GetJobRuns().Items.Select(jr => jr.State))}"); + Assert.AreEqual(9, failedJobRuns.Items.Count, $"Still have jobruns with the following states:\n {string.Join(", ", Repository.GetJobRuns().Items.Select(jr => jr.State))}"); } [TestMethod] public void GivenMultipleScheduledJobRuns_WhenLimitingAmountOfParallelRuns_ThenNewestShouldBeExecuted() { - scheduler.Start(); + Scheduler.Start(); var jobId = AddAndSaveJob(1); var dateFrom2091 = new DateTime(2091, 5, 17); var dateFrom2092 = new DateTime(2092, 7, 12); @@ -83,71 +83,71 @@ public void GivenMultipleScheduledJobRuns_WhenLimitingAmountOfParallelRuns_ThenN var firstTrigger = new ScheduledTrigger { JobId = jobId, IsActive = true, StartDateTimeUtc = dateFrom2091 }; var secondTrigger = new ScheduledTrigger { JobId = jobId, IsActive = true, StartDateTimeUtc = dateFrom2092 }; var thirdTrigger = new ScheduledTrigger { JobId = jobId, IsActive = true, StartDateTimeUtc = dateFrom2093 }; - repository.SaveAddTrigger(jobId, firstTrigger); - repository.SaveAddTrigger(jobId, secondTrigger); - repository.SaveAddTrigger(jobId, thirdTrigger); + Repository.SaveAddTrigger(jobId, firstTrigger); + Repository.SaveAddTrigger(jobId, secondTrigger); + Repository.SaveAddTrigger(jobId, thirdTrigger); - scheduler.OnTriggerAdded(jobId, firstTrigger.Id); - scheduler.OnTriggerAdded(jobId, secondTrigger.Id); + Scheduler.OnTriggerAdded(jobId, firstTrigger.Id); + Scheduler.OnTriggerAdded(jobId, secondTrigger.Id); - Assert.AreEqual(1, lastIssuedPlan.Count); - Assert.AreEqual(dateFrom2091, lastIssuedPlan.Single().PlannedStartDateTimeUtc); + Assert.AreEqual(1, LastIssuedPlan.Count); + Assert.AreEqual(dateFrom2091, LastIssuedPlan.Single().PlannedStartDateTimeUtc); - scheduler.OnTriggerAdded(jobId, thirdTrigger.Id); + Scheduler.OnTriggerAdded(jobId, thirdTrigger.Id); - Assert.AreEqual(1, lastIssuedPlan.Count); - Assert.AreEqual(dateFrom2091, lastIssuedPlan.Single().PlannedStartDateTimeUtc); + Assert.AreEqual(1, LastIssuedPlan.Count); + Assert.AreEqual(dateFrom2091, LastIssuedPlan.Single().PlannedStartDateTimeUtc); } [TestMethod] public void GivenMultipleScheduledJobRuns_WhenLimitingAmountOfParallelRuns_ThenLatestShouldNotBeExecuted() { - scheduler.Start(); + Scheduler.Start(); var jobId = AddAndSaveJob(2); var startTimeTrigger1 = new DateTime(2100, 1, 1); var startTimeTrigger2 = new DateTime(2200, 1, 1); var firstTrigger = new ScheduledTrigger { JobId = jobId, IsActive = true, StartDateTimeUtc = startTimeTrigger1 }; var secondTrigger = new ScheduledTrigger { JobId = jobId, IsActive = true, StartDateTimeUtc = startTimeTrigger2 }; - repository.SaveAddTrigger(jobId, firstTrigger); - repository.SaveAddTrigger(jobId, secondTrigger); + Repository.SaveAddTrigger(jobId, firstTrigger); + Repository.SaveAddTrigger(jobId, secondTrigger); AddJobRun(new DateTime(2050, 1, 1), JobRunStates.Started, jobId); - scheduler.OnTriggerAdded(jobId, firstTrigger.Id); + Scheduler.OnTriggerAdded(jobId, firstTrigger.Id); - scheduler.OnTriggerAdded(jobId, secondTrigger.Id); + Scheduler.OnTriggerAdded(jobId, secondTrigger.Id); - Assert.AreEqual(1, lastIssuedPlan.Count); - Assert.AreEqual(startTimeTrigger1, lastIssuedPlan.Single().PlannedStartDateTimeUtc); + Assert.AreEqual(1, LastIssuedPlan.Count); + Assert.AreEqual(startTimeTrigger1, LastIssuedPlan.Single().PlannedStartDateTimeUtc); } [TestMethod] public void ShouldQueueJobWhenJobRunEnded() { - scheduler.Start(); + Scheduler.Start(); var jobId = AddAndSaveJob(1); var startTimeTrigger1 = new DateTime(2100, 1, 1); var startTimeTrigger2 = new DateTime(2200, 1, 1); var firstTrigger = new ScheduledTrigger { JobId = jobId, IsActive = true, StartDateTimeUtc = startTimeTrigger1 }; var secondTrigger = new ScheduledTrigger { JobId = jobId, IsActive = true, StartDateTimeUtc = startTimeTrigger2 }; - repository.SaveAddTrigger(jobId, firstTrigger); - repository.SaveAddTrigger(jobId, secondTrigger); - scheduler.OnTriggerAdded(jobId, firstTrigger.Id); - var jobRunId = lastIssuedPlan.Single().Id; + Repository.SaveAddTrigger(jobId, firstTrigger); + Repository.SaveAddTrigger(jobId, secondTrigger); + Scheduler.OnTriggerAdded(jobId, firstTrigger.Id); + var jobRunId = LastIssuedPlan.Single().Id; - scheduler.OnJobRunEnded(jobRunId); + Scheduler.OnJobRunEnded(jobRunId); - Assert.AreEqual(1, lastIssuedPlan.Count); - Assert.AreEqual(startTimeTrigger1, lastIssuedPlan.Single().PlannedStartDateTimeUtc); + Assert.AreEqual(1, LastIssuedPlan.Count); + Assert.AreEqual(startTimeTrigger1, LastIssuedPlan.Single().PlannedStartDateTimeUtc); } private void AddJobRun(DateTime plannedStartDateTimeUtc, JobRunStates state, long jobId = 0) { - var accordingJobId = jobId != 0 ? jobId : demoJob1Id; - var scheduledTrigger = new InstantTrigger() { JobId = accordingJobId, IsActive = true }; - var demoJob = repository.GetJob(accordingJobId); + var accordingJobId = jobId != 0 ? jobId : DemoJob1Id; + var scheduledTrigger = new InstantTrigger { JobId = accordingJobId, IsActive = true }; + var demoJob = Repository.GetJob(accordingJobId); - var jobRun = repository.SaveNewJobRun(demoJob, scheduledTrigger, plannedStartDateTimeUtc); + var jobRun = Repository.SaveNewJobRun(demoJob, scheduledTrigger, plannedStartDateTimeUtc); jobRun.State = state; - repository.Update(jobRun); + Repository.Update(jobRun); } private long AddAndSaveJob(int maxConcurrentJobRuns) @@ -156,7 +156,7 @@ private long AddAndSaveJob(int maxConcurrentJobRuns) { MaxConcurrentJobRuns = maxConcurrentJobRuns }; - repository.AddJob(job); + Repository.AddJob(job); return job.Id; } } diff --git a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/TestBase.cs b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/TestBase.cs index 0cf10a4..63612d3 100644 --- a/source/Jobbr.Server.IntegrationTests/Components/Scheduler/TestBase.cs +++ b/source/Jobbr.Server.IntegrationTests/Components/Scheduler/TestBase.cs @@ -12,32 +12,43 @@ namespace Jobbr.Server.IntegrationTests.Components.Scheduler { public class TestBase { - protected long demoJob1Id = 1; - protected JobbrRepository repository; - protected DefaultScheduler scheduler; - protected List lastIssuedPlan; - protected PeriodicTimerMock periodicTimer; - protected ManualTimeProvider currentTimeProvider; - - public TestBase() + protected TestBase() { - repository = new JobbrRepository(NullLoggerFactory.Instance, new InMemoryJobStorageProvider()); + Repository = new JobbrRepository(NullLoggerFactory.Instance, new InMemoryJobStorageProvider()); var executorMock = new Mock(); - executorMock.Setup(e => e.OnPlanChanged(It.IsNotNull>())).Callback>(p => lastIssuedPlan = p); + executorMock.Setup(e => e.OnPlanChanged(It.IsNotNull>())).Callback>(p => LastIssuedPlan = p); - periodicTimer = new PeriodicTimerMock(); + PeriodicTimer = new PeriodicTimerMock(); - currentTimeProvider = new ManualTimeProvider(); + CurrentTimeProvider = new ManualTimeProvider(); var job = new Job(); - repository.AddJob(job); - demoJob1Id = job.Id; + Repository.AddJob(job); + DemoJob1Id = job.Id; - scheduler = new DefaultScheduler(NullLoggerFactory.Instance, repository, executorMock.Object, - new InstantJobRunPlaner(currentTimeProvider), new ScheduledJobRunPlaner(currentTimeProvider), - new RecurringJobRunPlaner(NullLoggerFactory.Instance, repository, currentTimeProvider), new DefaultSchedulerConfiguration(), - periodicTimer, currentTimeProvider); + Scheduler = new DefaultScheduler( + NullLoggerFactory.Instance, + Repository, + executorMock.Object, + new InstantJobRunPlaner(CurrentTimeProvider), + new ScheduledJobRunPlaner(CurrentTimeProvider), + new RecurringJobRunPlaner(NullLoggerFactory.Instance, Repository, CurrentTimeProvider), + new DefaultSchedulerConfiguration(), + PeriodicTimer, + CurrentTimeProvider); } + + protected long DemoJob1Id { get; } + + protected JobbrRepository Repository { get; } + + protected DefaultScheduler Scheduler { get; } + + protected List LastIssuedPlan { get; private set; } + + protected PeriodicTimerMock PeriodicTimer { get; } + + protected ManualTimeProvider CurrentTimeProvider { get; } } } \ No newline at end of file diff --git a/source/Jobbr.Server.IntegrationTests/Integration/Startup/ConfigurationValidationTests.cs b/source/Jobbr.Server.IntegrationTests/Integration/Startup/ConfigurationValidationTests.cs index 0c13c73..be93038 100644 --- a/source/Jobbr.Server.IntegrationTests/Integration/Startup/ConfigurationValidationTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Integration/Startup/ConfigurationValidationTests.cs @@ -9,57 +9,6 @@ namespace Jobbr.Server.IntegrationTests.Integration.Startup [TestClass] public class ConfigurationValidationTests { - public class DemoComponent : IJobbrComponent - { - public void Dispose() - { - } - - public void Start() - { - } - - public void Stop() - { - } - } - - public class DemoSettings - { - } - - public class DemoComponentValidator : IConfigurationValidator - { - private readonly Action _func; - private readonly bool _validationShouldFail; - private readonly bool _throwException; - - public Type ConfigurationType { get; set; } = typeof(DemoSettings); - - public DemoComponentValidator(bool validationShouldFail, bool throwException) - { - _validationShouldFail = validationShouldFail; - _throwException = throwException; - } - - public DemoComponentValidator(Action func) - { - _func = func; - } - - public bool Validate(object configuration) - { - if (_throwException) - { - throw new Exception("Exception from here"); - } - - _func?.Invoke((DemoSettings)configuration); - - return !_validationShouldFail; - } - } - [TestMethod] public void ValidatorForSettings_WhenRegistered_IsCalled() { @@ -126,5 +75,56 @@ public void ValidatorForSettings_ThrowsException_PreventsStart() jobbr.Start(); } + + public class DemoComponent : IJobbrComponent + { + public void Dispose() + { + } + + public void Start() + { + } + + public void Stop() + { + } + } + + private class DemoSettings + { + } + + private class DemoComponentValidator : IConfigurationValidator + { + private readonly Action _func; + private readonly bool _validationShouldFail; + private readonly bool _throwException; + + public DemoComponentValidator(bool validationShouldFail, bool throwException) + { + _validationShouldFail = validationShouldFail; + _throwException = throwException; + } + + public DemoComponentValidator(Action func) + { + _func = func; + } + + public Type ConfigurationType { get; set; } = typeof(DemoSettings); + + public bool Validate(object configuration) + { + if (_throwException) + { + throw new Exception("Exception from here"); + } + + _func?.Invoke((DemoSettings)configuration); + + return !_validationShouldFail; + } + } } } diff --git a/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs b/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs index 311e1af..24c3883 100644 --- a/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs +++ b/source/Jobbr.Server.IntegrationTests/Registration/BuilderTests.cs @@ -236,199 +236,195 @@ private static void SetupForSuccessfulRun(Mock storageMock) storageMock.Setup(s => s.GetJobRunsByJobId(It.IsAny(), 1, int.MaxValue, false)).Returns(CreatePagedResult()); storageMock.Setup(s => s.GetJobRunsByTriggerId(anyId, anyId, 1, int.MaxValue, false)).Returns(CreatePagedResult()); } - } - - public interface IPrioritizationStrategy : IComparable - { - } - - public class CustomArtefactStorageAdapter : IArtefactsStorageProvider - { - public void Save(string container, string fileName, Stream content) - { - } - - public Stream Load(string container, string fileName) - { - return null; - } - - public List GetArtefacts(string container) - { - return null; - } - } - - public class CustomJobStorageProvider : IJobStorageProvider - { - public void AddJob(Job job) - { - throw new NotImplementedException(); - } - - public void DeleteJob(long jobId) - { - throw new NotImplementedException(); - } - - public long GetJobsCount() - { - throw new NotImplementedException(); - } - - public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) - { - throw new NotImplementedException(); - } - - public Job GetJobById(long id) - { - throw new NotImplementedException(); - } - - public Job GetJobByUniqueName(string identifier) - { - throw new NotImplementedException(); - } - - public void Update(Job job) - { - throw new NotImplementedException(); - } - - public void AddTrigger(long jobId, RecurringTrigger trigger) - { - throw new NotImplementedException(); - } - - public void AddTrigger(long jobId, InstantTrigger trigger) - { - throw new NotImplementedException(); - } - - public void AddTrigger(long jobId, ScheduledTrigger trigger) - { - throw new NotImplementedException(); - } - - public JobTriggerBase GetTriggerById(long jobId, long triggerId) - { - throw new NotImplementedException(); - } - - public PagedResult GetTriggersByJobId(long jobId, int page = 1, int pageSize = 50, bool showDeleted = false) - { - throw new NotImplementedException(); - } - - public PagedResult GetActiveTriggers(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, params string[] sort) - { - throw new NotImplementedException(); - } - - public void DisableTrigger(long jobId, long triggerId) - { - throw new NotImplementedException(); - } - public void EnableTrigger(long jobId, long triggerId) - { - throw new NotImplementedException(); - } - - public void DeleteTrigger(long jobId, long triggerId) - { - throw new NotImplementedException(); - } - - public void Update(long jobId, InstantTrigger trigger) - { - throw new NotImplementedException(); - } - - public void Update(long jobId, ScheduledTrigger trigger) - { - throw new NotImplementedException(); - } - - public void Update(long jobId, RecurringTrigger trigger) - { - throw new NotImplementedException(); - } - - public void AddJobRun(JobRun jobRun) - { - throw new NotImplementedException(); - } - - public JobRun GetJobRunById(long id) - { - throw new NotImplementedException(); - } - - public JobRun GetLastJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) - { - throw new NotImplementedException(); - } - - public JobRun GetNextJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) - { - throw new NotImplementedException(); - } - - public PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) - { - throw new NotImplementedException(); - } - - public PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) - { - throw new NotImplementedException(); - } - - public PagedResult GetJobRunsByUserId(string userId, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) - { - throw new NotImplementedException(); - } - - public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) - { - throw new NotImplementedException(); - } - - public PagedResult GetJobRunsByUserDisplayName(string userDisplayName, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) - { - throw new NotImplementedException(); - } - - public PagedResult GetJobRunsByState(JobRunStates state, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) - { - throw new NotImplementedException(); - } - - public PagedResult GetJobRunsByStates(JobRunStates[] states, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) - { - throw new NotImplementedException(); - } - - public void Update(JobRun jobRun) - { - throw new NotImplementedException(); - } - - public void UpdateProgress(long jobRunId, double? progress) - { - throw new NotImplementedException(); - } - - public void ApplyRetention(DateTimeOffset date) - { - throw new NotImplementedException(); - } - - public bool IsAvailable() - { - throw new NotImplementedException(); + private class CustomArtefactStorageAdapter : IArtefactsStorageProvider + { + public void Save(string container, string fileName, Stream content) + { + } + + public Stream Load(string container, string fileName) + { + return null; + } + + public List GetArtefacts(string container) + { + return null; + } + } + + private class CustomJobStorageProvider : IJobStorageProvider + { + public void AddJob(Job job) + { + throw new NotImplementedException(); + } + + public void DeleteJob(long jobId) + { + throw new NotImplementedException(); + } + + public long GetJobsCount() + { + throw new NotImplementedException(); + } + + public PagedResult GetJobs(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) + { + throw new NotImplementedException(); + } + + public Job GetJobById(long id) + { + throw new NotImplementedException(); + } + + public Job GetJobByUniqueName(string identifier) + { + throw new NotImplementedException(); + } + + public void Update(Job job) + { + throw new NotImplementedException(); + } + + public void AddTrigger(long jobId, RecurringTrigger trigger) + { + throw new NotImplementedException(); + } + + public void AddTrigger(long jobId, InstantTrigger trigger) + { + throw new NotImplementedException(); + } + + public void AddTrigger(long jobId, ScheduledTrigger trigger) + { + throw new NotImplementedException(); + } + + public JobTriggerBase GetTriggerById(long jobId, long triggerId) + { + throw new NotImplementedException(); + } + + public PagedResult GetTriggersByJobId(long jobId, int page = 1, int pageSize = 50, bool showDeleted = false) + { + throw new NotImplementedException(); + } + + public PagedResult GetActiveTriggers(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, params string[] sort) + { + throw new NotImplementedException(); + } + + public void DisableTrigger(long jobId, long triggerId) + { + throw new NotImplementedException(); + } + + public void EnableTrigger(long jobId, long triggerId) + { + throw new NotImplementedException(); + } + + public void DeleteTrigger(long jobId, long triggerId) + { + throw new NotImplementedException(); + } + + public void Update(long jobId, InstantTrigger trigger) + { + throw new NotImplementedException(); + } + + public void Update(long jobId, ScheduledTrigger trigger) + { + throw new NotImplementedException(); + } + + public void Update(long jobId, RecurringTrigger trigger) + { + throw new NotImplementedException(); + } + + public void AddJobRun(JobRun jobRun) + { + throw new NotImplementedException(); + } + + public JobRun GetJobRunById(long id) + { + throw new NotImplementedException(); + } + + public JobRun GetLastJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) + { + throw new NotImplementedException(); + } + + public JobRun GetNextJobRunByTriggerId(long jobId, long triggerId, DateTime utcNow) + { + throw new NotImplementedException(); + } + + public PagedResult GetJobRuns(int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) + { + throw new NotImplementedException(); + } + + public PagedResult GetJobRunsByJobId(int jobId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) + { + throw new NotImplementedException(); + } + + public PagedResult GetJobRunsByUserId(string userId, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) + { + throw new NotImplementedException(); + } + + public PagedResult GetJobRunsByTriggerId(long jobId, long triggerId, int page = 1, int pageSize = 50, bool showDeleted = false, params string[] sort) + { + throw new NotImplementedException(); + } + + public PagedResult GetJobRunsByUserDisplayName(string userDisplayName, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, bool showDeleted = false, params string[] sort) + { + throw new NotImplementedException(); + } + + public PagedResult GetJobRunsByState(JobRunStates state, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) + { + throw new NotImplementedException(); + } + + public PagedResult GetJobRunsByStates(JobRunStates[] states, int page = 1, int pageSize = 50, string jobTypeFilter = null, string jobUniqueNameFilter = null, string query = null, bool showDeleted = false, params string[] sort) + { + throw new NotImplementedException(); + } + + public void Update(JobRun jobRun) + { + throw new NotImplementedException(); + } + + public void UpdateProgress(long jobRunId, double? progress) + { + throw new NotImplementedException(); + } + + public void ApplyRetention(DateTimeOffset date) + { + throw new NotImplementedException(); + } + + public bool IsAvailable() + { + throw new NotImplementedException(); + } } } } diff --git a/source/Jobbr.Server.UnitTests/ShouldDateTimeExtensions.cs b/source/Jobbr.Server.UnitTests/ShouldDateTimeExtensions.cs index 4b110f8..519e8a4 100644 --- a/source/Jobbr.Server.UnitTests/ShouldDateTimeExtensions.cs +++ b/source/Jobbr.Server.UnitTests/ShouldDateTimeExtensions.cs @@ -12,9 +12,9 @@ public static class ShouldDateTimeExtensions /// /// The value to check against. /// Custom error message to display when an error occurs. - public static DateTime ShouldBeUtcNowWithTolerance(this DateTime actual, string customMessage = null) + public static void ShouldBeUtcNowWithTolerance(this DateTime actual, string customMessage = null) { - return actual.ShouldBeUtcNowWithTolerance(DefaultOffsetTolerance, customMessage); + actual.ShouldBeUtcNowWithTolerance(DefaultOffsetTolerance, customMessage); } /// @@ -23,11 +23,10 @@ public static DateTime ShouldBeUtcNowWithTolerance(this DateTime actual, string /// The value to check against. /// The allowed tolerance for the equality to be checked. /// Custom error message to display when an error occurs. - public static DateTime ShouldBeUtcNowWithTolerance(this DateTime actual, TimeSpan tolerance, string customMessage = null) + private static void ShouldBeUtcNowWithTolerance(this DateTime actual, TimeSpan tolerance, string customMessage = null) { var offset = DateTime.UtcNow - actual; offset.ShouldBeLessThanOrEqualTo(tolerance, customMessage); - return actual; } } } diff --git a/source/Jobbr.Server/Scheduling/DefaultScheduler.cs b/source/Jobbr.Server/Scheduling/DefaultScheduler.cs index 3bb9813..0153007 100644 --- a/source/Jobbr.Server/Scheduling/DefaultScheduler.cs +++ b/source/Jobbr.Server/Scheduling/DefaultScheduler.cs @@ -39,8 +39,16 @@ public class DefaultScheduler : IJobScheduler /// Scheduler configuration. /// Periodic timer. /// DateTime provider. - public DefaultScheduler(ILoggerFactory loggerFactory, IJobbrRepository jobbrRepository, IJobExecutor executor, IInstantJobRunPlaner instantJobRunPlanner, IScheduledJobRunPlaner scheduledJobRunPlanner, - IRecurringJobRunPlaner recurringJobRunPlanner, DefaultSchedulerConfiguration schedulerConfiguration, IPeriodicTimer periodicTimer, IDateTimeProvider dateTimeProvider) + public DefaultScheduler( + ILoggerFactory loggerFactory, + IJobbrRepository jobbrRepository, + IJobExecutor executor, + IInstantJobRunPlaner instantJobRunPlanner, + IScheduledJobRunPlaner scheduledJobRunPlanner, + IRecurringJobRunPlaner recurringJobRunPlanner, + DefaultSchedulerConfiguration schedulerConfiguration, + IPeriodicTimer periodicTimer, + IDateTimeProvider dateTimeProvider) { _logger = loggerFactory.CreateLogger(); _jobbrRepository = jobbrRepository; diff --git a/source/submodules/devsupport b/source/submodules/devsupport index 0d47c19..1c1496c 160000 --- a/source/submodules/devsupport +++ b/source/submodules/devsupport @@ -1 +1 @@ -Subproject commit 0d47c199f93b0be8ea00443702bc44797d2e1549 +Subproject commit 1c1496c998a840a10580ce589a9fc04680df0891 From e995dc856e3c85d993bc93124c0a9e1448c89663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Thu, 16 Mar 2023 11:30:21 +0100 Subject: [PATCH 36/41] Align dependencies in the nuspec file --- source/Jobbr.Server.nuspec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/source/Jobbr.Server.nuspec b/source/Jobbr.Server.nuspec index 2a4b0db..86f6257 100644 --- a/source/Jobbr.Server.nuspec +++ b/source/Jobbr.Server.nuspec @@ -17,13 +17,13 @@ - + - - + + From e445a1ac9cb9a57c6c7b187c3ea1a00cb5a9f758 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Thu, 16 Mar 2023 16:13:38 +0100 Subject: [PATCH 37/41] Use transient life style for MessageDispatcher --- source/Jobbr.Server/Builder/DefaultContainer.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/Jobbr.Server/Builder/DefaultContainer.cs b/source/Jobbr.Server/Builder/DefaultContainer.cs index 855ded6..9ca5e64 100644 --- a/source/Jobbr.Server/Builder/DefaultContainer.cs +++ b/source/Jobbr.Server/Builder/DefaultContainer.cs @@ -13,6 +13,7 @@ using Jobbr.Server.Storage; using Microsoft.Extensions.Logging; using SimpleInjector; +using SimpleInjector.Lifestyles; using TinyMessenger; namespace Jobbr.Server.Builder @@ -79,7 +80,7 @@ private void AddComponentModelImplementations() Register(Lifestyle.Singleton); Register(Lifestyle.Singleton); - Register(Lifestyle.Singleton); + Register(Lifestyle.Transient); Register(Lifestyle.Singleton); Register(Lifestyle.Singleton); From f7f38e63404b26718a0535b14b5b6a1c1344da0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Thu, 16 Mar 2023 16:45:01 +0100 Subject: [PATCH 38/41] Fix JobbrServer DI registration --- source/Jobbr.Server/Builder/DefaultContainer.cs | 2 +- source/Jobbr.Server/Builder/JobbrBuilder.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/source/Jobbr.Server/Builder/DefaultContainer.cs b/source/Jobbr.Server/Builder/DefaultContainer.cs index 9ca5e64..b8eb512 100644 --- a/source/Jobbr.Server/Builder/DefaultContainer.cs +++ b/source/Jobbr.Server/Builder/DefaultContainer.cs @@ -80,7 +80,7 @@ private void AddComponentModelImplementations() Register(Lifestyle.Singleton); Register(Lifestyle.Singleton); - Register(Lifestyle.Transient); + Register(Lifestyle.Singleton); Register(Lifestyle.Singleton); Register(Lifestyle.Singleton); diff --git a/source/Jobbr.Server/Builder/JobbrBuilder.cs b/source/Jobbr.Server/Builder/JobbrBuilder.cs index 466cf79..05cf1f1 100644 --- a/source/Jobbr.Server/Builder/JobbrBuilder.cs +++ b/source/Jobbr.Server/Builder/JobbrBuilder.cs @@ -38,7 +38,7 @@ public JobbrBuilder(ILoggerFactory loggerFactory) /// A new . public JobbrServer Create(int maxConcurrentJobs = 4) { - _dependencyContainer.Register(); + _dependencyContainer.Register(Lifestyle.Transient); // Register default implementations if user did not specify any separate if (_dependencyContainer.GetRegistration(typeof(IJobStorageProvider)) == null) From 396a8566acc129ef27a559ceb686736bc3921a29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Fri, 17 Mar 2023 11:17:07 +0100 Subject: [PATCH 39/41] Remove JobbrServer from DI container Create the one instance manually, otherwise the WebHostBuilder might create a new instance for every sub-component, causing multiple calls to WireUp and thus multiple subscriptions on the MessageDispatcher --- source/Jobbr.Server/Builder/JobbrBuilder.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/source/Jobbr.Server/Builder/JobbrBuilder.cs b/source/Jobbr.Server/Builder/JobbrBuilder.cs index 05cf1f1..7696211 100644 --- a/source/Jobbr.Server/Builder/JobbrBuilder.cs +++ b/source/Jobbr.Server/Builder/JobbrBuilder.cs @@ -1,12 +1,16 @@ using System; +using System.Collections.Generic; using Jobbr.ComponentModel.ArtefactStorage; using Jobbr.ComponentModel.Execution; using Jobbr.ComponentModel.JobStorage; using Jobbr.ComponentModel.Management; using Jobbr.ComponentModel.Registration; +using Jobbr.Server.Core.Messaging; +using Jobbr.Server.JobRegistry; using Jobbr.Server.Scheduling; using Jobbr.Server.Storage; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; using SimpleInjector; namespace Jobbr.Server.Builder @@ -38,8 +42,6 @@ public JobbrBuilder(ILoggerFactory loggerFactory) /// A new . public JobbrServer Create(int maxConcurrentJobs = 4) { - _dependencyContainer.Register(Lifestyle.Transient); - // Register default implementations if user did not specify any separate if (_dependencyContainer.GetRegistration(typeof(IJobStorageProvider)) == null) { @@ -80,7 +82,14 @@ public JobbrServer Create(int maxConcurrentJobs = 4) _logger.LogError("No Server Management Service found."); } - return _dependencyContainer.GetInstance(); + return new JobbrServer(_dependencyContainer.GetInstance(), + _dependencyContainer.GetInstance(), + _dependencyContainer.GetInstance(), + _dependencyContainer.GetInstance(), + _dependencyContainer.GetInstance>(), + _dependencyContainer.GetInstance(), + _dependencyContainer.GetInstance(), + _dependencyContainer.GetInstance()); } /// From e9d1effe9e96f771b9411174149f9b65229b868a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Mon, 20 Mar 2023 01:08:13 +0100 Subject: [PATCH 40/41] Add GitHub Actions support --- .github/workflows/ci.yml | 60 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..f1dc3a4 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,60 @@ +name: CI + +on: [push, pull_request] + +env: + DOTNET_CLI_TELEMETRY_OPTOUT: 1 + IGNORE_NORMALISATION_GIT_HEAD_MOVE: 1 + +jobs: + build: + name: ${{ matrix.platform.name }} ${{ matrix.dotnet.name }} + runs-on: ${{ matrix.platform.os }} + + strategy: + fail-fast: false + matrix: + platform: + - { name: Windows VS2022, os: windows-2022 } + - { name: Linux, os: ubuntu-20.04 } + - { name: MacOS, os: macos-12 } + dotnet: + - { name: .NET 6, version: '6.0.x' } + - { name: .NET 7, version: '7.0.x' } + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + submodules: recursive + + - name: Setup .NET ${{ matrix.dotnet.version }} SDK + id: setup-dotnet + uses: actions/setup-dotnet@v3 + with: + dotnet-version: ${{ matrix.dotnet.version }} + - name: Enforce SDK Version + run: dotnet new globaljson --sdk-version ${{ steps.setup-dotnet.outputs.dotnet-version }} --force + - name: Verify SDK Installation + run: dotnet --info + + - name: Install GitVersion + uses: gittools/actions/gitversion/setup@v0 + with: + versionSpec: '5.x' + - name: Determine Version + uses: gittools/actions/gitversion/execute@v0 + with: + useConfigFile: true + updateAssemblyInfo: true + additionalArguments: '/l console' + + - name: Install Dependencies + run: dotnet restore source/Jobbr.Server.sln + - name: Build + run: dotnet build --configuration Release --no-restore source/Jobbr.Server.sln + - name: Test + run: dotnet test --no-restore --verbosity normal source/Jobbr.Server.sln + + - name: NuGet Pack + run: nuget pack source/Jobbr.Server.nuspec -version "${{ env.GitVersion_SemVer }}" -prop "target=Release" \ No newline at end of file From c6f5c76765d4706750e9d50d4706fc9906fcf34c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=BCrrenberger?= Date: Mon, 20 Mar 2023 12:36:25 +0100 Subject: [PATCH 41/41] Update ComponentModel packages to the released versions --- source/Jobbr.Server/Jobbr.Server.csproj | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/source/Jobbr.Server/Jobbr.Server.csproj b/source/Jobbr.Server/Jobbr.Server.csproj index 68348f8..cef6527 100644 --- a/source/Jobbr.Server/Jobbr.Server.csproj +++ b/source/Jobbr.Server/Jobbr.Server.csproj @@ -36,11 +36,11 @@ - - - - - + + + + +