├── OddJob ├── Properties │ └── AssemblyInfo.cs ├── Interfaces │ ├── IJobExecutor.cs │ ├── IOddJobWithMetadata.cs │ ├── IRetryParameters.cs │ ├── IJobFilterMetadata.cs │ ├── IContainerFactory.cs │ ├── IOddJob.cs │ ├── IJobQueueManager.cs │ └── IJobQueueAdder.cs ├── OddJobParameter.cs ├── DefaultJobQueueManagerPriority.cs ├── JobStates.cs ├── DefaultContainerFactory.cs ├── GlutenFree.OddJob.csproj ├── JobLockData.cs ├── GlutenFree.OddJob.nuspec ├── OddJobWithMetaData.cs ├── RetryParameters.cs ├── JobCreator.cs ├── OldDefaultJobExecutor.cs ├── OddJob.cs └── DefaultJobExecutor.cs ├── GlutenFree.OddJob.Manager.WebSharper ├── wsconfig.json ├── Remoting.cs ├── packages.config ├── Web.config ├── Client.cs ├── Web.Debug.config ├── Web.Release.config ├── Properties │ └── AssemblyInfo.cs ├── Server.cs └── Main.html ├── OddJob.Execution.Akka ├── Messages │ ├── JobSweep.cs │ ├── Configured.cs │ ├── ShutDownQueues.cs │ ├── SilentRetrySweep.cs │ ├── QueueShutDown.cs │ ├── MarkJobFailed.cs │ ├── MarkJobSuccess.cs │ ├── MarkJobInProgress.cs │ ├── JobSuceeded.cs │ ├── ExecuteJobRequest.cs │ ├── GetJobs.cs │ ├── JobFailed.cs │ ├── MarkJobInRetryAndIncrement.cs │ └── SetJobQueueConfiguration.cs ├── packages.config ├── ShutdownPriorityMailbox.cs ├── GlutenFree.OddJob.Execution.Akka.nuspec ├── IExecutionEngineLoggerConfig.cs ├── GlutenFree.OddJob.Execution.Akka.csproj ├── StandardConsoleEngineLoggerConfig.cs ├── HardInjectedJobExecutorShell.cs ├── JobWorkerActor.cs ├── DependencyInjectedJobExecutorShell.cs └── JobQueueLayerActor.cs ├── GlutenFree.OddJob.Manager.Presentation.WS ├── wsconfig.json ├── JobParameter.html ├── JobItem.html ├── EditableJobItem.html ├── Scripts │ └── WebSharper │ │ ├── WebSharper.Main │ │ ├── AnimFrame.min.js │ │ ├── AnimFrame.js │ │ ├── Json.js │ │ └── Json.min.js │ │ └── WebSharper.JavaScript │ │ └── Cookies.js ├── SearchOption.html ├── packages.config ├── Readme.MD ├── Web.config ├── Web.Debug.config ├── Web.Release.config ├── Properties │ └── AssemblyInfo.cs ├── JobSearch.html └── Main.html ├── OddJob.Storage.FileSystem ├── packages.config ├── GlutenFree.OddJob.Storage.FileSystem.nuspec ├── FileSystemJobMetaData.cs └── Properties │ └── AssemblyInfo.cs ├── GlutenFree.Linq2Db.Helpers ├── ExpressionScopedVariables.cs ├── GlutenFree.Linq2Db.Helpers.csproj ├── SwapVisitor.cs ├── GetValuesExpressionReplacer.cs ├── ExpressionHelpers.cs └── ExprHelpers.cs ├── GlutenFree.OddJob.Manager.Presentation.WS-AspnetCore ├── appsettings.json ├── IJob1.cs ├── IJob2.cs ├── OddJobSitelet.cs ├── JobParameter.html ├── MyTableConfigs.cs ├── JobItem.html ├── Readme.MD ├── Properties │ └── launchSettings.json ├── AsyncOddJobRemotingHandlerDecorator.cs ├── GlutenFree.OddJob.Manager.Presentation.WS_AspnetCore.csproj ├── OddJobRemotingWrapper.cs ├── Server.cs └── Main.html ├── GlutenFree.OddJob.Serializable ├── ITypeNameSerializer.cs ├── IJobTypeResolver.cs ├── ISerializedJobQueueAdder.cs ├── ThrowOnMissingJobTypeResolver.cs ├── OddJobSerializedParameter.cs ├── VersionedTypeSerializer.cs ├── NullOnMissingTypeJobTypeResolver.cs ├── GlutenFree.OddJob.Serializable.csproj ├── GlutenFree.OddJob.Serializable.nuspec ├── UnversionedTypeSerializer.cs ├── SerializableOddJob.cs └── TargetPlatformHelpers.cs ├── OddJob.Execution.Akka.Test ├── MockJob.cs ├── Mocks │ ├── MockJobSuccessExecutor.cs │ └── MockJobFailureExecutor.cs ├── app.config ├── MockJobWorker.cs ├── packages.config ├── GlutenFree.OddJob.Execution.Akka.Test.csproj ├── QueueLayerMock.cs └── JobWorkerTests.cs ├── OddJob.Storage.SQL.Common ├── packages.config ├── ISqlDbJobQueueTableConfiguration.cs ├── DbDtos │ ├── SqlDbOddJobMethodGenericInfo.cs │ ├── SqlServerOddJobParamMetaData.cs │ └── SqlServerDbOddJobMetaData.cs ├── IJobQueueDataConnectionFactory.cs ├── TableResolver │ ├── DefaultJobAdderQueueTableResolver.cs │ ├── IJobAdderQueueTableResolver.cs │ └── QueueNameBasedJobAdderQueueTableResolver.cs ├── JobUpdateCommand.cs ├── SqlDbOddJob.cs ├── GlutenFree.OddJob.Storage.SQL.Common.nuspec ├── SqlDbJobQueueDefaultTableConfiguration.cs ├── GlutenFree.OddJob.Storage.SQL.Common.csproj ├── Mapping.cs ├── IJobSearchProvider.cs └── BaseSqlJobQueuePurger.cs ├── OddJob.Storage.SqlServer ├── packages.config ├── SqlServerJobQueueAdder.cs ├── GlutenFree.OddJob.Storage.Sql.SqlServer.0.9.0 │ ├── [Content_Types].xml │ ├── _rels │ │ └── .rels │ ├── package │ │ └── services │ │ │ └── metadata │ │ │ └── core-properties │ │ │ └── ebb72772f30040fc92ec35b4082ba3b4.psmdcp │ └── GlutenFree.OddJob.Storage.Sql.SqlServer.nuspec ├── SqlServerJobQueueManager.cs ├── GlutenFree.OddJob.Storage.Sql.SqlServer.nuspec ├── GlutenFree.OddJob.Storage.Sql.SqlServer.csproj ├── SqlServerDataConnectionFactory.cs └── SqlServerDbJobTableHelper.cs ├── OddJob.Storage.SQLite ├── packages.config ├── SQLiteJobQueueAdder.cs ├── SQLiteOddjobQueueManager.cs ├── GlutenFree.OddJob.Storage.Sql.SQLite.nuspec ├── GlutenFree.OddJob.Storage.Sql.SQLite.csproj ├── SQLiteJobQueueDataConnectionFactory.cs ├── Properties │ └── AssemblyInfo.cs └── SQLiteDbJobTableHelper.cs ├── GlutenFree.OddJob.Samples.Serialized.CommandAggregator ├── Service2Contract │ └── IService2Contract.cs ├── Service1Contract │ └── IService1Contract.cs ├── Messages │ ├── MyParam.cs │ ├── MyCommand.cs │ ├── CommandsWritten.cs │ ├── MyInProcessCommand.cs │ └── AggregatedCommand.cs ├── Helpers │ ├── SQLiteSampleHelper.cs │ └── ArrayHelper.cs ├── Configuration │ ├── MyTableConfigs.cs │ └── GenerateMappings.cs ├── Service1 │ ├── ConsoleWriter.cs │ └── Service1.cs ├── JobDI │ └── SimpleInjectorContainerFactory.cs ├── Service2 │ ├── CounterWriter.cs │ └── Service2.cs ├── Actors │ ├── DecoratorService1 │ │ └── ConsoleWriterAggregator.cs │ ├── DecoratorService2 │ │ └── CounterWriterAggregator.cs │ └── ResultJobWriter.cs ├── GlutenFree.OddJob.Samples.Serialized.CommandAggregator.csproj ├── readme.md └── Program.cs ├── GlutenFree.OddJob.Serializable.Tests ├── UnitTest1.cs └── GlutenFree.OddJob.Serializable.Tests.csproj ├── GlutenFree.OddJob.Execution.ThreadPool.Test ├── packages.config ├── UnitTest1.cs └── Properties │ └── AssemblyInfo.cs ├── GlutenFree.OddJob.Returnable ├── GlutenFree.OddJob.Returnable.csproj └── Class1.cs ├── Directory.Build.props ├── OddJob.Storage.SqlServer.Test ├── App.config ├── packages.config ├── GlutenFree.OddJob.Storage.Sql.SqlServer.Test.csproj ├── UnitTest1.cs └── UnitTestTableHelper.cs ├── OddJob.sln.DotSettings ├── GlutenFree.OddJob.Execution.BaseTests ├── app.config ├── packages.config ├── GlutenFree.OddJob.Execution.BaseTests.csproj └── OddJobWithMetaAndStorageData.cs ├── PushNuget.ps1 ├── nuget.config ├── OddJob.SampleApp.Console ├── App.config ├── Properties │ └── AssemblyInfo.cs └── Program.cs ├── OddJob.Storage.FileSystem.Test ├── UnitTest1.cs ├── Properties │ └── AssemblyInfo.cs └── packages.config ├── OddJob.Storage.BaseTests ├── packages.config ├── GlutenFree.OddJob.Storage.BaseTests.csproj ├── Properties │ └── AssemblyInfo.cs └── TestData.cs ├── OddJob.Tests ├── GlutenFree.OddJob.Tests.csproj └── packages.config ├── GlutenFree.OddJob.Storage.Sql.SQLite.Test ├── packages.config ├── GlutenFree.OddJob.Storage.Sql.SQLite.Test.csproj └── UnitTest1.cs └── GlutenFree.OddJob.Execution.ThreadPool ├── Properties └── AssemblyInfo.cs └── GlutenFree.OddJob.Execution.ThreadPool.csproj /OddJob/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.WebSharper/wsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://websharper.com/wsconfig.schema.json", 3 | "project": "site" 4 | } 5 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka/Messages/JobSweep.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Execution.Akka.Messages 2 | { 3 | public class JobSweep 4 | { 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka/Messages/Configured.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Execution.Akka.Messages 2 | { 3 | public class Configured 4 | { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /OddJob.Execution.Akka/Messages/ShutDownQueues.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Execution.Akka.Messages 2 | { 3 | public class ShutDownQueues 4 | { 5 | 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka/Messages/SilentRetrySweep.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Execution.Akka.Messages 2 | { 3 | public class SilentRetrySweep 4 | { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/wsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://websharper.com/wsconfig.schema.json", 3 | "project": "site", 4 | "sourceMap": true 5 | } 6 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka/Messages/QueueShutDown.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Execution.Akka.Messages 2 | { 3 | public class QueueShutDown 4 | { 5 | 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /OddJob.Storage.FileSystem/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /GlutenFree.Linq2Db.Helpers/ExpressionScopedVariables.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.Linq2Db.Helpers 2 | { 3 | class ExpressionScopedVariables 4 | { 5 | public T Value; 6 | } 7 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS-AspnetCore/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "websharper": { 3 | "WebSharper.JQuery.Resources.JQuery": "https://code.jquery.com/jquery-3.2.1.min.js" 4 | } 5 | } -------------------------------------------------------------------------------- /OddJob/Interfaces/IJobExecutor.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Interfaces; 2 | 3 | namespace GlutenFree.OddJob 4 | { 5 | public interface IJobExecutor 6 | { 7 | void ExecuteJob(IOddJob job); 8 | } 9 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Serializable/ITypeNameSerializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GlutenFree.OddJob.Serializable 4 | { 5 | public interface ITypeNameSerializer 6 | { 7 | string GetTypeName(Type type); 8 | } 9 | } -------------------------------------------------------------------------------- /OddJob.Execution.Akka.Test/MockJob.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Execution.Akka.Test 2 | { 3 | 4 | public class MockJob 5 | { 6 | public void MockMethod() 7 | { 8 | 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS-AspnetCore/IJob1.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Manager.Presentation.WS_AspnetCore 2 | { 3 | public interface IJob1 4 | { 5 | void Job1Method1(); 6 | void Job1Method2(); 7 | } 8 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Serializable/IJobTypeResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GlutenFree.OddJob.Serializable 4 | { 5 | public interface IJobTypeResolver 6 | { 7 | Type GetTypeForJob(string assemblyQualifiedTypeName); 8 | } 9 | } -------------------------------------------------------------------------------- /OddJob/OddJobParameter.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob 2 | { 3 | public class OddJobParameter 4 | { 5 | public string Name { get; set; } 6 | public object Value { get; set; } 7 | public string Type { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS-AspnetCore/IJob2.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Manager.Presentation.WS_AspnetCore 2 | { 3 | public interface IJob2 4 | { 5 | void Job2Method1(); 6 | void Job2Method2(string param1); 7 | } 8 | } -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /OddJob.Storage.SqlServer/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /OddJob.Storage.SQLite/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Service2Contract/IService2Contract.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 2 | { 3 | public interface IService2Contract 4 | { 5 | void WriteCounter(T param); 6 | } 7 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Serializable.Tests/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace GlutenFree.OddJob.Serializable.Tests 4 | { 5 | public class UnitTest1 6 | { 7 | [Fact] 8 | public void Test1() 9 | { 10 | 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Service1Contract/IService1Contract.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 2 | { 3 | public interface IService1Contract 4 | { 5 | void WriteToConsole(string consoleMessage); 6 | } 7 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Execution.ThreadPool.Test/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Messages/MyParam.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 2 | { 3 | public class MyParam 4 | { 5 | public T Param { get; set; } 6 | public TV AnotherParam { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /OddJob/Interfaces/IOddJobWithMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GlutenFree.OddJob.Interfaces 4 | { 5 | public interface IOddJobWithMetadata : IOddJob 6 | { 7 | DateTimeOffset? ExecutionTime { get; } 8 | IRetryParameters RetryParameters { get; } 9 | string Queue { get; } 10 | } 11 | } -------------------------------------------------------------------------------- /OddJob/Interfaces/IRetryParameters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GlutenFree.OddJob.Interfaces 4 | { 5 | public interface IRetryParameters 6 | { 7 | int MaxRetries { get; } 8 | TimeSpan MinRetryWait { get; } 9 | int RetryCount { get; } 10 | DateTime? LastAttempt { get; } 11 | } 12 | } -------------------------------------------------------------------------------- /OddJob.Execution.Akka.Test/Mocks/MockJobSuccessExecutor.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Interfaces; 2 | 3 | namespace GlutenFree.OddJob.Execution.Akka.Test.Mocks 4 | { 5 | public class MockJobSuccessExecutor : IJobExecutor 6 | { 7 | public void ExecuteJob(IOddJob job) 8 | { 9 | 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /GlutenFree.Linq2Db.Helpers/GlutenFree.Linq2Db.Helpers.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452;netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Serializable/ISerializedJobQueueAdder.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace GlutenFree.OddJob.Serializable 4 | { 5 | public interface ISerializedJobQueueAdder 6 | { 7 | void AddJob(SerializableOddJob jobData); 8 | void AddJobs(IEnumerable jobDataSet); 9 | } 10 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Execution.ThreadPool.Test/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | 3 | namespace GlutenFree.OddJob.Execution.ThreadPool.Test 4 | { 5 | [TestClass] 6 | public class UnitTest1 7 | { 8 | [TestMethod] 9 | public void TestMethod1() 10 | { 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Returnable/GlutenFree.OddJob.Returnable.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452;netstandard2.0 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka/Messages/MarkJobFailed.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GlutenFree.OddJob.Execution.Akka.Messages 4 | { 5 | public class MarkJobFailed 6 | { 7 | public Guid JobId { get; protected set; } 8 | 9 | public MarkJobFailed(Guid jobId) 10 | { 11 | this.JobId = jobId; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /OddJob.Execution.Akka/Messages/MarkJobSuccess.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GlutenFree.OddJob.Execution.Akka.Messages 4 | { 5 | public class MarkJobSuccess 6 | { 7 | public Guid JobId { get; protected set; } 8 | 9 | public MarkJobSuccess(Guid jobId) 10 | { 11 | this.JobId = jobId; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /OddJob.Execution.Akka/Messages/MarkJobInProgress.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GlutenFree.OddJob.Execution.Akka.Messages 4 | { 5 | public class MarkJobInProgress 6 | { 7 | public Guid JobId { get; protected set; } 8 | 9 | public MarkJobInProgress(Guid jobId) 10 | { 11 | this.JobId = jobId; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /OddJob/DefaultJobQueueManagerPriority.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GlutenFree.OddJob.Interfaces 5 | { 6 | public static class DefaultJobQueueManagerPriority 7 | { 8 | public static Expression> Expression {get{ 9 | return data => data.MostRecentDate; 10 | }} 11 | } 12 | } -------------------------------------------------------------------------------- /OddJob.Execution.Akka/Messages/JobSuceeded.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Interfaces; 2 | 3 | namespace GlutenFree.OddJob.Execution.Akka.Messages 4 | { 5 | public class JobSuceeded 6 | { 7 | public JobSuceeded(IOddJob jobData) 8 | { 9 | JobData = jobData; 10 | } 11 | public IOddJob JobData { get; protected set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka.Test/Mocks/MockJobFailureExecutor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GlutenFree.OddJob.Interfaces; 3 | 4 | namespace GlutenFree.OddJob.Execution.Akka.Test.Mocks 5 | { 6 | public class MockJobFailureExecutor : IJobExecutor 7 | { 8 | public void ExecuteJob(IOddJob job) 9 | { 10 | throw new Exception("Failed!"); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/ISqlDbJobQueueTableConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Storage.Sql.Common 2 | { 3 | public interface ISqlDbJobQueueTableConfiguration 4 | { 5 | string QueueTableName { get; } 6 | string ParamTableName { get; } 7 | int JobClaimLockTimeoutInSeconds { get; } 8 | string JobMethodGenericParamTableName { get; } 9 | } 10 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Messages/MyCommand.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 2 | { 3 | /// 4 | /// A command. While here it does nothing, 5 | /// in other cases it could contain contextual data to pass to each command decorator. 6 | /// 7 | public class MyCommand 8 | { 9 | 10 | } 11 | } -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 0.9.92 4 | 0.9.92 5 | 0.9.92 6 | Gluten Free Solutions 7 | First NetFramework/NetStandard Release 8 | true 9 | 10 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka/Messages/ExecuteJobRequest.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Interfaces; 2 | 3 | namespace GlutenFree.OddJob.Execution.Akka.Messages 4 | { 5 | public class ExecuteJobRequest 6 | { 7 | public ExecuteJobRequest(IOddJobWithMetadata jobData) 8 | { 9 | JobData = jobData; 10 | } 11 | public IOddJobWithMetadata JobData { get; protected set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /OddJob.Storage.SqlServer.Test/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /OddJob.sln.DotSettings: -------------------------------------------------------------------------------- 1 | 2 | SQ -------------------------------------------------------------------------------- /GlutenFree.OddJob.Serializable/ThrowOnMissingJobTypeResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GlutenFree.OddJob.Serializable 4 | { 5 | public class ThrowOnMissingJobTypeResolver : IJobTypeResolver 6 | { 7 | public Type GetTypeForJob(string assemblyQualifiedTypeName) 8 | { 9 | return Type.GetType(TargetPlatformHelpers.ReplaceCoreTypes(assemblyQualifiedTypeName)); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /OddJob/JobStates.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob 2 | { 3 | public static class JobStates 4 | { 5 | public const string Processed = "Processed"; 6 | public const string New = "New"; 7 | public const string Failed = "Failed"; 8 | public const string Retry = "Retry"; 9 | public const string InProgress = "InProgress"; 10 | public const string Inserting = "Inserting"; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka/Messages/GetJobs.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Execution.Akka.Messages 2 | { 3 | public class GetJobs 4 | { 5 | public string QueueName { get; protected set; } 6 | public int FetchSize { get; protected set; } 7 | public GetJobs(string queueName,int fetchSize) 8 | { 9 | QueueName = queueName; 10 | FetchSize = fetchSize; 11 | } 12 | } 13 | } 14 | 15 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Serializable/OddJobSerializedParameter.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Serializable 2 | { 3 | public class OddJobSerializedParameter 4 | { 5 | public OddJobSerializedParameter() 6 | { 7 | 8 | } 9 | public int Ordinal { get; set; } 10 | public string Name { get; set; } 11 | public string Value { get; set; } 12 | public string TypeName { get; set; } 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /OddJob/DefaultContainerFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GlutenFree.OddJob.Interfaces; 3 | 4 | namespace GlutenFree.OddJob 5 | { 6 | public class DefaultContainerFactory : IContainerFactory 7 | { 8 | public object CreateInstance(Type typeToCreate) 9 | { 10 | return Activator.CreateInstance(typeToCreate); 11 | } 12 | 13 | public void Relase(object usedInstance) 14 | { 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS-AspnetCore/OddJobSitelet.cs: -------------------------------------------------------------------------------- 1 | using WebSharper.AspNetCore; 2 | using WebSharper.Sitelets; 3 | 4 | namespace GlutenFree.OddJob.Manager.Presentation.WS_AspnetCore 5 | { 6 | public class OddJobSitelet : ISiteletService 7 | { 8 | public Sitelet Sitelet 9 | { 10 | get 11 | { 12 | return new Server().Main; 13 | } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Serializable/VersionedTypeSerializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GlutenFree.OddJob.Serializable 4 | { 5 | public class VersionedTypeSerializer : ITypeNameSerializer 6 | { 7 | public string GetTypeName(Type type) 8 | { 9 | if (type != null) 10 | { 11 | return type.AssemblyQualifiedName; 12 | } 13 | 14 | return ""; 15 | 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /OddJob/Interfaces/IJobFilterMetadata.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GlutenFree.OddJob.Interfaces 4 | { 5 | public interface IJobFilterMetadata 6 | { 7 | DateTime? MostRecentDate { get; set; } 8 | DateTime? CreatedDate { get; set; } 9 | DateTime? LastAttempt { get; set; } 10 | int Retries { get; set; } 11 | DateTimeOffset? DoNotExecuteBefore { get; set; } 12 | string Status { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/JobParameter.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
Ordinal :
4 |
Name:
5 |
Type:
6 |
Value:
7 |
-------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.WebSharper/Remoting.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using WebSharper; 5 | 6 | namespace GlutenFree.OddJob.Manager.Presentation.WS 7 | { 8 | public static class Remoting 9 | { 10 | [Remote] 11 | public static Task DoSomething(string input) 12 | { 13 | return Task.FromResult(new String(input.ToCharArray().Reverse().ToArray())); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS-AspnetCore/JobParameter.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
Ordinal :
4 |
Name:
5 |
Type:
6 |
Value:
7 |
-------------------------------------------------------------------------------- /OddJob.Execution.Akka.Test/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/DbDtos/SqlDbOddJobMethodGenericInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using LinqToDB.Mapping; 3 | 4 | namespace GlutenFree.OddJob.Storage.Sql.Common.DbDtos 5 | { 6 | public class SqlDbOddJobMethodGenericInfo 7 | { 8 | [Identity] 9 | [PrimaryKey] 10 | public long Id { get; set; } 11 | public Guid JobGuid { get; set; } 12 | public int ParamOrder { get; set; } 13 | public string ParamTypeName { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Helpers/SQLiteSampleHelper.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Storage.Sql.SQLite; 2 | 3 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 4 | { 5 | class SQLiteSampleHelper 6 | { 7 | public static SQLiteJobQueueDataConnectionFactory ConnFactoryFunc() 8 | { 9 | return new GlutenFree.OddJob.Storage.Sql.SQLite.SQLiteJobQueueDataConnectionFactory(SampleTableHelper.connString); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /OddJob/GlutenFree.OddJob.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452;netstandard2.0 5 | GlutenFree.OddJob 6 | GlutenFree.OddJob 7 | Core Model and Functionality for Job Creation and Job Running. 8 | job jobs jobscheduler scheduler oddjob task future later 9 | 10 | 11 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Execution.BaseTests/app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/IJobQueueDataConnectionFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Data.Common; 2 | using LinqToDB.Data; 3 | using LinqToDB.Mapping; 4 | 5 | namespace GlutenFree.OddJob.Storage.Sql.Common 6 | { 7 | public interface IJobQueueDataConnectionFactory 8 | { 9 | DataConnection CreateDataConnection(MappingSchema mappingSchema); 10 | } 11 | 12 | public interface IJobQueueDbConnectionFactory 13 | { 14 | DbConnection CreateDbConnection(); 15 | } 16 | 17 | 18 | } 19 | -------------------------------------------------------------------------------- /OddJob/Interfaces/IContainerFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GlutenFree.OddJob.Interfaces 4 | { 5 | public interface IContainerFactory 6 | { 7 | object CreateInstance(Type typeToCreate); 8 | 9 | /// 10 | /// If the DI framework somehow requires explicit releasing of acquired resources, this should be implemented. 11 | /// 12 | /// 13 | void Relase(object usedInstance); 14 | } 15 | } -------------------------------------------------------------------------------- /OddJob.Storage.SQLite/SQLiteJobQueueAdder.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Storage.Sql.Common; 2 | 3 | namespace GlutenFree.OddJob.Storage.Sql.SQLite 4 | { 5 | public class SQLiteJobQueueAdder : BaseSqlJobQueueAdder 6 | { 7 | 8 | public SQLiteJobQueueAdder(SQLiteJobQueueDataConnectionFactory jobQueueDataConnectionFactory, IJobAdderQueueTableResolver jobQueueTableConfiguration) : base(jobQueueDataConnectionFactory, jobQueueTableConfiguration) 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /PushNuget.ps1: -------------------------------------------------------------------------------- 1 | cd .\OddJob 2 | nuget pack -IncludeReferencedProjects 3 | cd .. 4 | cd .\OddJob.Execution.Akka 5 | nuget pack -IncludeReferencedProjects 6 | cd .. 7 | cd .\OddJob.Storage.FileSystem 8 | nuget pack -IncludeReferencedProjects 9 | cd .. 10 | cd .\OddJob.Storage.SQL.Common 11 | nuget pack -IncludeReferencedProjects 12 | cd .. 13 | cd .\OddJob.Storage.SQLite 14 | nuget pack -IncludeReferencedProjects 15 | cd .. 16 | cd .\OddJob.Storage.SqlServer 17 | nuget pack -IncludeReferencedProjects 18 | cd .. 19 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS-AspnetCore/MyTableConfigs.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Storage.Sql.Common; 2 | 3 | namespace GlutenFree.OddJob.Manager.Presentation.WS_AspnetCore 4 | { 5 | public class MyTableConfigs : ISqlDbJobQueueTableConfiguration 6 | { 7 | public string QueueTableName { get; set; } 8 | public string ParamTableName { get; set; } 9 | public int JobClaimLockTimeoutInSeconds { get; set; } 10 | public string JobMethodGenericParamTableName { get; set; } 11 | } 12 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/JobItem.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS-AspnetCore/JobItem.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka/Messages/JobFailed.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GlutenFree.OddJob.Interfaces; 3 | 4 | namespace GlutenFree.OddJob.Execution.Akka.Messages 5 | { 6 | public class JobFailed 7 | { 8 | public JobFailed(IOddJobWithMetadata jobData, Exception exception) 9 | { 10 | JobData = jobData; 11 | Exception = exception; 12 | } 13 | public IOddJobWithMetadata JobData { get; protected set; } 14 | public Exception Exception { get; protected set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka/Messages/MarkJobInRetryAndIncrement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GlutenFree.OddJob.Execution.Akka.Messages 4 | { 5 | public class MarkJobInRetryAndIncrement 6 | { 7 | public Guid JobId { get; protected set; } 8 | public DateTime LastAttempt { get; protected set; } 9 | 10 | public MarkJobInRetryAndIncrement(Guid jobId, DateTime lastAttempt) 11 | { 12 | this.JobId = jobId; 13 | this.LastAttempt = lastAttempt; 14 | } 15 | } 16 | } 17 | 18 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Configuration/MyTableConfigs.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Storage.Sql.Common; 2 | 3 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 4 | { 5 | public class MyTableConfigs : ISqlDbJobQueueTableConfiguration 6 | { 7 | public string QueueTableName { get; set;} 8 | public string ParamTableName { get; set;} 9 | public int JobClaimLockTimeoutInSeconds { get; set;} 10 | public string JobMethodGenericParamTableName { get; set;} 11 | } 12 | } -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/TableResolver/DefaultJobAdderQueueTableResolver.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace GlutenFree.OddJob.Storage.Sql.Common 4 | { 5 | public class DefaultJobAdderQueueTableResolver : QueueNameBasedJobAdderQueueTableResolver 6 | { 7 | 8 | public DefaultJobAdderQueueTableResolver(ISqlDbJobQueueTableConfiguration tableConfiguration) : base( 9 | new Dictionary(), tableConfiguration) 10 | { 11 | 12 | } 13 | 14 | } 15 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Serializable.Tests/GlutenFree.OddJob.Serializable.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /OddJob.Storage.SqlServer/SqlServerJobQueueAdder.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Storage.Sql.Common; 2 | 3 | namespace GlutenFree.OddJob.Storage.Sql.SqlServer 4 | { 5 | public class SqlServerJobQueueAdder : BaseSqlJobQueueAdder 6 | { 7 | 8 | 9 | public SqlServerJobQueueAdder(SqlServerDataConnectionFactory jobQueueDataConnectionFactory, 10 | IJobAdderQueueTableResolver jobQueueTableConfiguration) : base(jobQueueDataConnectionFactory, 11 | jobQueueTableConfiguration) 12 | { 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /OddJob.Storage.SqlServer/GlutenFree.OddJob.Storage.Sql.SqlServer.0.9.0/[Content_Types].xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /GlutenFree.Linq2Db.Helpers/SwapVisitor.cs: -------------------------------------------------------------------------------- 1 | using System.Linq.Expressions; 2 | 3 | namespace GlutenFree.Linq2Db.Helpers 4 | { 5 | public class SwapVisitor : ExpressionVisitor 6 | { 7 | private readonly Expression from, to; 8 | public SwapVisitor(Expression from, Expression to) 9 | { 10 | this.from = from; 11 | this.to = to; 12 | } 13 | public override Expression Visit(Expression node) 14 | { 15 | return node == from ? to : base.Visit(node); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /OddJob/JobLockData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GlutenFree.OddJob.Interfaces; 3 | 4 | namespace GlutenFree.OddJob 5 | { 6 | public class JobLockData : IJobFilterMetadata 7 | { 8 | public long JobId { get; set; } 9 | public DateTime? MostRecentDate { get; set; } 10 | public DateTime? CreatedDate { get; set; } 11 | public DateTime? LastAttempt { get; set; } 12 | public int Retries { get; set; } 13 | public DateTimeOffset? DoNotExecuteBefore { get; set; } 14 | public string Status { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Service1/ConsoleWriter.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 2 | { 3 | /// 4 | /// An example job. You could instead define an interface as a contract on the creation end, 5 | /// allowing for a fully detached implementation. 6 | /// 7 | public class ConsoleWriter : IService1Contract 8 | { 9 | public void WriteToConsole(string consoleMessage) 10 | { 11 | System.Console.WriteLine(consoleMessage); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/EditableJobItem.html: -------------------------------------------------------------------------------- 1 | 2 |
  • 3 |
    4 |
    JobGuid:
    5 |
    MethodName:
    6 |
    QueueName:
    7 |
    Status:
    8 |
    9 |
    10 |
  • -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.WebSharper/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Helpers/ArrayHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 4 | { 5 | /// 6 | /// A helper class to allow for appending to arrays. 7 | /// 8 | public static class ArrayHelper 9 | { 10 | public static T[] WithItem(this T[] array, T newItem) 11 | { 12 | //Probably not the most efficient way to do any of this, but it's just for the example. =) 13 | return array.Append(newItem).ToArray(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Serializable/NullOnMissingTypeJobTypeResolver.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GlutenFree.OddJob.Serializable 4 | { 5 | public class NullOnMissingTypeJobTypeResolver : IJobTypeResolver 6 | { 7 | public Type GetTypeForJob(string assemblyQualifiedTypeName) 8 | { 9 | try 10 | { 11 | return Type.GetType(TargetPlatformHelpers.ReplaceCoreTypes(assemblyQualifiedTypeName)); 12 | } 13 | catch (Exception) 14 | { 15 | return null; 16 | } 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/DbDtos/SqlServerOddJobParamMetaData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using LinqToDB.Mapping; 3 | 4 | namespace GlutenFree.OddJob.Storage.Sql.Common.DbDtos 5 | { 6 | public class SqlCommonOddJobParamMetaData 7 | { 8 | [Identity] 9 | [PrimaryKey] 10 | public long Id { get; set; } 11 | public Guid JobGuid { get; set; } 12 | public int ParamOrdinal { get; set; } 13 | public string SerializedValue { get; set; } 14 | public string SerializedType { get; set; } 15 | public string ParameterName { get; set; } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /OddJob.Storage.SqlServer/GlutenFree.OddJob.Storage.Sql.SqlServer.0.9.0/_rels/.rels: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /OddJob.Storage.SqlServer/SqlServerJobQueueManager.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Serializable; 2 | using GlutenFree.OddJob.Storage.Sql.Common; 3 | 4 | namespace GlutenFree.OddJob.Storage.Sql.SqlServer 5 | { 6 | 7 | public class SqlServerJobQueueManager : BaseSqlJobQueueManager 8 | { 9 | public SqlServerJobQueueManager(SqlServerDataConnectionFactory jobQueueConnectionFactory, 10 | ISqlDbJobQueueTableConfiguration tableConfig, IJobTypeResolver typeResolver) : base(jobQueueConnectionFactory, 11 | tableConfig, typeResolver) 12 | { } 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/Scripts/WebSharper/WebSharper.Main/AnimFrame.min.js: -------------------------------------------------------------------------------- 1 | (function(){for(var i=0,t=["webkit","moz"],n=0;n 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /OddJob/Interfaces/IOddJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GlutenFree.OddJob.Interfaces 4 | { 5 | 6 | 7 | public interface IOddJob 8 | { 9 | Guid JobId { get; } 10 | OddJobParameter[] JobArgs { get; } 11 | Type TypeExecutedOn { get; } 12 | string MethodName { get; } 13 | string Status { get; } 14 | Type[] MethodGenericTypes { get; } 15 | } 16 | 17 | public interface IConfiguredOddJob : IOddJob 18 | { 19 | RetryParameters RetryParameters { get; } 20 | string Queue { get; } 21 | DateTime? ExecutionTime { get; } 22 | } 23 | } -------------------------------------------------------------------------------- /OddJob.Storage.SQLite/SQLiteOddjobQueueManager.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Serializable; 2 | using GlutenFree.OddJob.Storage.Sql.Common; 3 | 4 | namespace GlutenFree.OddJob.Storage.Sql.SQLite 5 | { 6 | public class SQLiteJobQueueManager : BaseSqlJobQueueManager 7 | { 8 | public SQLiteJobQueueManager(SQLiteJobQueueDataConnectionFactory jobQueueDataConnectionFactory, 9 | ISqlDbJobQueueTableConfiguration tableConfiguration, IJobTypeResolver typeResolver) : base( 10 | jobQueueDataConnectionFactory, tableConfiguration, typeResolver) 11 | { 12 | 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /OddJob.Storage.FileSystem.Test/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GlutenFree.OddJob.Interfaces; 3 | using GlutenFree.OddJob.Storage.BaseTests; 4 | 5 | namespace GlutenFree.OddJob.Storage.FileSystem.Test 6 | { 7 | public class FileSystemStoreTests : StorageTests 8 | { 9 | public FileSystemStoreTests() 10 | { 11 | } 12 | 13 | protected override Func JobAddStoreFunc { get{return ()=> new FileSystemJobQueueAdder("test.json"); } } 14 | protected override Func JobMgrStoreFunc { get {return ()=> new FileSystemJobQueueManager("test.json"); } } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/TableResolver/IJobAdderQueueTableResolver.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Serializable; 2 | 3 | namespace GlutenFree.OddJob.Storage.Sql.Common 4 | { 5 | /// 6 | /// This interface lets you configure Queue table configurations for specific jobs. 7 | /// This can be useful in distributed scenarios where you wish to have multiple jobs written to different queues 8 | /// But want to keep everything in a single operation. 9 | /// 10 | public interface IJobAdderQueueTableResolver 11 | { 12 | ISqlDbJobQueueTableConfiguration GetConfigurationForJob(SerializableOddJob job); 13 | } 14 | } -------------------------------------------------------------------------------- /OddJob/Interfaces/IJobQueueManager.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace GlutenFree.OddJob.Interfaces 6 | { 7 | public interface IJobQueueManager 8 | { 9 | void MarkJobSuccess(Guid jobGuid); 10 | void MarkJobFailed(Guid jobGuid); 11 | IEnumerable GetJobs(string[] queueNames, int fetchSize, Expression> orderPredicate); 12 | void MarkJobInProgress(Guid jobId); 13 | void MarkJobInRetryAndIncrement(Guid jobId, DateTime lastAttempt); 14 | IOddJobWithMetadata GetJob(Guid jobId); 15 | } 16 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/SearchOption.html: -------------------------------------------------------------------------------- 1 | 2 |
  • 3 |
    4 | 5 |
    6 |
    7 |
    JobGuid:
    8 |
    MethodName:
    9 |
    QueueName:
    10 |
    Status:
    11 |
    12 |
    13 |
  • -------------------------------------------------------------------------------- /GlutenFree.OddJob.Serializable/GlutenFree.OddJob.Serializable.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0;net452 5 | Wire-Safe Serializable Job Model and functionality 6 | job jobs jobscheduler scheduler oddjob task future later serializable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /OddJob.Storage.BaseTests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS-AspnetCore/Readme.MD: -------------------------------------------------------------------------------- 1 | # OddJob Manager - WebSharper Sample 2 | 3 | This is a Sample project, Providing a Basic Job Manager using WebSharper alongside ASP.NET Core. 4 | 5 | The inspiration for this was the desire to provide some capabilities to manage and observe Job States, and to try WebSharper as a framework. 6 | 7 | Consider it something in between 'Batteries Included', 'Project Template', and 'Cautionary Tale'. 8 | 9 | Some Important Notes: 10 | 11 | - Websharper Remoting rules mean that Remoting classes are treated as *singletons*. Unfortunately this means this POC doesn't easily translate into certain usage scenarios. 12 | 13 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Execution.BaseTests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Serializable/GlutenFree.OddJob.Serializable.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | $author$ 8 | $author$ 9 | https://github.com/to11mtm/OddJob/blob/master/LICENSE 10 | https://github.com/to11mtm/OddJob/ 11 | false 12 | $description$ 13 | Copyright 2018 14 | job jobs jobscheduler scheduler oddjob task future later 15 | 16 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Messages/CommandsWritten.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 2 | { 3 | /// 4 | /// An Acknowledgement message to signal that a command is written. 5 | /// If you wish to work with Guaranteed delivery semantics, 6 | /// this could have a Sequence number (if using something like Akka.NET) 7 | /// Or another ID for your system of choice. 8 | /// 9 | public class CommandsWritten 10 | { 11 | //If you want to work with guaranteed delivery semantics, 12 | //this would be a good place to put a sequence number to respond back to a delivery buffer. 13 | 14 | } 15 | } -------------------------------------------------------------------------------- /GlutenFree.Linq2Db.Helpers/GetValuesExpressionReplacer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq.Expressions; 3 | 4 | namespace GlutenFree.Linq2Db.Helpers 5 | { 6 | public class GetValuesExpressionReplacer : ExpressionVisitor 7 | { 8 | protected List _values; 9 | 10 | public List GetValues(Expression expr) 11 | { 12 | _values = new List(); 13 | Visit(expr); 14 | return _values; 15 | } 16 | 17 | protected override Expression VisitConstant(ConstantExpression node) 18 | { 19 | _values.Add(node.Value); 20 | return base.VisitConstant(node); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /OddJob.Execution.Akka/ShutdownPriorityMailbox.cs: -------------------------------------------------------------------------------- 1 | using Akka.Actor; 2 | using Akka.Configuration; 3 | using Akka.Dispatch; 4 | using GlutenFree.OddJob.Execution.Akka.Messages; 5 | 6 | namespace GlutenFree.OddJob.Execution.Akka 7 | { 8 | public class ShutdownPriorityMailbox : UnboundedPriorityMailbox 9 | { 10 | public ShutdownPriorityMailbox(Settings settings, Config config) : base(settings, config) 11 | { 12 | } 13 | 14 | protected override int PriorityGenerator(object message) 15 | { 16 | 17 | 18 | if (message is ShutDownQueues) 19 | { 20 | return 0; 21 | } 22 | 23 | return 1; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/JobUpdateCommand.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using GlutenFree.OddJob.Storage.Sql.Common.DbDtos; 5 | 6 | namespace GlutenFree.OddJob.Storage.Sql.Common 7 | { 8 | public class JobUpdateCommand 9 | { 10 | public Dictionary>, object> SetJobMetadata { get; set; } 11 | public Dictionary>, object>> SetJobParameters 12 | { 13 | get; 14 | set; 15 | } 16 | public Guid JobGuid { get; set; } 17 | public string OldStatusIfRequired { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/SqlDbOddJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GlutenFree.OddJob.Interfaces; 3 | 4 | namespace GlutenFree.OddJob.Storage.Sql.Common 5 | { 6 | 7 | public class SqlDbOddJob : IOddJobWithMetadata 8 | { 9 | public Guid JobId { get; set; } 10 | public OddJobParameter[] JobArgs { get; set; } 11 | 12 | public Type TypeExecutedOn { get; set; } 13 | 14 | public string MethodName { get; set; } 15 | public string Status { get; set; } 16 | public Type[] MethodGenericTypes { get; set; } 17 | public IRetryParameters RetryParameters { get; set; } 18 | public string Queue { get; set; } 19 | public DateTimeOffset? ExecutionTime { get; set; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /OddJob.Tests/GlutenFree.OddJob.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452;netcoreapp2.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /OddJob/GlutenFree.OddJob.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | $author$ 8 | $author$ 9 | https://github.com/to11mtm/OddJob/blob/master/LICENSE 10 | https://github.com/to11mtm/OddJob/ 11 | false 12 | $description$ 13 | First NetFramework/NetStandard Release 14 | Copyright 2018 15 | job jobs jobscheduler scheduler oddjob task future later 16 | 17 | -------------------------------------------------------------------------------- /OddJob.Storage.FileSystem.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("OddJob.Storage.FileSystem.Test")] 5 | [assembly: AssemblyDescription("")] 6 | [assembly: AssemblyConfiguration("")] 7 | [assembly: AssemblyCompany("")] 8 | [assembly: AssemblyProduct("OddJob.Storage.FileSystem.Test")] 9 | [assembly: AssemblyCopyright("Copyright © 2018")] 10 | [assembly: AssemblyTrademark("")] 11 | [assembly: AssemblyCulture("")] 12 | 13 | [assembly: ComVisible(false)] 14 | 15 | [assembly: Guid("9e9cb318-9cbe-409b-9e4c-6b2efab570b9")] 16 | 17 | // [assembly: AssemblyVersion("1.0.*")] 18 | [assembly: AssemblyVersion("1.0.0.0")] 19 | [assembly: AssemblyFileVersion("1.0.0.0")] 20 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Returnable/Class1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GlutenFree.OddJob.Returnable 5 | { 6 | public class ReturnableOddJob : OddJob 7 | { 8 | public ReturnableOddJob(string methodName, OddJobParameter[] jobArgs, Type typeExecutedOn, Type[] methodGenericTypes, string status = JobStates.New) : base(methodName, jobArgs, typeExecutedOn, methodGenericTypes, status) 9 | { 10 | } 11 | } 12 | public static class ReturnableJobCreator 13 | { 14 | public static void Create(Expression> jobExpr) 15 | { 16 | ExpressionBasedJobCreator.CreateInternal(jobExpr.Body as MethodCallExpression); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka/GlutenFree.OddJob.Execution.Akka.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | $author$ 8 | $author$ 9 | https://github.com/to11mtm/OddJob/blob/master/LICENSE 10 | https://github.com/to11mtm/OddJob/ 11 | false 12 | $description$ 13 | First NetFramework/NetStandard Release 14 | Copyright 2018 15 | job jobs jobscheduler scheduler oddjob task future later akka 16 | 17 | -------------------------------------------------------------------------------- /OddJob.Storage.FileSystem/GlutenFree.OddJob.Storage.FileSystem.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | $author$ 8 | $author$ 9 | https://github.com/to11mtm/OddJob/blob/master/LICENSE 10 | https://github.com/to11mtm/OddJob/ 11 | false 12 | $description$ 13 | First NetFramework/NetStandard Release 14 | Copyright 2018 15 | job jobs jobscheduler scheduler task storage filesystem 16 | 17 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Execution.BaseTests/GlutenFree.OddJob.Execution.BaseTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452;netcoreapp2.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/JobDI/SimpleInjectorContainerFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GlutenFree.OddJob.Interfaces; 3 | 4 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 5 | { 6 | public class SimpleInjectorContainerFactory : IContainerFactory 7 | { 8 | private SimpleInjector.Container _container; 9 | 10 | public SimpleInjectorContainerFactory(SimpleInjector.Container container) 11 | { 12 | _container = container; 13 | } 14 | public object CreateInstance(Type typeToCreate) 15 | { 16 | return _container.GetInstance(typeToCreate); 17 | } 18 | 19 | public void Relase(object usedInstance) 20 | { 21 | 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /OddJob.Storage.SQLite/GlutenFree.OddJob.Storage.Sql.SQLite.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | $author$ 8 | $author$ 9 | https://github.com/to11mtm/OddJob/blob/master/LICENSE 10 | https://github.com/to11mtm/OddJob/ 11 | false 12 | $description$ 13 | First NetFramework/NetStandard Release 14 | Copyright 2018 15 | job jobs jobscheduler scheduler oddjob task future later sql sqlite 16 | 17 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Execution.ThreadPool.Test/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | [assembly: AssemblyTitle("GlutenFree.OddJob.Execution.ThreadPool.Test")] 5 | [assembly: AssemblyDescription("")] 6 | [assembly: AssemblyConfiguration("")] 7 | [assembly: AssemblyCompany("")] 8 | [assembly: AssemblyProduct("GlutenFree.OddJob.Execution.ThreadPool.Test")] 9 | [assembly: AssemblyCopyright("Copyright © 2018")] 10 | [assembly: AssemblyTrademark("")] 11 | [assembly: AssemblyCulture("")] 12 | 13 | [assembly: ComVisible(false)] 14 | 15 | [assembly: Guid("3242458b-9acb-4ba4-8e62-cda9462a806e")] 16 | 17 | // [assembly: AssemblyVersion("1.0.*")] 18 | [assembly: AssemblyVersion("1.0.0.0")] 19 | [assembly: AssemblyFileVersion("1.0.0.0")] 20 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.WebSharper/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/GlutenFree.OddJob.Storage.SQL.Common.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | $author$ 8 | $author$ 9 | https://github.com/to11mtm/OddJob/blob/master/LICENSE 10 | https://github.com/to11mtm/OddJob/ 11 | false 12 | $description$ 13 | First NetFramework/NetStandard Release 14 | Copyright 2018 15 | job jobs jobscheduler scheduler oddjob task future later sql sqlcommon common 16 | 17 | -------------------------------------------------------------------------------- /OddJob.Storage.SqlServer/GlutenFree.OddJob.Storage.Sql.SqlServer.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | $id$ 5 | $version$ 6 | $title$ 7 | $author$ 8 | $author$ 9 | https://github.com/to11mtm/OddJob/blob/master/LICENSE 10 | https://github.com/to11mtm/OddJob/ 11 | false 12 | $description$ 13 | First NetFramework/NetStandard Release 14 | Copyright 2018 15 | job jobs jobscheduler scheduler oddjob task future later sql server sqlserver 16 | 17 | -------------------------------------------------------------------------------- /OddJob/OddJobWithMetaData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GlutenFree.OddJob.Interfaces; 3 | 4 | namespace GlutenFree.OddJob 5 | { 6 | public class OddJobWithMetaData : IOddJobWithMetadata 7 | { 8 | public RetryParameters RetryParameters { get; set; } 9 | 10 | public Guid JobId { get; set; } 11 | 12 | public OddJobParameter[] JobArgs { get; set; } 13 | 14 | public Type TypeExecutedOn { get; set; } 15 | 16 | public string MethodName { get; set; } 17 | public string Status { get; set; } 18 | public Type[] MethodGenericTypes { get; set; } 19 | IRetryParameters IOddJobWithMetadata.RetryParameters { get { return RetryParameters; } } 20 | public DateTimeOffset? ExecutionTime { get; set; } 21 | public string Queue { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Service2/CounterWriter.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 2 | { 3 | /// 4 | /// An example job. You could instead define an interface as a contract on the creation end, 5 | /// allowing for a fully detached implementation. 6 | /// 7 | public class CounterWriter : IService2Contract 8 | { 9 | private static object _lockObject = new object(); 10 | private static int _counter = 0; 11 | public void WriteCounter(T param) 12 | { 13 | lock (_lockObject) 14 | { 15 | _counter = _counter + 1; 16 | System.Console.WriteLine("Counter" + _counter + " Param: " + param.ToString()); 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /OddJob.Storage.FileSystem.Test/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /OddJob.Storage.BaseTests/GlutenFree.OddJob.Storage.BaseTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452;netcoreapp2.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | false 21 | GlutenFree.OddJob.Storage.BaseTests 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /OddJob.Storage.SQLite/GlutenFree.OddJob.Storage.Sql.SQLite.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452;netstandard2.0 5 | 6 | 7 | false 8 | GlutenFree.OddJob.Storage.Sql.SQLite 9 | SQLite OddJob Storage implementation. 10 | job jobs jobscheduler scheduler oddjob task future later sql sqlite 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS-AspnetCore/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:60819/", 7 | "sslPort": 0 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "GlutenFree.OddJob.Manager.Presentation.WS-AspnetCore": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "environmentVariables": { 22 | "ASPNETCORE_ENVIRONMENT": "Development" 23 | }, 24 | "applicationUrl": "http://localhost:60821/" 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /OddJob.Execution.Akka/IExecutionEngineLoggerConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Akka.Dispatch; 3 | using Akka.Event; 4 | 5 | namespace GlutenFree.OddJob.Execution.Akka 6 | { 7 | /// 8 | /// Interface defining a logger for the execution engine. 9 | /// Is considered a safe default 10 | /// 11 | public interface IExecutionEngineLoggerConfig 12 | { 13 | /// 14 | /// This corresponds to a Type defined in an Akka.NET Logging plugin. 15 | /// 16 | Func> LoggerTypeFactory { get; } 17 | /// 18 | /// This is expected to be a value of OFF, ERROR, WARNING, INFO, or DEBUG 19 | /// 20 | string LogLevel { get; } 21 | } 22 | } -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/SqlDbJobQueueDefaultTableConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Storage.Sql.Common 2 | { 3 | public class SqlDbJobQueueDefaultTableConfiguration : ISqlDbJobQueueTableConfiguration 4 | { 5 | public const string DefaultQueueTableName = "QueueTable"; 6 | public const string DefaultQueueParamTableName = "QueueParamValue"; 7 | public const string DefaultJobMethodGenericParamTableName = "QueueJobMethodGenericParam"; 8 | public string QueueTableName { get { return DefaultQueueTableName; } } 9 | public string ParamTableName { get { return DefaultQueueParamTableName; } } 10 | public int JobClaimLockTimeoutInSeconds { get { return 180; } } 11 | public string JobMethodGenericParamTableName 12 | { 13 | get { return DefaultJobMethodGenericParamTableName; } 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /OddJob.Execution.Akka/GlutenFree.OddJob.Execution.Akka.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452;netstandard2.0 5 | GlutenFree.OddJob.Execution.Akka 6 | Basic Execution engine using Akka.NET for underlying Architecture. 7 | job jobs jobscheduler scheduler oddjob task future later akka 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /OddJob.Storage.SqlServer/GlutenFree.OddJob.Storage.Sql.SqlServer.0.9.0/package/services/metadata/core-properties/ebb72772f30040fc92ec35b4082ba3b4.psmdcp: -------------------------------------------------------------------------------- 1 | 2 | 3 | Gluten Free Solutions 4 | OddJob - SqlServer Storage Provider 5 | GlutenFree.OddJob.Storage.Sql.SqlServer 6 | 0.9.0 7 | job jobs jobscheduler scheduler oddjob task future later sql server sqlserver 8 | NuGet, Version=4.6.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35;Microsoft Windows NT 6.2.9200.0;.NET Framework 4.6 9 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Storage.Sql.SQLite.Test/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /OddJob.Storage.SqlServer/GlutenFree.OddJob.Storage.Sql.SqlServer.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452;netstandard2.0 5 | 6 | 7 | false 8 | GlutenFree.OddJob.Storage.Sql.SqlServer 9 | GlutenFree.OddJob.Storage.Sql.SqlServer 10 | SQLServer OddJob Storage implementation. 11 | job jobs jobscheduler scheduler oddjob task future later sql server sqlserver 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /OddJob.Tests/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Messages/MyInProcessCommand.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Serializable; 2 | 3 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 4 | { 5 | /// 6 | /// An In process command. 7 | /// In this example there is simply a counter and a set of resulting commands. 8 | /// But you could have other contextual data that is passed to each of the commands, 9 | /// (or both via envelopes to encapsulate) to aggregate data instead. 10 | /// 11 | public class MyInProcessCommand 12 | { 13 | public MyInProcessCommand(long counter, SerializableOddJob[] resultingCommands) 14 | { 15 | Counter = counter; 16 | ResultingCommands = resultingCommands; 17 | } 18 | public long Counter { get; protected set; } 19 | public SerializableOddJob[] ResultingCommands { get; protected set; } 20 | } 21 | } -------------------------------------------------------------------------------- /OddJob.Storage.SQLite/SQLiteJobQueueDataConnectionFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq.Expressions; 3 | using GlutenFree.Linq2Db.Helpers; 4 | using GlutenFree.OddJob.Storage.Sql.Common; 5 | using LinqToDB; 6 | using LinqToDB.Data; 7 | using LinqToDB.Mapping; 8 | 9 | namespace GlutenFree.OddJob.Storage.Sql.SQLite 10 | { 11 | public class SQLiteJobQueueDataConnectionFactory : IJobQueueDataConnectionFactory 12 | { 13 | private readonly string _connectionString; 14 | 15 | public SQLiteJobQueueDataConnectionFactory(string connectionString) 16 | { 17 | _connectionString = connectionString; 18 | } 19 | public DataConnection CreateDataConnection(MappingSchema mappingSchema) 20 | { 21 | return new ExpressionReplacingLinq2DbConnection(ProviderName.SQLiteClassic, _connectionString, mappingSchema,new List()); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Serializable/UnversionedTypeSerializer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace GlutenFree.OddJob.Serializable 5 | { 6 | public class UnversionedTypeSerializer : ITypeNameSerializer 7 | { 8 | public string GetTypeName(Type type) 9 | { 10 | if (type != null) 11 | { 12 | var str = _assemblyRegex.Replace(type.AssemblyQualifiedName, ""); 13 | var str2 = str.Replace(TargetPlatformHelpers.GetCoreAssemblyName(), TargetPlatformHelpers.coreLibString); 14 | return str2; 15 | } 16 | 17 | return ""; 18 | } 19 | 20 | 21 | //(\[[^,]*?,\s*[^,]*?)(,[^\]]*?)(\])(\],[^,]*) 22 | //(\[[^,]*?,\s*[^,]*?)(,[^\]]*?)(\]) 23 | internal static Regex _assemblyRegex = new Regex(@"(\,\s*Version\=\S*\sCulture\S*,\sPublicKeyToken=[A-Za-z0-9_]*)", RegexOptions.Compiled); 24 | } 25 | } -------------------------------------------------------------------------------- /OddJob/RetryParameters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GlutenFree.OddJob.Interfaces; 3 | 4 | namespace GlutenFree.OddJob 5 | { 6 | public class RetryParameters : IRetryParameters 7 | { 8 | public int RetryCount { get; set; } 9 | public DateTime? LastAttempt { get; set; } 10 | 11 | public int MaxRetries { get; set; } 12 | public TimeSpan MinRetryWait { get; set; } 13 | 14 | public RetryParameters() 15 | { 16 | 17 | } 18 | 19 | public RetryParameters(int maxRetries, TimeSpan minRetryWait) 20 | { 21 | MaxRetries = maxRetries; 22 | MinRetryWait = minRetryWait; 23 | } 24 | 25 | public RetryParameters(int maxRetries, TimeSpan minRetryWait, int retryCount, DateTime? lastAttempt) : this(maxRetries, minRetryWait) 26 | { 27 | this.RetryCount = retryCount; 28 | this.LastAttempt = lastAttempt; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /OddJob.Storage.SqlServer.Test/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka/StandardConsoleEngineLoggerConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Akka.Dispatch; 3 | using Akka.Event; 4 | 5 | namespace GlutenFree.OddJob.Execution.Akka 6 | { 7 | /// 8 | /// Uses the default Execution engine configuration of 9 | /// 10 | public class StandardConsoleEngineLoggerConfig : IExecutionEngineLoggerConfig 11 | { 12 | public StandardConsoleEngineLoggerConfig(string logLevel) 13 | { 14 | LogLevel = logLevel; 15 | } 16 | /// 17 | /// Returns no logger, which results in the default console logger being used. 18 | /// 19 | public Func> LoggerTypeFactory 20 | { 21 | get { return null; } 22 | } 23 | 24 | /// 25 | /// Defaults to INFO 26 | /// 27 | public string LogLevel { get; protected set; } 28 | } 29 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Messages/AggregatedCommand.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Serializable; 2 | 3 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 4 | { 5 | /// 6 | /// A final Command to be sent to the Result Writer. 7 | /// If you wish to work with Guaranteed delivery semantics, 8 | /// this could have a Sequence number (if using something like Akka.NET) 9 | /// Or another ID for your system of choice. 10 | /// 11 | public class AggregatedCommand 12 | { 13 | //If you want to work with guaranteed delivery semantics, 14 | //this would be a good place to put a sequence number for the command writer to use for acknowledging. 15 | public AggregatedCommand(SerializableOddJob[] resultingCommands) 16 | { 17 | ResultingCommands = resultingCommands; 18 | } 19 | public SerializableOddJob[] ResultingCommands { get; protected set; } 20 | } 21 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Storage.Sql.SQLite.Test/GlutenFree.OddJob.Storage.Sql.SQLite.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452;netcoreapp2.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/DbDtos/SqlServerDbOddJobMetaData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using LinqToDB.Mapping; 3 | 4 | namespace GlutenFree.OddJob.Storage.Sql.Common.DbDtos 5 | { 6 | public class SqlCommonDbOddJobMetaData 7 | { 8 | [Identity] 9 | [PrimaryKey] 10 | public long Id { get; set; } 11 | public Guid JobGuid { get; set; } 12 | 13 | public string TypeExecutedOn { get; set; } 14 | 15 | public string MethodName { get; set; } 16 | 17 | public int MaxRetries { get; set; } 18 | public int MinRetryWait { get; set; } 19 | public DateTime? LastAttempt { get; set; } 20 | public int RetryCount { get; set; } 21 | public string Status { get; set; } 22 | public string QueueName { get; set; } 23 | public DateTimeOffset? DoNotExecuteBefore { get; set; } 24 | public DateTime? LockClaimTime { get; set; } 25 | public Guid? LockGuid { get; set; } 26 | public DateTime? CreatedDate { get; set; } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Actors/DecoratorService1/ConsoleWriterAggregator.cs: -------------------------------------------------------------------------------- 1 | using Akka.Actor; 2 | using GlutenFree.OddJob.Serializable; 3 | 4 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 5 | { 6 | /// 7 | /// An Aggregator that Decorates the command with an additional piece of work. 8 | /// 9 | public class ConsoleWriterAggregator : ActorBase 10 | { 11 | protected override bool Receive(object message) 12 | { 13 | if (message is MyInProcessCommand) 14 | { 15 | var msg = (MyInProcessCommand) message; 16 | Context.Sender.Tell(new MyInProcessCommand(msg.Counter, msg.ResultingCommands.WithItem( 17 | SerializableJobCreator.CreateJobDefinition((IService1Contract c) => 18 | c.WriteToConsole(string.Format("Hello from {0}", msg.Counter)), queueName:"console")))); 19 | 20 | } 21 | 22 | return true; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Serializable/SerializableOddJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GlutenFree.OddJob.Serializable 4 | { 5 | /// 6 | /// A Job Definition in a Serializable format. 7 | /// Type information is stored in Assembly qualified Name format. 8 | /// Parameter Data is stored as JSON. 9 | /// Other data is stored in standard .NET types (GUID,string, etc.) 10 | /// 11 | public class SerializableOddJob 12 | { 13 | 14 | 15 | public SerializableOddJob() 16 | { 17 | 18 | 19 | } 20 | public Guid JobId { get; set; } 21 | public OddJobSerializedParameter[] JobArgs { get; set; } 22 | public string TypeExecutedOn { get; set; } 23 | public string MethodName { get; set; } 24 | public string Status { get; set; } 25 | public string[] MethodGenericTypes { get; set; } 26 | public RetryParameters RetryParameters { get; set; } 27 | public DateTimeOffset? ExecutionTime { get; set; } 28 | public string QueueName { get; set; } 29 | } 30 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Execution.BaseTests/OddJobWithMetaAndStorageData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GlutenFree.OddJob.Interfaces; 3 | 4 | namespace GlutenFree.OddJob.Execution.BaseTests 5 | { 6 | public class OddJobWithMetaAndStorageData : IOddJobWithMetadata 7 | { 8 | public RetryParameters RetryParameters { get; set; } 9 | 10 | public Guid JobId { get; set; } 11 | 12 | public OddJobParameter[] JobArgs { get; set; } 13 | 14 | public Type TypeExecutedOn { get; set; } 15 | 16 | public string MethodName { get; set; } 17 | public string Status { get; set; } 18 | public Type[] MethodGenericTypes { get; set; } 19 | public DateTime CreatedOn { get; set; } 20 | public DateTime QueueTime { get; set; } 21 | public DateTime? LastAttemptTime { get; set; } 22 | public DateTime? FailureTime { get; set; } 23 | IRetryParameters IOddJobWithMetadata.RetryParameters { get { return RetryParameters; } } 24 | public DateTimeOffset? ExecutionTime { get; set; } 25 | public string Queue { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/GlutenFree.OddJob.Samples.Serialized.CommandAggregator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | netcoreapp2.1 6 | false 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /OddJob.Storage.SqlServer/SqlServerDataConnectionFactory.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Storage.Sql.Common; 2 | using LinqToDB.Data; 3 | using LinqToDB.DataProvider.SqlServer; 4 | using LinqToDB.Mapping; 5 | 6 | namespace GlutenFree.OddJob.Storage.Sql.SqlServer 7 | { 8 | public class SqlServerDataConnectionFactory : IJobQueueDataConnectionFactory 9 | { 10 | 11 | private readonly IJobQueueDbConnectionFactory _connectionFactory; 12 | private readonly SqlServerVersion _sqlServerVersion; 13 | public SqlServerDataConnectionFactory(IJobQueueDbConnectionFactory connectionFactory, SqlServerVersion sqlServerVersion) 14 | { 15 | _connectionFactory = connectionFactory; 16 | _sqlServerVersion = sqlServerVersion; 17 | } 18 | public DataConnection CreateDataConnection(MappingSchema mappingSchema) 19 | { 20 | return new DataConnection(new SqlServerDataProvider("sqlserver-oddjob",_sqlServerVersion), _connectionFactory.CreateDbConnection(),true).AddMappingSchema(mappingSchema); 21 | 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/Scripts/WebSharper/WebSharper.Main/AnimFrame.js: -------------------------------------------------------------------------------- 1 | (function () { 2 | var lastTime = 0; 3 | var vendors = ['webkit', 'moz']; 4 | for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 5 | window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']; 6 | window.cancelAnimationFrame = 7 | window[vendors[x] + 'CancelAnimationFrame'] || window[vendors[x] + 'CancelRequestAnimationFrame']; 8 | } 9 | 10 | if (!window.requestAnimationFrame) 11 | window.requestAnimationFrame = function (callback, element) { 12 | var currTime = new Date().getTime(); 13 | var timeToCall = Math.max(0, 16 - (currTime - lastTime)); 14 | var id = window.setTimeout(function () { callback(currTime + timeToCall); }, 15 | timeToCall); 16 | lastTime = currTime + timeToCall; 17 | return id; 18 | }; 19 | 20 | if (!window.cancelAnimationFrame) 21 | window.cancelAnimationFrame = function (id) { 22 | clearTimeout(id); 23 | }; 24 | }()); 25 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Actors/DecoratorService2/CounterWriterAggregator.cs: -------------------------------------------------------------------------------- 1 | using Akka.Actor; 2 | using GlutenFree.OddJob.Serializable; 3 | 4 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 5 | { 6 | /// 7 | /// An Aggregator that Decorates the command with an additional piece of work. 8 | /// 9 | public class CounterWriterAggregator : ActorBase 10 | { 11 | protected override bool Receive(object message) 12 | { 13 | if (message is MyInProcessCommand) 14 | { 15 | var msg = (MyInProcessCommand)message; 16 | Context.Sender.Tell(new MyInProcessCommand(msg.Counter, msg.ResultingCommands.WithItem( 17 | SerializableJobCreator.CreateJobDefinition((IService2Contract c) => 18 | c.WriteCounter>( 19 | new MyParam {Param = "genericParam"}), 20 | queueName: "counter")))); 21 | } 22 | 23 | return true; 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/GlutenFree.OddJob.Storage.SQL.Common.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452;netstandard2.0 5 | GlutenFree.OddJob.Storage.Sql.Common 6 | GlutenFree.OddJob.Storage.Sql.Common 7 | Oddjob Base SQL Storage Implementation for Storage and retrieval of jobs. 8 | job jobs jobscheduler scheduler oddjob task future later sql sqlcommon common 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Serializable/TargetPlatformHelpers.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Serializable 2 | { 3 | public static class TargetPlatformHelpers 4 | { 5 | private static object _coreAssemblyNameWrteLock = new object(); 6 | private static string _assemblyCoreType = null; 7 | public const string coreLibString = "%coretarget%"; 8 | 9 | public static string ReplaceCoreTypes(string typeString) 10 | { 11 | return typeString.Replace(coreLibString, GetCoreAssemblyName()); 12 | } 13 | 14 | public static string GetCoreAssemblyName() 15 | { 16 | if (_assemblyCoreType == null) 17 | { 18 | lock (_coreAssemblyNameWrteLock) 19 | { 20 | if (_assemblyCoreType == null) 21 | { 22 | _assemblyCoreType = 23 | UnversionedTypeSerializer._assemblyRegex.Replace(typeof(string).Assembly.FullName, ""); 24 | } 25 | } 26 | } 27 | 28 | return _assemblyCoreType; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /OddJob/Interfaces/IJobQueueAdder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GlutenFree.OddJob.Interfaces 5 | { 6 | public interface IJobQueuePurger 7 | { 8 | void PurgeQueue(string name, string stateToPurge, DateTime purgeOlderThan); 9 | } 10 | public interface IJobQueueAdder 11 | { 12 | /// 13 | /// Adds a Job to the Queue. 14 | /// 15 | /// The Type being used for the Job being executed. 16 | /// The Job Expression. Should be a single method call with parameters. 17 | /// Retry Parameters to use for the job 18 | /// A time in the future to execute the job. 19 | /// The Queue to place the job in. 20 | /// GUID for the added Job 21 | Guid AddJob(Expression> jobExpression, RetryParameters retryParameters=null, DateTimeOffset? executionTime = null, string queueName = "default"); 22 | } 23 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/Readme.MD: -------------------------------------------------------------------------------- 1 | # Oddjob Manager Presenatation Layer (Websharper) 2 | 3 | This Project is designed to be an example of how to build a Job Manager for Oddjob. 4 | 5 | I've used Websharper here because: 6 | 7 | - I wanted to have an Easily Refactorable Presenatation Layer 8 | - Websharper lets you write HTML and Javascript in C#, allowing one to more easily utilize C# refactoring tools and compile analysis. 9 | 10 | - Low friction Remoting 11 | - This ties into the above, but Websharper makes it easy to call server-side code from client side, again with safe refactoring. 12 | 13 | - Simpler Packaging (theoretically, future) 14 | - Websharper facilitates the use of Functional code to build your websites; this should make it easier to package this as a configurable library to attach to a given website/implementatipn. 15 | 16 | 17 | 18 | # TO DO: 19 | 20 | This all runs in a fairly 'pure' Websharper Template project. We still want to: 21 | 22 | - Make it something that can be integrated into ASP.NET Core. 23 | 24 | - Make it more configurable, use things like ASP.NET DI. 25 | 26 | - Allow Auth Schemes. -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/Web.config: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka/HardInjectedJobExecutorShell.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using Akka.Actor; 4 | 5 | namespace GlutenFree.OddJob.Execution.Akka 6 | { 7 | public class HardInjectedJobExecutorShell : BaseJobExecutorShell 8 | where TJobLayerActor: JobQueueLayerActor 9 | where TJobWorkerActor : JobWorkerActor 10 | where TJobCoordinator : JobQueueCoordinator 11 | { 12 | public HardInjectedJobExecutorShell(Expression> jobQueueFunc, 13 | Expression> workerFunc, 14 | Expression> coordinatorFunc, 15 | IExecutionEngineLoggerConfig loggerConfig) : base(loggerConfig) 16 | { 17 | JobQueueProps = Props.Create(jobQueueFunc); 18 | WorkerProps = Props.Create(workerFunc); 19 | CoordinatorProps = Props.Create(coordinatorFunc); 20 | } 21 | 22 | 23 | protected override Props WorkerProps { get; } 24 | protected override Props JobQueueProps { get; } 25 | protected override Props CoordinatorProps { get; } 26 | } 27 | 28 | 29 | } -------------------------------------------------------------------------------- /OddJob/JobCreator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using System.Runtime.Serialization; 4 | 5 | namespace GlutenFree.OddJob 6 | { 7 | public class JobCreationException : Exception 8 | { 9 | public JobCreationException() 10 | { 11 | } 12 | 13 | public JobCreationException(string message) : base(message) 14 | { 15 | } 16 | 17 | public JobCreationException(string message, Exception innerException) : base(message, innerException) 18 | { 19 | } 20 | 21 | protected JobCreationException(SerializationInfo info, StreamingContext context) : base(info, context) 22 | { 23 | } 24 | } 25 | 26 | /// 27 | /// Optional way to pass Jobs that are Static method calls (i.e. calls in a Static Class) 28 | /// 29 | public class StaticClassJob 30 | { 31 | 32 | } 33 | 34 | public static class JobCreator 35 | { 36 | public static OddJob Create(Expression> jobExpr) 37 | { 38 | return ExpressionBasedJobCreator.CreateInternal(jobExpr.Body as MethodCallExpression); 39 | } 40 | 41 | } 42 | } -------------------------------------------------------------------------------- /OddJob.Storage.FileSystem/FileSystemJobMetaData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GlutenFree.OddJob.Interfaces; 3 | 4 | namespace GlutenFree.OddJob.Storage.FileSystem 5 | { 6 | public class FileSystemJobMetaData : IOddJobWithMetadata 7 | { 8 | public RetryParameters RetryParameters { get; set; } 9 | 10 | public Guid JobId {get;set;} 11 | 12 | public OddJobParameter[] JobArgs {get;set;} 13 | 14 | public Type TypeExecutedOn {get;set;} 15 | 16 | public string MethodName {get;set;} 17 | public string QueueName { get; set; } 18 | public DateTime CreatedOn { get; set; } 19 | public string Status { get; set; } 20 | public Type[] MethodGenericTypes { get; set; } 21 | public DateTime QueueTime { get; internal set; } 22 | public DateTime FailureTime { get; internal set; } 23 | public DateTime LastAttemptTime { get; internal set; } 24 | public DateTimeOffset? ExecutionTime { get; set; } 25 | public string Queue { get; set; } 26 | IRetryParameters IOddJobWithMetadata.RetryParameters 27 | { 28 | get 29 | { 30 | return RetryParameters; 31 | } 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Service1/Service1.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Execution.Akka; 2 | using GlutenFree.OddJob.Serializable; 3 | using GlutenFree.OddJob.Storage.Sql.SQLite; 4 | 5 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 6 | { 7 | public class Service1 8 | { 9 | public static BaseJobExecutorShell CreateAndStartEngine1() 10 | { 11 | var container = new SimpleInjector.Container(); 12 | container.Register(); 13 | container.Verify(); 14 | var engine = new Execution.Akka.HardInjectedJobExecutorShell( 15 | () => new JobQueueLayerActor(new SQLiteJobQueueManager(SQLiteSampleHelper.ConnFactoryFunc(), 16 | GenerateMappings.TableConfigurations["console"], new NullOnMissingTypeJobTypeResolver())), 17 | () => new JobWorkerActor(new DefaultJobExecutor(new SimpleInjectorContainerFactory(container))), 18 | () => new JobQueueCoordinator(), new StandardConsoleEngineLoggerConfig("DEBUG")); 19 | engine.StartJobQueue("console", 20, 3); 20 | return engine; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /OddJob.Execution.Akka.Test/MockJobWorker.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Akka.Actor; 3 | using GlutenFree.OddJob.Execution.Akka.Messages; 4 | 5 | namespace GlutenFree.OddJob.Execution.Akka.Test 6 | { 7 | public class MockJobWorker : ActorBase 8 | { 9 | public IActorRef ForwardTo { get; set; } 10 | public MockJobWorker(IActorRef forwardTo) 11 | { 12 | ForwardTo = forwardTo; 13 | } 14 | protected override bool Receive(object message) 15 | { 16 | if (message is ExecuteJobRequest) 17 | { 18 | ForwardTo.Forward(message); 19 | if (message is ExecuteJobRequest) 20 | { 21 | var msg = message as ExecuteJobRequest; 22 | if (msg.JobData.MethodName=="Fail") 23 | { 24 | Context.Sender.Tell(new JobFailed(msg.JobData, new Exception("derp"))); 25 | } 26 | else if (msg.JobData.MethodName =="Success") 27 | { 28 | Context.Sender.Tell(new JobSuceeded(msg.JobData)); 29 | } 30 | } 31 | } 32 | return true; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Service2/Service2.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Execution.Akka; 2 | using GlutenFree.OddJob.Serializable; 3 | using GlutenFree.OddJob.Storage.Sql.SQLite; 4 | 5 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 6 | { 7 | public class Service2 8 | { 9 | public static BaseJobExecutorShell CreateAndStartEngine2() 10 | { 11 | var container = new SimpleInjector.Container(); 12 | container.Register(); 13 | container.Verify(); 14 | var engine = new GlutenFree.OddJob.Execution.Akka.HardInjectedJobExecutorShell( 15 | () => new JobQueueLayerActor(new SQLiteJobQueueManager(SQLiteSampleHelper.ConnFactoryFunc(), 16 | GenerateMappings.TableConfigurations["counter"], new NullOnMissingTypeJobTypeResolver())), 17 | () => new JobWorkerActor(new DefaultJobExecutor(new SimpleInjectorContainerFactory(container))), 18 | () => new JobQueueCoordinator(), new StandardConsoleEngineLoggerConfig("DEBUG")); 19 | engine.StartJobQueue("counter", 20, 3); 20 | return engine; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /OddJob.Storage.SqlServer/GlutenFree.OddJob.Storage.Sql.SqlServer.0.9.0/GlutenFree.OddJob.Storage.Sql.SqlServer.nuspec: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | GlutenFree.OddJob.Storage.Sql.SqlServer 5 | 0.9.0 6 | GlutenFree.OddJob.Storage.SqlServer 7 | Gluten Free Solutions 8 | Gluten Free Solutions 9 | false 10 | https://github.com/to11mtm/OddJob/blob/master/LICENSE 11 | https://github.com/to11mtm/OddJob/ 12 | OddJob - SqlServer Storage Provider 13 | First Nuget Release 14 | Copyright 2018 15 | job jobs jobscheduler scheduler oddjob task future later sql server sqlserver 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS-AspnetCore/AsyncOddJobRemotingHandlerDecorator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using SimpleInjector; 4 | using SimpleInjector.Lifestyles; 5 | 6 | namespace GlutenFree.OddJob.Manager.Presentation.WS_AspnetCore 7 | { 8 | //We use this to help get around Websharper's treatment of all Remoting handlers as singletons. 9 | //This will let us use an Async Lifestyle within the scope of said singleton. 10 | public class AsyncOddJobRemotingHandlerDecorator : IRemotingHandler 11 | { 12 | private readonly Func> _decorateeFactory; 13 | private readonly Container _container; 14 | public AsyncOddJobRemotingHandlerDecorator(Container container, Func> decorateeFactory) 15 | { 16 | _container = container; 17 | _decorateeFactory = decorateeFactory; 18 | } 19 | 20 | public Task Handle(TRequest command) 21 | { 22 | using (AsyncScopedLifestyle.BeginScope(_container)) 23 | { 24 | var handler = _decorateeFactory(); 25 | return handler.Handle(command); 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.WebSharper/Client.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using WebSharper; 3 | using WebSharper.UI; 4 | using Html = WebSharper.UI.Client.Html; 5 | 6 | namespace GlutenFree.OddJob.Manager.Presentation.WS 7 | { 8 | [JavaScript] 9 | public static class Client 10 | { 11 | static public IControlBody Main() 12 | { 13 | var rvInput = Var.Create(""); 14 | var submit = Submitter.CreateOption(rvInput.View); 15 | var vReversed = 16 | submit.View.MapAsync(input => 17 | { 18 | if (input == null) 19 | return Task.FromResult(""); 20 | return Remoting.DoSomething(input.Value); 21 | }); 22 | return Html.div( 23 | Html.input(rvInput), 24 | Html.button("Send", submit.Trigger), 25 | Html.hr(), 26 | Html.h4( 27 | Html.attr.@class("text-muted"), 28 | "The server responded:", 29 | Html.div( 30 | Html.attr.@class("jumbotron"), 31 | Html.h1(vReversed) 32 | ) 33 | ) 34 | ); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /OddJob.Execution.Akka.Test/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /OddJob/OldDefaultJobExecutor.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Reflection; 3 | using GlutenFree.OddJob.Interfaces; 4 | 5 | namespace GlutenFree.OddJob 6 | { 7 | public class OldDefaultJobExecutor : IJobExecutor 8 | { 9 | public OldDefaultJobExecutor(IContainerFactory containerFactory) 10 | { 11 | _containerFactory = containerFactory; 12 | } 13 | private IContainerFactory _containerFactory; 14 | public void ExecuteJob(IOddJob expr) 15 | { 16 | var instance = _containerFactory.CreateInstance(expr.TypeExecutedOn); 17 | MethodInfo method = null; 18 | if (expr.MethodGenericTypes != null && expr.MethodGenericTypes.Length > 0) 19 | { 20 | method = expr.TypeExecutedOn.GetMethods().Where(q => 21 | q.IsGenericMethod && q.GetGenericArguments().Length == expr.MethodGenericTypes.Length).FirstOrDefault().MakeGenericMethod(expr.MethodGenericTypes); 22 | } 23 | else 24 | { 25 | method = expr.TypeExecutedOn.GetMethod(expr.MethodName); 26 | } 27 | 28 | method.Invoke(instance, expr.JobArgs.Select(q=>q.Value).ToArray()); 29 | _containerFactory.Relase(instance); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /GlutenFree.Linq2Db.Helpers/ExpressionHelpers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | 4 | namespace GlutenFree.Linq2Db.Helpers 5 | { 6 | //TODO: This is good for lots of things, not just Linq2DB! It should be in it's own library. 7 | public static class ExpressionHelpers 8 | { 9 | public static Expression> CombineBinaryExpression(Expression> expr, 10 | Expression> toAdd, bool trueAnd) 11 | { 12 | if (expr == null) 13 | { 14 | return toAdd; 15 | } 16 | else 17 | { 18 | if (trueAnd) 19 | { 20 | return Expression.Lambda>(Expression.AndAlso( 21 | new SwapVisitor(expr.Parameters[0], toAdd.Parameters[0]).Visit(expr.Body), toAdd.Body), 22 | toAdd.Parameters); 23 | 24 | } 25 | else 26 | { 27 | return Expression.Lambda>(Expression.OrElse( 28 | new SwapVisitor(expr.Parameters[0], toAdd.Parameters[0]).Visit(expr.Body), toAdd.Body), 29 | toAdd.Parameters); 30 | } 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/Mapping.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Storage.Sql.Common.DbDtos; 2 | using LinqToDB.Mapping; 3 | 4 | namespace GlutenFree.OddJob.Storage.Sql.Common 5 | { 6 | static class Mapping 7 | { 8 | public static FluentMappingBuilder BuildMappingSchema(ISqlDbJobQueueTableConfiguration _jobQueueTableConfiguration) 9 | { 10 | var mapper = new LinqToDB.Mapping.FluentMappingBuilder(MappingSchema.Default); 11 | mapper.Entity().HasAttribute( 12 | new TableAttribute(_jobQueueTableConfiguration.QueueTableName) { IsColumnAttributeRequired = false, Name = _jobQueueTableConfiguration.QueueTableName}); 13 | mapper.Entity().HasAttribute( 14 | new TableAttribute(_jobQueueTableConfiguration.ParamTableName){IsColumnAttributeRequired = false, Name = _jobQueueTableConfiguration.ParamTableName}); 15 | mapper.Entity().HasAttribute( 16 | new TableAttribute(_jobQueueTableConfiguration.JobMethodGenericParamTableName) 17 | { 18 | IsColumnAttributeRequired = false, 19 | Name = _jobQueueTableConfiguration.JobMethodGenericParamTableName 20 | }); 21 | 22 | return mapper; 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /OddJob.Storage.SqlServer.Test/GlutenFree.OddJob.Storage.Sql.SqlServer.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452;netcoreapp2.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | ..\packages\linq2db.2.2.0\lib\net45\linq2db.dll 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Storage.Sql.SQLite.Test/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GlutenFree.OddJob.Interfaces; 3 | using GlutenFree.OddJob.Serializable; 4 | using GlutenFree.OddJob.Storage.BaseTests; 5 | using GlutenFree.OddJob.Storage.Sql.Common; 6 | 7 | namespace GlutenFree.OddJob.Storage.Sql.SQLite.Test 8 | { 9 | public class SQLiteStorageTest : StorageTests 10 | { 11 | public SQLiteStorageTest() 12 | { 13 | 14 | UnitTestTableHelper.EnsureTablesExist(); 15 | 16 | 17 | } 18 | 19 | protected override Func JobAddStoreFunc 20 | { 21 | get 22 | { 23 | return () => new SQLiteJobQueueAdder( 24 | new SQLiteJobQueueDataConnectionFactory(UnitTestTableHelper.connString) 25 | , 26 | new DefaultJobAdderQueueTableResolver(new SqlDbJobQueueDefaultTableConfiguration())); 27 | } 28 | } 29 | 30 | protected override Func JobMgrStoreFunc 31 | { 32 | get 33 | { 34 | return () => new SQLiteJobQueueManager( 35 | new SQLiteJobQueueDataConnectionFactory(UnitTestTableHelper.connString), 36 | new SqlDbJobQueueDefaultTableConfiguration(),new NullOnMissingTypeJobTypeResolver()); 37 | } 38 | } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /GlutenFree.Linq2Db.Helpers/ExprHelpers.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace GlutenFree.Linq2Db.Helpers 5 | { 6 | public static class ExprHelpers 7 | { 8 | public static bool LikeAny(this string myString, IEnumerable likeSet) 9 | { 10 | return likeSet.Any(s => myString.Contains(s)); 11 | } 12 | 13 | public static bool LikeAnyLower(this string myString, IEnumerable likeSet) 14 | { 15 | return likeSet.Any(s => myString.ToLower().Contains(s.ToLower())); 16 | } 17 | 18 | public static bool LikeAnyUpper(this string myString, IEnumerable likeSet) 19 | { 20 | return likeSet.Any(s => myString.ToUpper().Contains(s.ToUpper())); 21 | } 22 | 23 | public static bool LikeAll(this string myString, IEnumerable likeSet) 24 | { 25 | return likeSet.All(s => myString.Contains(s)); 26 | } 27 | 28 | public static bool LikeAllLower(this string myString, IEnumerable likeSet) 29 | { 30 | return likeSet.All(s => myString.ToLower().Contains(s.ToLower())); 31 | } 32 | 33 | public static bool LikeAllUpper(this string myString, IEnumerable likeSet) 34 | { 35 | return likeSet.All(s => myString.ToUpper().Contains(s.ToUpper())); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.WebSharper/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka.Test/GlutenFree.OddJob.Execution.Akka.Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net452;netcoreapp2.1 5 | 6 | false 7 | 8 | GlutenFree.OddJob.Execution.Akka.Test 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/TableResolver/QueueNameBasedJobAdderQueueTableResolver.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using GlutenFree.OddJob.Serializable; 3 | 4 | namespace GlutenFree.OddJob.Storage.Sql.Common 5 | { 6 | /// 7 | /// Retrieves Table configurations based on the Queue Name for a job 8 | /// If no mapping is found, the default table is used. 9 | /// 10 | public class QueueNameBasedJobAdderQueueTableResolver : IJobAdderQueueTableResolver 11 | { 12 | private readonly Dictionary _queueTableMappings; 13 | private readonly ISqlDbJobQueueTableConfiguration _defaultTableConfiguration; 14 | 15 | public QueueNameBasedJobAdderQueueTableResolver( 16 | Dictionary queueTableConfigurations, 17 | ISqlDbJobQueueTableConfiguration defaultTableConfiguration) 18 | { 19 | _queueTableMappings = queueTableConfigurations; 20 | _defaultTableConfiguration = defaultTableConfiguration; 21 | } 22 | 23 | public ISqlDbJobQueueTableConfiguration GetConfigurationForJob(SerializableOddJob job) 24 | { 25 | if (_queueTableMappings.ContainsKey(job.QueueName)) 26 | { 27 | return _queueTableMappings[job.QueueName]; 28 | } 29 | 30 | return _defaultTableConfiguration; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.WebSharper/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka/JobWorkerActor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Akka.Actor; 3 | using GlutenFree.OddJob.Execution.Akka.Messages; 4 | 5 | namespace GlutenFree.OddJob.Execution.Akka 6 | { 7 | public class JobWorkerActor : ActorBase 8 | { 9 | public IJobExecutor _jobExecutor { get; protected set; } 10 | 11 | public JobWorkerActor(IJobExecutor jobExecutor) 12 | { 13 | _jobExecutor = jobExecutor; 14 | } 15 | 16 | protected override bool Receive(object message) 17 | { 18 | if (message is ShutDownQueues) 19 | { 20 | //By design when we get this message it should mean the queue is drained. 21 | Context.Sender.Tell(new QueueShutDown()); 22 | } 23 | else if (message is ExecuteJobRequest) 24 | { 25 | RunJob(message as ExecuteJobRequest); 26 | } 27 | else 28 | { 29 | //Unhandled. 30 | return false; 31 | } 32 | return true; 33 | } 34 | public void RunJob(ExecuteJobRequest request) 35 | { 36 | try 37 | { 38 | _jobExecutor.ExecuteJob(request.JobData); 39 | Context.Sender.Tell(new JobSuceeded(request.JobData)); 40 | } 41 | catch(Exception ex) 42 | { 43 | Context.Sender.Tell(new JobFailed(request.JobData, ex)); 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka/Messages/SetJobQueueConfiguration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq.Expressions; 3 | using Akka.Actor; 4 | 5 | namespace GlutenFree.OddJob.Execution.Akka.Messages 6 | { 7 | public class SetJobQueueConfiguration 8 | { 9 | public string QueueName { get; protected set; } 10 | public int NumWorkers { get; protected set; } 11 | public int PulseDelayInSeconds { get; protected set; } 12 | public int FirstPulseDelayInSeconds { get; protected set; } 13 | public Props WorkerProps { get; protected set; } 14 | public Props QueueProps { get; protected set; } 15 | public bool AggressiveSweep { get; protected set; } 16 | public Expression> PriorityExpression { get; protected set; } 17 | public SetJobQueueConfiguration(Props workerProps, Props queueProps, string queueName, int numWorkers, 18 | int pulseDelayInSeconds, int firstPulseDelayInSeconds = 5, Expression> priorityExpression = null, bool aggressiveSweep=false) 19 | { 20 | QueueName = queueName; 21 | NumWorkers = numWorkers; 22 | PulseDelayInSeconds = pulseDelayInSeconds; 23 | FirstPulseDelayInSeconds = firstPulseDelayInSeconds; 24 | WorkerProps = workerProps; 25 | QueueProps = queueProps; 26 | PriorityExpression = priorityExpression ?? ((JobLockData p)=> p.MostRecentDate); 27 | AggressiveSweep = aggressiveSweep; 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /OddJob.SampleApp.Console/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("OddJob.SampleApp.Console")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("OddJob.SampleApp.Console")] 12 | [assembly: AssemblyCopyright("Copyright © 2018")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("e8bd023a-4bec-40b9-8fca-feb200922dcd")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /OddJob.Storage.BaseTests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("OddJob.Storage.BaseTests")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("OddJob.Storage.BaseTests")] 12 | [assembly: AssemblyCopyright("Copyright © 2018")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("6f6aa4d7-a77c-4c32-8f10-1240ad39fb11")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Execution.ThreadPool/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("GlutenFree.OddJob.Execution.ThreadPool")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("GlutenFree.OddJob.Execution.ThreadPool")] 12 | [assembly: AssemblyCopyright("Copyright © 2018")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("8f4d96a6-f2f7-4307-9729-088c3869787a")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("GlutenFree.OddJob.Manager.Presentation.WS")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("GlutenFree.OddJob.Manager.Presentation.WS")] 12 | [assembly: AssemblyCopyright("Copyright © 2018")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("561043ac-7e1e-48da-b544-480eade8c0e1")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /OddJob.Storage.FileSystem/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("OddJob.Storage.FileSystem")] 8 | [assembly: AssemblyDescription("OddJob - File System Storage Provider")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("Gluten Free Solutions")] 11 | [assembly: AssemblyProduct("OddJob.Storage.FileSystem")] 12 | [assembly: AssemblyCopyright("Copyright © 2018")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("55035d4f-b1db-4dfd-bb92-33bb1c96183a")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("0.9.8.0")] 35 | [assembly: AssemblyFileVersion("0.9.8.0")] 36 | -------------------------------------------------------------------------------- /OddJob.Storage.SQLite/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("GlutenFree.OddJob.Storage.SQLite")] 8 | [assembly: AssemblyDescription("OddJob - SQLite Storage Provider")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("Gluten Free Solutions")] 11 | [assembly: AssemblyProduct("GlutenFree.OddJob.Storage.SQLite")] 12 | [assembly: AssemblyCopyright("Copyright © 2018")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("29e7e72f-e6c0-41f6-a613-4aff6c402f14")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("0.9.8.0")] 35 | [assembly: AssemblyFileVersion("0.9.8.0")] 36 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.WebSharper/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("GlutenFree.OddJob.Manager.WebSharper")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("GlutenFree.OddJob.Manager.WebSharper")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("53a4b2ab-5e3e-424b-b984-354a518a0744")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka.Test/QueueLayerMock.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Akka.Actor; 3 | using GlutenFree.OddJob.Execution.Akka.Messages; 4 | using GlutenFree.OddJob.Execution.BaseTests; 5 | 6 | namespace GlutenFree.OddJob.Execution.Akka.Test 7 | { 8 | public class QueueLayerMock : ActorBase 9 | { 10 | IActorRef ForwardTo; 11 | string GenerateJobType; 12 | public QueueLayerMock(IActorRef forwardTo, string generateJobType) 13 | { 14 | ForwardTo = forwardTo; 15 | GenerateJobType = generateJobType; 16 | } 17 | protected override bool Receive(object message) 18 | { 19 | ForwardTo.Forward(message); 20 | if (message is GetJobs) 21 | { 22 | Context.Sender.Tell(new[] 23 | { 24 | new OddJobWithMetaAndStorageData() 25 | { 26 | CreatedOn = DateTime.Now, FailureTime = null, 27 | JobArgs = new OddJobParameter[] 28 | { 29 | new OddJobParameter() {Value = 0}, new OddJobParameter() {Value = 1}, 30 | new OddJobParameter() {Value = "derp"} 31 | }, 32 | JobId = Guid.NewGuid(), LastAttemptTime = null, MethodName = GenerateJobType, 33 | QueueTime = DateTime.Now, RetryParameters = null, Status = JobStates.New, 34 | TypeExecutedOn = "derp".GetType() 35 | } 36 | }); 37 | } 38 | else return false; 39 | return true; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /OddJob/OddJob.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using GlutenFree.OddJob.Interfaces; 3 | 4 | namespace GlutenFree.OddJob 5 | { 6 | public class OddJob : IOddJob 7 | { 8 | /// 9 | /// The Job ID. Uniquely generated when the job is created. 10 | /// 11 | public Guid JobId { get; protected set; } 12 | /// 13 | /// Array of Job arguments. 14 | /// 15 | public OddJobParameter[] JobArgs { get; protected set; } 16 | /// 17 | /// Gets the Type the Job is Executed on. 18 | /// This will include any Generic parameters on the type (not method) in question 19 | /// 20 | public Type TypeExecutedOn { get; protected set; } 21 | /// 22 | /// Gets the Method name for the Job 23 | /// 24 | public string MethodName { get; protected set; } 25 | /// 26 | /// Indicates the current Status for the Job. 27 | /// 28 | public string Status { get; protected set; } 29 | /// 30 | /// Contains the Generic Types used by the method. 31 | /// 32 | public Type[] MethodGenericTypes { get; protected set; } 33 | public OddJob(string methodName, OddJobParameter[] jobArgs, Type typeExecutedOn, Type[] methodGenericTypes, string status=JobStates.New) 34 | { 35 | JobId = Guid.NewGuid(); 36 | MethodName = methodName; 37 | JobArgs = jobArgs; 38 | TypeExecutedOn = typeExecutedOn; 39 | Status = status; 40 | MethodGenericTypes = methodGenericTypes; 41 | } 42 | } 43 | 44 | 45 | 46 | 47 | } -------------------------------------------------------------------------------- /OddJob.Storage.BaseTests/TestData.cs: -------------------------------------------------------------------------------- 1 | namespace GlutenFree.OddJob.Storage.BaseTests 2 | { 3 | public static class TestConstants 4 | { 5 | public static readonly string SimpleParam = "simple"; 6 | public static readonly string OddParam1 = "odd1"; 7 | public static readonly string OddParam2 = "odd2"; 8 | public static readonly string NestedOddParam1 = "n1"; 9 | public static readonly string NestedOddParam2 = "n2"; 10 | } 11 | 12 | public class MockJobNoParam 13 | { 14 | public void DoThing() 15 | { 16 | //Intentionally empty, storage test. 17 | } 18 | } 19 | 20 | public class MockJobInClassWithArity 21 | { 22 | public void DoThing(TString simpleParam, OddParam oddParam) 23 | { 24 | //Intentionally Empty since this is testing storage. 25 | } 26 | } 27 | 28 | public class MockJobWithArity 29 | { 30 | public void DoThing(TString simpleParam, TOddParam oddParam) 31 | { 32 | //Intentionally empty since this is testing storage. 33 | } 34 | } 35 | 36 | public class MockJob 37 | { 38 | public void DoThing(string simpleParam, OddParam oddParam) 39 | { 40 | //Intentionally empty since this is testing storage. 41 | } 42 | } 43 | 44 | public class OddParam 45 | { 46 | public string Param1 { get; set; } 47 | public string Param2 { get; set; } 48 | public NestedOddParam Nested { get; set; } 49 | } 50 | 51 | public class NestedOddParam 52 | { 53 | public string NestedParam1 { get; set; } 54 | public string NestedParam2 { get; set; } 55 | } 56 | } 57 | 58 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS-AspnetCore/GlutenFree.OddJob.Manager.Presentation.WS_AspnetCore.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp2.1 5 | Website 6 | True 7 | $(MSBuildThisFileDirectory)/wwwroot 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka.Test/JobWorkerTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Akka.Actor; 3 | using Akka.TestKit.Xunit2; 4 | using GlutenFree.OddJob.Execution.Akka.Messages; 5 | using GlutenFree.OddJob.Execution.Akka.Test.Mocks; 6 | using GlutenFree.OddJob.Execution.BaseTests; 7 | using Xunit; 8 | 9 | namespace GlutenFree.OddJob.Execution.Akka.Test 10 | { 11 | public class JobWorkerTests : TestKit 12 | { 13 | [Fact] 14 | public void JobWorker_Returns_Success_for_Passed_Jobs() 15 | { 16 | var actor = Sys.ActorOf(Props.Create(() => new JobWorkerActor(new MockJobSuccessExecutor()))); 17 | var jobInfo = JobCreator.Create((MockJob m) => m.MockMethod()); 18 | var jobData = new OddJobWithMetaAndStorageData() { Status = JobStates.New, JobArgs = jobInfo.JobArgs, JobId = Guid.NewGuid(), MethodName = jobInfo.MethodName, CreatedOn = DateTime.Now, QueueTime = DateTime.Now, TypeExecutedOn = jobInfo.TypeExecutedOn }; 19 | actor.Tell(new ExecuteJobRequest(jobData)); 20 | ExpectMsg(); 21 | } 22 | 23 | [Fact] 24 | public void JobWorker_Returns_Failures_for_Failed_Jobs() 25 | { 26 | var actor = Sys.ActorOf(Props.Create(() => new JobWorkerActor(new MockJobFailureExecutor()))); 27 | var jobInfo = JobCreator.Create((MockJob m) => m.MockMethod()); 28 | var jobData = new OddJobWithMetaAndStorageData() { Status = JobStates.New, JobArgs = jobInfo.JobArgs, JobId = Guid.NewGuid(), MethodName = jobInfo.MethodName, CreatedOn = DateTime.Now, QueueTime = DateTime.Now, TypeExecutedOn = jobInfo.TypeExecutedOn }; 29 | actor.Tell(new ExecuteJobRequest(jobData)); 30 | ExpectMsg(); 31 | } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /OddJob.Execution.Akka/DependencyInjectedJobExecutorShell.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Akka.Actor; 3 | using Akka.DI.Core; 4 | 5 | namespace GlutenFree.OddJob.Execution.Akka 6 | { 7 | 8 | public class DependencyInjectedJobExecutorShell : BaseJobExecutorShell 9 | { 10 | IDependencyResolver _dependencyResolver; 11 | public DependencyInjectedJobExecutorShell(Func dependencyResolverCreator, IExecutionEngineLoggerConfig loggerConfig) :base(loggerConfig) 12 | { 13 | _dependencyResolver = dependencyResolverCreator(_actorSystem); 14 | } 15 | 16 | 17 | protected override Props WorkerProps 18 | { 19 | get { return _dependencyResolver.Create(WorkerType); } 20 | } 21 | 22 | /// 23 | /// Override this to have a custom worker type. 24 | /// 25 | protected virtual Type WorkerType 26 | { 27 | get { return (typeof(JobWorkerActor)); } 28 | } 29 | 30 | /// 31 | /// Override this to provide a custom Queue Layer type. 32 | /// 33 | protected virtual Type QueueLayerType 34 | { 35 | get { return (typeof(JobQueueLayerActor)); } 36 | } 37 | 38 | protected override Props JobQueueProps 39 | { 40 | get { return _dependencyResolver.Create(QueueLayerType); } 41 | } 42 | 43 | protected override Props CoordinatorProps 44 | { 45 | get { return _dependencyResolver.Create(CoordinatorType); } 46 | } 47 | 48 | protected virtual Type CoordinatorType 49 | { 50 | get { return (typeof(JobQueueCoordinator)); } 51 | } 52 | 53 | 54 | } 55 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/JobSearch.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
    6 |

    My TODO list

    7 | 8 |
    9 |
      10 |
    • 11 |
      12 | 17 |
      18 |
    • 19 |
    20 |
    21 |
    22 | 23 |
    24 | 25 | 26 | 27 | 28 | 29 |
    30 |

    You are going to add: ${NewTaskName}

    31 |
    32 | 33 |
    34 |
    35 |
    36 | 37 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Configuration/GenerateMappings.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using GlutenFree.OddJob.Storage.Sql.Common; 3 | 4 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 5 | { 6 | /// 7 | /// This is a helper class to provide mappings for Queuenames to specific tables. 8 | /// If you want to use a single Queue table, you do not need to do this. 9 | /// But for scenarios where you wish to have multiple queue tables, 10 | /// This is an opportunity to provide a level of indirection for serialized jobs. 11 | /// 12 | public static class GenerateMappings 13 | { 14 | public static Dictionary TableConfigurations 15 | { 16 | get 17 | { 18 | return new Dictionary() 19 | { 20 | { 21 | "console", 22 | new MyTableConfigs() 23 | { 24 | QueueTableName = "consoleQueue", ParamTableName = "consoleParam", 25 | JobMethodGenericParamTableName = "consoleGeneric", JobClaimLockTimeoutInSeconds = 30 26 | } 27 | }, 28 | { "counter", 29 | new MyTableConfigs() 30 | { 31 | QueueTableName = "counterQueue", ParamTableName = "counterParam", 32 | JobMethodGenericParamTableName = "counterGeneric", JobClaimLockTimeoutInSeconds = 30 33 | } 34 | } 35 | }; 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/IJobSearchProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | using GlutenFree.OddJob.Interfaces; 5 | using GlutenFree.OddJob.Serializable; 6 | using GlutenFree.OddJob.Storage.Sql.Common.DbDtos; 7 | 8 | namespace GlutenFree.OddJob.Storage.Sql.Common 9 | { 10 | public interface IJobSearchProvider 11 | { 12 | bool UpdateJobMetadataValues( 13 | IDictionary>, object> setters, Guid jobGuid, 14 | string oldStatusIfRequired); 15 | 16 | bool UpdateJobMetadataAndParameters(JobUpdateCommand updateCommand); 17 | 18 | bool UpdateJobMetadataFull(SqlCommonDbOddJobMetaData metaDataToUpdate, string oldStatusIfRequired); 19 | bool UpdateJobParameterValues(IEnumerable metaDatas); 20 | IEnumerable GetJobParamCriteriaValues(Expression> selector); 21 | IEnumerable GetJobCriteriaValues(Expression> selector); 22 | 23 | IEnumerable GetJobCriteriaByCriteria(Expression> criteria, 24 | Expression> selector); 25 | IEnumerable GetJobsByParameterAndMainCriteria( 26 | Expression> jobQueryable, 27 | Expression> paramQueryable); 28 | IEnumerable GetSerializableJobsByCriteria( 29 | Expression> criteria); 30 | IEnumerable GetJobsByCriteria( 31 | Expression> criteria); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /OddJob.Storage.SqlServer/SqlServerDbJobTableHelper.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Storage.Sql.Common; 2 | 3 | namespace GlutenFree.OddJob.Storage.Sql.SqlServer 4 | { 5 | public static class SqlServerDbJobTableHelper 6 | { 7 | public static string JobTableCreateScript(ISqlDbJobQueueTableConfiguration configuration) 8 | { 9 | return string.Format(@" 10 | 11 | create Table {0} 12 | ( 13 | Id BIGINT NOT NULL IDENTITY(1,1) PRIMARY KEY, 14 | QueueName NVarchar(255) not null, 15 | TypeExecutedOn NVarChar(512) not null, 16 | MethodName NVarChar(255) not null, 17 | DoNotExecuteBefore datetime null, 18 | JobGuid uniqueidentifier not null, 19 | Status NVarChar(32) not null, 20 | MaxRetries int, 21 | MinRetryWait int, 22 | RetryCount int, 23 | LockClaimTime datetime null, 24 | LockGuid uniqueidentifier null, 25 | LastAttempt datetime null, 26 | CreatedDate datetime not null) 27 | ", configuration.QueueTableName); 28 | } 29 | 30 | public static string JobQueueParamTableCreateScript(ISqlDbJobQueueTableConfiguration config) 31 | { 32 | return string.Format(@" 33 | Create table {0} 34 | ( 35 | Id bigint not null identity(1,1) primary key, 36 | JobGuid uniqueidentifier not null, 37 | ParamOrdinal int not null, 38 | SerializedValue nvarchar(max) null, 39 | SerializedType nvarchar(255) null, 40 | ParameterName nvarchar(255) null 41 | )", config.ParamTableName); 42 | } 43 | 44 | public static string JobQueueJobMethodGenericParamTableCreateScript(ISqlDbJobQueueTableConfiguration config) 45 | { 46 | return string.Format(@" 47 | create table {0} 48 | ( 49 | Id bigint not null identity(1,1) primary key, 50 | JobGuid UniqueIdentifier not null, 51 | ParamOrder int not null, 52 | ParamTypeName nvarchar(255) not null, 53 | )", config.JobMethodGenericParamTableName); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /OddJob/DefaultJobExecutor.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | using System.Reflection; 3 | using GlutenFree.OddJob.Interfaces; 4 | 5 | namespace GlutenFree.OddJob 6 | { 7 | public class DefaultJobExecutor : IJobExecutor 8 | { 9 | public DefaultJobExecutor(IContainerFactory containerFactory) 10 | { 11 | _containerFactory = containerFactory; 12 | } 13 | 14 | private IContainerFactory _containerFactory; 15 | 16 | public void ExecuteJob(IOddJob expr) 17 | { 18 | //IsAbstract and IsSealed means we are dealing with a static class invocation and want NULL. 19 | var instance = (expr.TypeExecutedOn.IsAbstract && expr.TypeExecutedOn.IsSealed) 20 | ? null 21 | : _containerFactory.CreateInstance(expr.TypeExecutedOn) 22 | ; 23 | MethodInfo method = null; 24 | if (expr.MethodGenericTypes != null && expr.MethodGenericTypes.Length > 0) 25 | { 26 | method = expr.TypeExecutedOn.GetMethods().Where(q => 27 | q.Name==expr.MethodName && 28 | q.IsGenericMethod && q.GetGenericArguments().Length == expr.MethodGenericTypes.Length && 29 | q.GetParameters().Length == expr.JobArgs.Length) 30 | .FirstOrDefault().MakeGenericMethod(expr.MethodGenericTypes); 31 | } 32 | else 33 | { 34 | method = expr.TypeExecutedOn.GetMethod(expr.MethodName, expr.JobArgs.Select(q => q.Value.GetType()).ToArray()); 35 | } 36 | //var method = expr.TypeExecutedOn.GetMethod(expr.MethodName, expr.JobArgs.Select(q=>q.Value.GetType()).ToArray()); 37 | method.Invoke(instance, expr.JobArgs.Select(q=>q.Value).ToArray()); 38 | _containerFactory.Relase(instance); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /OddJob.Storage.SqlServer.Test/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Reflection; 4 | using GlutenFree.OddJob.Interfaces; 5 | using GlutenFree.OddJob.Serializable; 6 | using GlutenFree.OddJob.Storage.BaseTests; 7 | using GlutenFree.OddJob.Storage.Sql.Common; 8 | using LinqToDB.DataProvider.SqlServer; 9 | using OddJob.Storage.Sql.SqlServer.Test; 10 | 11 | namespace GlutenFree.OddJob.Storage.Sql.SqlServer.Test 12 | { 13 | public class SqlServerStorageTest : StorageTests 14 | { 15 | public SqlServerStorageTest() 16 | { 17 | var execPath = Path.Combine(Assembly.GetExecutingAssembly().CodeBase, string.Empty) 18 | .Substring(0, Assembly.GetExecutingAssembly().CodeBase.LastIndexOf('/')); 19 | AppDomain.CurrentDomain.SetData("DataDirectory", new Uri(Path.Combine(execPath, string.Empty)).LocalPath); 20 | UnitTestTableHelper.EnsureTablesExist(); 21 | 22 | 23 | } 24 | 25 | protected override Func JobAddStoreFunc 26 | { 27 | get 28 | { 29 | return () => new SqlServerJobQueueAdder( 30 | new SqlServerDataConnectionFactory(new TestDbConnectionFactory(), SqlServerVersion.v2008) 31 | , 32 | new DefaultJobAdderQueueTableResolver(new SqlDbJobQueueDefaultTableConfiguration())); 33 | } 34 | } 35 | 36 | protected override Func JobMgrStoreFunc 37 | { 38 | get 39 | { 40 | return () => new SqlServerJobQueueManager( 41 | new SqlServerDataConnectionFactory(new TestDbConnectionFactory(), SqlServerVersion.v2008), 42 | new SqlDbJobQueueDefaultTableConfiguration(), new NullOnMissingTypeJobTypeResolver()); 43 | } 44 | } 45 | 46 | } 47 | } 48 | 49 | 50 | -------------------------------------------------------------------------------- /OddJob.SampleApp.Console/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using GlutenFree.OddJob; 4 | using GlutenFree.OddJob.Execution.Akka; 5 | using GlutenFree.OddJob.Execution.BaseTests; 6 | 7 | namespace OddJob.SampleApp.Console 8 | { 9 | class Program 10 | { 11 | static void Main(string[] args) 12 | { 13 | var store = new InMemoryTestStore(); 14 | var jobQueue = new HardInjectedJobExecutorShell(() => new JobQueueLayerActor(store), 15 | () => new JobWorkerActor(new DefaultJobExecutor(new DefaultContainerFactory())), 16 | () => new JobQueueCoordinator(), 17 | loggerConfig: new StandardConsoleEngineLoggerConfig("DEBUG")); 18 | jobQueue.StartJobQueue("sample",5,5); 19 | 20 | 21 | var timer = StartSampleJobTimer(store); 22 | 23 | System.Console.WriteLine("Press ENTER to quit..."); 24 | System.Console.ReadLine(); 25 | } 26 | 27 | private static Timer StartSampleJobTimer(InMemoryTestStore store) 28 | { 29 | return new Timer( 30 | 31 | (state) => 32 | { 33 | var counter = CounterClass.Counter; 34 | CounterClass.Counter = counter + 1; 35 | var counterString = counter.ToString(); 36 | store.AddJob((SampleJob job) => job.WriteSomething(counterString, DateTime.Now.ToString()), queueName: "sample"); 37 | }, null, 38 | TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(2)); 39 | } 40 | } 41 | public static class CounterClass 42 | { 43 | public static int Counter { get; set; } 44 | } 45 | 46 | public class SampleJob 47 | { 48 | public void WriteSomething(string thing, string time) 49 | { 50 | System.Console.WriteLine("Hello! I got {0} at {1}, and am executing at {2}", thing,time,DateTime.Now.ToString()); 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /OddJob.Storage.SQL.Common/BaseSqlJobQueuePurger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using GlutenFree.OddJob.Interfaces; 4 | using GlutenFree.OddJob.Storage.Sql.Common.DbDtos; 5 | using LinqToDB; 6 | using LinqToDB.Mapping; 7 | using LinqToDB.Tools; 8 | 9 | namespace GlutenFree.OddJob.Storage.Sql.Common 10 | { 11 | public class BaseSqlJobQueuePurger : IJobQueuePurger 12 | { 13 | private readonly FluentMappingBuilder _mappingSchema; 14 | private readonly IJobQueueDataConnectionFactory _jobQueueConnectionFactory; 15 | 16 | public BaseSqlJobQueuePurger(IJobQueueDataConnectionFactory jobQueueConnectionFactory, 17 | ISqlDbJobQueueTableConfiguration tableConfig) 18 | { 19 | _jobQueueConnectionFactory = jobQueueConnectionFactory; 20 | 21 | _mappingSchema = Mapping.BuildMappingSchema(tableConfig); 22 | } 23 | 24 | public void PurgeQueue(string name, string stateToPurge, DateTime purgeOlderThan) 25 | { 26 | using (var conn = _jobQueueConnectionFactory.CreateDataConnection(_mappingSchema.MappingSchema)) 27 | { 28 | conn.GetTable() 29 | .Where(q => q.JobGuid.In(conn.GetTable() 30 | .Where(r => r.Status == stateToPurge && r.CreatedDate < purgeOlderThan && r.QueueName == name).Select(r=>r.JobGuid))) 31 | .Delete(); 32 | conn.GetTable() 33 | .Where(q => q.JobGuid.In(conn.GetTable() 34 | .Where(r => r.Status == stateToPurge && r.CreatedDate < purgeOlderThan && r.QueueName == name).Select(r => r.JobGuid))) 35 | .Delete(); 36 | conn.GetTable() 37 | .Where(r => r.Status == stateToPurge && r.CreatedDate < purgeOlderThan && r.QueueName == name) 38 | .Delete(); 39 | 40 | } 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Actors/ResultJobWriter.cs: -------------------------------------------------------------------------------- 1 | using System.Transactions; 2 | using Akka.Actor; 3 | using GlutenFree.OddJob.Serializable; 4 | 5 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 6 | { 7 | /// 8 | /// This is a writer that will write the jobs to the database in a single transaction, 9 | /// then acknowledging. This can be extended with guaranteed delivery semantics. 10 | /// 11 | public class ResultJobWriter : ActorBase 12 | { 13 | private readonly ISerializedJobQueueAdder _jobQueueAdder; 14 | public ResultJobWriter(ISerializedJobQueueAdder jobQueueAdder) 15 | { 16 | _jobQueueAdder = jobQueueAdder; 17 | } 18 | protected override bool Receive(object message) 19 | { 20 | if (message is AggregatedCommand) 21 | { 22 | var msg = message as AggregatedCommand; 23 | /* 24 | * This pattern is Safe. 25 | * If you follow the rules in this example, 26 | * Treating your messages as immutable and assembling an aggregated command, 27 | * Either every Job is queued, or none are. 28 | * Your workers can have their own rules about idempotent processing. 29 | * 30 | * If you were to use Guaranteed Delivery in something like Akka, 31 | * You would want CommandsWritten to send back a sequence number (Sent by AggregatedCommand) 32 | * You could also have this pattern writer as part of a WebAPI or MQ solution. 33 | */ 34 | using (var scope = new TransactionScope(TransactionScopeOption.Required)) 35 | { 36 | _jobQueueAdder.AddJobs(msg.ResultingCommands); 37 | scope.Complete(); 38 | Context.Sender.Tell(new CommandsWritten()); 39 | } 40 | } 41 | else 42 | { 43 | return false; 44 | } 45 | 46 | return true; 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /OddJob.Storage.SQLite/SQLiteDbJobTableHelper.cs: -------------------------------------------------------------------------------- 1 | using GlutenFree.OddJob.Storage.Sql.Common; 2 | 3 | namespace GlutenFree.OddJob.Storage.Sql.SQLite 4 | { 5 | public static class SQLiteDbJobTableHelper 6 | { 7 | public static string JobTableCreateScript(ISqlDbJobQueueTableConfiguration configuration) 8 | { 9 | return string.Format(@" 10 | 11 | create Table {0} 12 | ( 13 | Id INTEGER PRIMARY KEY, 14 | QueueName NVarchar(255) not null, 15 | TypeExecutedOn NVarChar(255) not null, 16 | MethodName NVarChar(255) not null, 17 | DoNotExecuteBefore datetime null, 18 | JobGuid uniqueidentifier not null, 19 | Status NVarChar(32) not null, 20 | MaxRetries int, 21 | MinRetryWait int, 22 | RetryCount int, 23 | LockClaimTime datetime null, 24 | LockGuid uniqueidentifier null, 25 | LastAttempt datetime null, 26 | CreatedDate datetime not null) 27 | ", configuration.QueueTableName); 28 | } 29 | 30 | public static string JobQueueParamTableCreateScript(ISqlDbJobQueueTableConfiguration config) 31 | { 32 | return string.Format(@" 33 | Create table {0} 34 | ( 35 | Id INTEGER PRIMARY KEY, 36 | JobGuid uniqueidentifier not null, 37 | ParamOrdinal int not null, 38 | SerializedValue text null, 39 | SerializedType nvarchar(255) null, 40 | ParameterName nvarchar(255) null 41 | )", config.ParamTableName); 42 | } 43 | 44 | public static string JobQueueJobMethodGenericParamTableCreateScript(ISqlDbJobQueueTableConfiguration config) 45 | { 46 | return string.Format(@" 47 | create table {0} 48 | ( 49 | Id INTEGER primary key, 50 | JobGuid UniqueIdentifier not null, 51 | ParamOrder int not null, 52 | ParamTypeName text not null 53 | )", config.JobMethodGenericParamTableName); 54 | } 55 | 56 | public static string SuggestedIndexes(ISqlDbJobQueueTableConfiguration config) 57 | { 58 | return string.Format(@" 59 | create index {2}_jobguid_idx on {2}(JobGuid); 60 | create index {1}_jobguid_idx on {1}(JobGuid); 61 | create unique index {0}_jobguid_idx on {0}(JobGuid); 62 | ", config.QueueTableName, config.ParamTableName, config.JobMethodGenericParamTableName); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS-AspnetCore/OddJobRemotingWrapper.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using WebSharper; 3 | 4 | namespace GlutenFree.OddJob.Manager.Presentation.WS_AspnetCore 5 | { 6 | //Unfortunately, We need this for now. 7 | //Websharper doesn't appear to let you use interface methods marked with [Remote], 8 | //Only Abstract or Concrete classes. 9 | //But at the same time, we need to Decorate anything going through Websharper in the name of potential thread-safety. 10 | public class OddJobRemotingWrapper : IRemotingHandler, IRemotingHandler, 11 | IRemotingHandler, IRemotingHandler 12 | { 13 | private IRemotingHandler _methodHandlerImpl; 14 | private IRemotingHandler _searchHandlerImpl; 15 | private IRemotingHandler _updateHandlerImpl; 16 | private IRemotingHandler _queueNameHandlerImpl; 17 | 18 | public OddJobRemotingWrapper(IRemotingHandler methodHandlerImpl, IRemotingHandler searchHandlerImpl, IRemotingHandler updateHandlerImpl, IRemotingHandler queueNameHandlerImpl) 19 | { 20 | _methodHandlerImpl = methodHandlerImpl; 21 | _searchHandlerImpl = searchHandlerImpl; 22 | _updateHandlerImpl = updateHandlerImpl; 23 | _queueNameHandlerImpl = queueNameHandlerImpl; 24 | } 25 | [Remote] 26 | public Task Handle(GetMethodsForQueueNameRequest command) 27 | { 28 | return _methodHandlerImpl.Handle(command); 29 | } 30 | [Remote] 31 | public Task Handle(JobSearchCriteria command) 32 | { 33 | return _searchHandlerImpl.Handle(command); 34 | } 35 | [Remote] 36 | public Task Handle(JobUpdateViewModel command) 37 | { 38 | return _updateHandlerImpl.Handle(command); 39 | } 40 | [Remote] 41 | public Task Handle(QueueNameListRequest command) 42 | { 43 | return _queueNameHandlerImpl.Handle(command); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.WebSharper/Server.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using GlutenFree.OddJob.Manager.Presentation.WS.Template; 3 | using WebSharper; 4 | using WebSharper.Sitelets; 5 | using WebSharper.UI; 6 | 7 | namespace GlutenFree.OddJob.Manager.Presentation.WS 8 | { 9 | public class Server 10 | { 11 | [EndPoint("/")] 12 | public class Home 13 | { 14 | public override bool Equals(object obj) => obj is Home; 15 | public override int GetHashCode() => 0; 16 | } 17 | 18 | [EndPoint("GET /about")] 19 | public class About 20 | { 21 | public override bool Equals(object obj) => obj is About; 22 | public override int GetHashCode() => 1; 23 | } 24 | 25 | public static Doc MenuBar(Context ctx, object endpoint) 26 | { 27 | Doc link(string txt, object act) => 28 | Html.li( 29 | endpoint.Equals(act) ? Html.attr.@class("active") : null, 30 | Html.a(Html.attr.href(ctx.Link(act)), txt) 31 | ); 32 | return Html.doc( 33 | Html.li(link("Home", new Home())), 34 | Html.li(link("About", new About())) 35 | ); 36 | } 37 | 38 | public static Task Page(Context ctx, object endpoint, string title, Doc body) => 39 | Content.Page( 40 | new Main() 41 | .Title(title) 42 | .MenuBar(MenuBar(ctx, endpoint)) 43 | .Body(body) 44 | .Doc() 45 | ); 46 | 47 | [Website] 48 | public static Sitelet Main => 49 | new SiteletBuilder() 50 | .With((ctx, action) => 51 | Page(ctx, action, "Home", 52 | Html.doc( 53 | Html.h1("Say Hi to the server!"), 54 | Html.div(Html.client(() => Client.Main())) 55 | ) 56 | ) 57 | ) 58 | .With((ctx, action) => 59 | Page(ctx, action, "About", 60 | Html.doc( 61 | Html.h1("About"), 62 | Html.p("This is a template WebSharper client-server application.") 63 | ) 64 | ) 65 | ) 66 | .Install(); 67 | } 68 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS-AspnetCore/Server.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using GlutenFree.OddJob.Manager.Presentation.WS_AspnetCore.Template; 3 | using WebSharper; 4 | using WebSharper.Sitelets; 5 | using WebSharper.UI; 6 | using static WebSharper.UI.Html; 7 | 8 | namespace GlutenFree.OddJob.Manager.Presentation.WS_AspnetCore 9 | { 10 | public class Server 11 | { 12 | 13 | [EndPoint("/")] 14 | public class Home 15 | { 16 | public override bool Equals(object obj) => obj is Home; 17 | public override int GetHashCode() => 0; 18 | } 19 | 20 | [EndPoint("GET /about")] 21 | public class About 22 | { 23 | public override bool Equals(object obj) => obj is About; 24 | public override int GetHashCode() => 1; 25 | } 26 | 27 | public static Doc MenuBar(Context ctx, object endpoint) 28 | { 29 | Doc link(string txt, object act) => 30 | li( 31 | endpoint.Equals(act) ? attr.@class("active") : null, 32 | a(attr.href(ctx.Link(act)), txt) 33 | ); 34 | return doc( 35 | li(link("Home", new Home())), 36 | li(link("About", new About())) 37 | ); 38 | } 39 | 40 | public static Task Page(Context ctx, object endpoint, string title, Doc body) => 41 | Content.Page( 42 | new Main() 43 | .Title(title) 44 | .MenuBar(MenuBar(ctx, endpoint)) 45 | .Body(body) 46 | .Doc() 47 | ); 48 | 49 | [Website] 50 | public Sitelet Main => 51 | new SiteletBuilder() 52 | .With((ctx, action) => 53 | Page(ctx, action, "Home", 54 | doc( 55 | h1("Say Hi to the server!"), 56 | div(client(() => JobSearchClient.Main())) 57 | ) 58 | ) 59 | ) 60 | .With((ctx, action) => 61 | Page(ctx, action, "About", 62 | doc( 63 | h1("About"), 64 | p("This is a template WebSharper client-server application.") 65 | ) 66 | ) 67 | ) 68 | .Install(); 69 | } 70 | } -------------------------------------------------------------------------------- /OddJob.Storage.SqlServer.Test/UnitTestTableHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | using GlutenFree.OddJob.Storage.Sql.SqlServer; 3 | using GlutenFree.OddJob.Storage.Sql.Common; 4 | 5 | namespace OddJob.Storage.Sql.SqlServer.Test 6 | { 7 | public static class UnitTestTableHelper 8 | { 9 | [MethodImpl(MethodImplOptions.Synchronized)] 10 | public static void EnsureTablesExist() 11 | { 12 | using (var db = SqlConnectionHelper.GetLocalDB("unittestdb")) 13 | { 14 | 15 | using (var cmd = db.CreateCommand()) 16 | { 17 | cmd.CommandText = string.Format(@"IF OBJECT_ID('dbo.{0}', 'U') IS NOT NULL 18 | DROP TABLE dbo.{0}; ", SqlDbJobQueueDefaultTableConfiguration.DefaultQueueTableName); 19 | cmd.ExecuteNonQuery(); 20 | } 21 | using (var cmd = db.CreateCommand()) 22 | { 23 | cmd.CommandText = string.Format(@"IF OBJECT_ID('dbo.{0}', 'U') IS NOT NULL 24 | DROP TABLE dbo.{0}; ", SqlDbJobQueueDefaultTableConfiguration.DefaultQueueParamTableName); 25 | cmd.ExecuteNonQuery(); 26 | } 27 | using (var cmd = db.CreateCommand()) 28 | { 29 | cmd.CommandText = string.Format(@"IF OBJECT_ID('dbo.{0}', 'U') IS NOT NULL 30 | DROP TABLE dbo.{0}; ", SqlDbJobQueueDefaultTableConfiguration.DefaultJobMethodGenericParamTableName); 31 | cmd.ExecuteNonQuery(); 32 | } 33 | using (var cmd = db.CreateCommand()) 34 | { 35 | cmd.CommandText = SqlServerDbJobTableHelper.JobQueueParamTableCreateScript( 36 | new SqlDbJobQueueDefaultTableConfiguration()); 37 | cmd.ExecuteNonQuery(); 38 | } 39 | using (var cmd = db.CreateCommand()) 40 | { 41 | cmd.CommandText = SqlServerDbJobTableHelper.JobTableCreateScript( 42 | new SqlDbJobQueueDefaultTableConfiguration()); 43 | cmd.ExecuteNonQuery(); 44 | } 45 | using (var cmd = db.CreateCommand()) 46 | { 47 | cmd.CommandText = SqlServerDbJobTableHelper.JobQueueJobMethodGenericParamTableCreateScript( 48 | new SqlDbJobQueueDefaultTableConfiguration()); 49 | cmd.ExecuteNonQuery(); 50 | } 51 | } 52 | 53 | 54 | 55 | 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /GlutenFree.OddJob.Execution.ThreadPool/GlutenFree.OddJob.Execution.ThreadPool.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {8F4D96A6-F2F7-4307-9729-088C3869787A} 8 | Library 9 | Properties 10 | GlutenFree.OddJob.Execution.ThreadPool 11 | GlutenFree.OddJob.Execution.ThreadPool 12 | v4.5.2 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | {AA34BEA9-12EC-4BF0-A6E0-9C459A4EBAE9} 49 | GlutenFree.OddJob 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.WebSharper/Main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ${Title} 7 | 8 | 33 | 34 | 35 | 36 | 54 |
    55 |
    56 |
    57 |
    58 |
    59 |
    60 |

    61 | For an enhanced template that provides automatic GitHub deployment to Azure, fork from GitHub, or 62 | read more here. 63 |

    64 |
    65 |
    66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/Main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ${Title} 7 | 8 | 33 | 34 | 35 | 36 | 54 |
    55 |
    56 |
    57 |
    58 |
    59 |
    60 |

    61 | For an enhanced template that provides automatic GitHub deployment to Azure, fork from GitHub, or 62 | read more here. 63 |

    64 |
    65 |
    66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS-AspnetCore/Main.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | ${Title} 7 | 8 | 33 | 34 | 35 | 36 | 54 |
    55 |
    56 |
    57 |
    58 |
    59 |
    60 |

    61 | For an enhanced template that provides automatic GitHub deployment to Azure, fork from GitHub, or 62 | read more here. 63 |

    64 |
    65 |
    66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/Scripts/WebSharper/WebSharper.JavaScript/Cookies.js: -------------------------------------------------------------------------------- 1 | (function(g,f){'use strict';var h=function(e){if("object"!==typeof e.document)throw Error("Cookies.js requires a `window` with a `document` object");var b=function(a,d,c){return 1===arguments.length?b.get(a):b.set(a,d,c)};b._document=e.document;b._cacheKeyPrefix="cookey.";b._maxExpireDate=new Date("Fri, 31 Dec 9999 23:59:59 UTC");b.defaults={path:"/",secure:!1};b.get=function(a){b._cachedDocumentCookie!==b._document.cookie&&b._renewCache();a=b._cache[b._cacheKeyPrefix+a];return a===f?f:decodeURIComponent(a)}; 2 | b.set=function(a,d,c){c=b._getExtendedOptions(c);c.expires=b._getExpiresDate(d===f?-1:c.expires);b._document.cookie=b._generateCookieString(a,d,c);return b};b.expire=function(a,d){return b.set(a,f,d)};b._getExtendedOptions=function(a){return{path:a&&a.path||b.defaults.path,domain:a&&a.domain||b.defaults.domain,expires:a&&a.expires||b.defaults.expires,secure:a&&a.secure!==f?a.secure:b.defaults.secure}};b._isValidDate=function(a){return"[object Date]"===Object.prototype.toString.call(a)&&!isNaN(a.getTime())}; 3 | b._getExpiresDate=function(a,d){d=d||new Date;"number"===typeof a?a=Infinity===a?b._maxExpireDate:new Date(d.getTime()+1E3*a):"string"===typeof a&&(a=new Date(a));if(a&&!b._isValidDate(a))throw Error("`expires` parameter cannot be converted to a valid Date instance");return a};b._generateCookieString=function(a,b,c){a=a.replace(/[^#$&+\^`|]/g,encodeURIComponent);a=a.replace(/\(/g,"%28").replace(/\)/g,"%29");b=(b+"").replace(/[^!#$&-+\--:<-\[\]-~]/g,encodeURIComponent);c=c||{};a=a+"="+b+(c.path?";path="+ 4 | c.path:"");a+=c.domain?";domain="+c.domain:"";a+=c.expires?";expires="+c.expires.toUTCString():"";return a+=c.secure?";secure":""};b._getCacheFromString=function(a){var d={};a=a?a.split("; "):[];for(var c=0;cb?a.length:b,c=a.substr(0,b),e;try{e=decodeURIComponent(c)}catch(f){console&&"function"=== 5 | typeof console.error&&console.error('Could not decode cookie with key "'+c+'"',f)}return{key:e,value:a.substr(b+1)}};b._renewCache=function(){b._cache=b._getCacheFromString(b._document.cookie);b._cachedDocumentCookie=b._document.cookie};b._areEnabled=function(){var a="1"===b.set("cookies.js",1).get("cookies.js");b.expire("cookies.js");return a};b.enabled=b._areEnabled();return b},e="object"===typeof g.document?h(g):h;"function"===typeof define&&define.amd?define(function(){return e}):"object"===typeof exports? 6 | ("object"===typeof module&&"object"===typeof module.exports&&(exports=module.exports=e),exports.Cookies=e):g.Cookies=e})("undefined"===typeof window?this:window); -------------------------------------------------------------------------------- /GlutenFree.OddJob.Manager.Presentation.WS/Scripts/WebSharper/WebSharper.Main/Json.js: -------------------------------------------------------------------------------- 1 | var JSON;JSON||(JSON={}),function(){"use strict";function i(n){return n<10?"0"+n:n}function f(n){return o.lastIndex=0,o.test(n)?'"'+n.replace(o,function(n){var t=s[n];return typeof t=="string"?t:"\\u"+("0000"+n.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+n+'"'}function r(i,e){var s,l,h,a,v=n,c,o=e[i];o&&typeof o=="object"&&typeof o.toJSON=="function"&&(o=o.toJSON(i)),typeof t=="function"&&(o=t.call(e,i,o));switch(typeof o){case"string":return f(o);case"number":return isFinite(o)?String(o):"null";case"boolean":case"null":return String(o);case"object":if(!o)return"null";if(n+=u,c=[],Object.prototype.toString.apply(o)==="[object Array]"){for(a=o.length,s=0;s 18 | /// Overridable Method to allow Handling of a Queue Failure. 19 | /// 20 | /// The Command that Failed. 21 | /// The Exception relating to Queue Failure. 22 | protected virtual void OnQueueFailure(object failedCommand, Exception ex) 23 | { 24 | Context.GetLogger().Error(ex,"Error On command {0}", failedCommand.GetType().ToString()); 25 | } 26 | protected override bool Receive(object message) 27 | { 28 | try 29 | { 30 | 31 | 32 | if (message is ShutDownQueues) 33 | { 34 | Context.Sender.Tell(new QueueShutDown()); 35 | } 36 | else if (message is GetJobs) 37 | { 38 | var msg = (GetJobs) message; 39 | Context.Sender.Tell(jobQueue.GetJobs(new[] {msg.QueueName}, msg.FetchSize, (q)=>q.MostRecentDate)); 40 | } 41 | else if (message is MarkJobInProgress) 42 | { 43 | jobQueue.MarkJobInProgress(((MarkJobInProgress) message).JobId); 44 | } 45 | else if (message is MarkJobFailed) 46 | { 47 | jobQueue.MarkJobFailed(((MarkJobFailed) message).JobId); 48 | } 49 | else if (message is MarkJobSuccess) 50 | { 51 | jobQueue.MarkJobSuccess(((MarkJobSuccess) message).JobId); 52 | } 53 | else if (message is MarkJobInRetryAndIncrement) 54 | { 55 | var msg = ((MarkJobInRetryAndIncrement) message); 56 | jobQueue.MarkJobInRetryAndIncrement(msg.JobId, msg.LastAttempt); 57 | } 58 | else 59 | { 60 | return false; 61 | } 62 | } 63 | catch (Exception ex) 64 | { 65 | try 66 | { 67 | OnQueueFailure(message, ex); 68 | } 69 | finally 70 | { 71 | 72 | } 73 | } 74 | 75 | return true; 76 | 77 | } 78 | 79 | } 80 | } 81 | 82 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/readme.md: -------------------------------------------------------------------------------- 1 | #The Job Command Aggregation Pattern 2 | 3 | This project is a sample of a Command Aggregation Pattern. 4 | 5 | The Problem: A common challenge in distributed applications (and microservices) is the idea of a transaction. 6 | 7 | As a contrived example, consider when one completes checkout at an online retailer. One may expect something like the following to happen: 8 | 9 | - The customer's order history is updated 10 | - A notification is sent to the warehouse 11 | - An email is sent to the customer 12 | 13 | Oftentimes (in my experience, in any case) this is handled by a single, tightly coupled method at the end of an operation, that has to either: 14 | 15 | - Have awareness of each service (To call them) or, 16 | - Use a message bus, sometimes working with a very raw json/xml format. 17 | 18 | Oddjob, used in this example pattern, provides an in-between. 19 | 20 | - Commands are created as standard .NET objects, with any 'boundary unsafe' information contained in JSON format. 21 | - This means that they can pass service boundaries, with intermediates being completely unaware of the interfaces/types involved in executing a job. 22 | - Commands can be collected (aggregated) as a coordinator/aggregator queries multiple services involved in a request. 23 | - Each service may decide what side effects are relevant to a given command. 24 | - As noted above, the caller need not know anything about what command is added, although it has the capability to inspect the created .NET objects if desired. 25 | - Once all of the resulting commands are collected, they can be atomically written to the database. 26 | 27 | 28 | Example Notes: 29 | 30 | - This example uses multiple Job Table sets; 31 | - You can use a single table set if you'd like. 32 | - That said, Some DBs may perform better if you use separate tables for queues. 33 | - Folders: 34 | - The Actors folder is where most of the pattern magic happens. 35 | - Note that the Decorators are only aware of the interface they are requesting; implementation is hidden. 36 | - The Configuration folder has mappings and a Table configuration type. 37 | - You can do all sorts of interesting things here, if you're daring. 38 | - Helpers is a set of helper classes for Table creation and SQLite in-memory management. 39 | - ArrayHelper is also there, but you'll probably find a better pattern for what is done there. 40 | - JobDI has a SimpleInjector Implementation for `IContainerFactory` 41 | - Messages is a series of domain commands. 42 | - Service1 and Service2 are the service workers. 43 | - The Contract folders contain the interfaces. 44 | - SimpleInjector is used for the Job DI, because it's great. 45 | - Service1 and Service2 would normally each be a separate process. 46 | - While the Decorator Services are part of the same ecosystem as the Aggregator and Result writer, there is nothing stopping these from being parts of different subsystems, in different .NET processes. 47 | -------------------------------------------------------------------------------- /GlutenFree.OddJob.Samples.Serialized.CommandAggregator/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Data.SQLite; 3 | using System.Linq; 4 | using Akka.Actor; 5 | using GlutenFree.OddJob.Execution.Akka; 6 | using GlutenFree.OddJob.Storage.Sql.Common; 7 | 8 | namespace GlutenFree.OddJob.Samples.Serialized.CommandAggregator 9 | { 10 | /* 11 | * I'm using Akka.NET for this example as it was the easiest to express intent here. 12 | * This pattern is usable with HTTP or MQ Semantics as well. 13 | */ 14 | 15 | class Program 16 | { 17 | 18 | private static SQLiteConnection _heldConnection; 19 | 20 | private static BaseJobExecutorShell counterEngine; 21 | private static BaseJobExecutorShell consoleEngine; 22 | 23 | 24 | 25 | 26 | static void Main(string[] args) 27 | { 28 | 29 | SampleTableHelper.EnsureTablesExist(GenerateMappings.TableConfigurations.Select(q => q.Value) 30 | .Append(new SqlDbJobQueueDefaultTableConfiguration())); 31 | WriteInstructions(); 32 | /* 33 | * Execution Engine: 34 | * Normally each of these would be it's own process, separate from your WebAPI or Akka or MQ Layer. 35 | * For ease of demonstration, this is rolled up into this single program. 36 | */ 37 | consoleEngine = Service1.CreateAndStartEngine1(); 38 | 39 | counterEngine = Service2.CreateAndStartEngine2(); 40 | 41 | /* 42 | * Service Layer: 43 | * Normally this would be it's own process, WebAPI, Akka, MQ, or similar layer. 44 | * For ease of demonstration, this is rolled up into a single program. 45 | */ 46 | var actorsystem = ActorSystem.Create("sampleAgg"); 47 | var aggRef = actorsystem.ActorOf(Props.Create(() => new Aggregator()),"aggregator"); 48 | 49 | /* 50 | * This is to simulate activity. Consider it a message/request to your service layer. 51 | */ 52 | actorsystem.Scheduler.ScheduleTellRepeatedly(TimeSpan.FromSeconds(0.1), TimeSpan.FromSeconds(0.1), aggRef, 53 | new MyCommand(), null); 54 | 55 | //Quit code. 56 | while (System.Console.ReadLine().ToLower() != "end") 57 | { 58 | WriteInstructions(); 59 | } 60 | //Cleanly shut down worker engines when done. 61 | counterEngine.ShutDownQueue("counter"); 62 | consoleEngine.ShutDownQueue("console"); 63 | //Cleanly terminate service layer. 64 | actorsystem.Terminate().RunSynchronously(); 65 | } 66 | 67 | public static void WriteInstructions() 68 | { 69 | System.Console.WriteLine("**********************************************"); 70 | System.Console.WriteLine("TYPE \"end\" (no quotes) and hit enter to exit"); 71 | System.Console.WriteLine("**********************************************"); 72 | } 73 | } 74 | } 75 | --------------------------------------------------------------------------------