Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
rasmus committed Sep 23, 2015
2 parents e9d9d80 + b37e327 commit e5aa034
Show file tree
Hide file tree
Showing 107 changed files with 3,259 additions and 500 deletions.
108 changes: 108 additions & 0 deletions Documentation/Jobs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# Jobs

A job is basically a task that you either don't want to execute in the current
context, on the current server or execute at a later time. EventFlow provides
basic functionality for jobs.

There are areas where you might find jobs very useful, here are some examples

* Publish a command at a specific time in the future
* Transient error handling

```csharp
var jobScheduler = resolver.Resolve<IJobScheduler>();
var job = PublishCommandJob.Create(new SendEmailCommand(id), resolver);
await jobScheduler.ScheduleAsync(
job,
TimeSpan.FromDays(7),
CancellationToken.None)
.ConfigureAwait(false);
```

In the above example the `SendEmailCommand` command will be published in seven
days.

## Be careful when using jobs

When working with jobs, you should be aware of the following

* The default implementation does executes the job _now_, i.e., in the
current context. To get another behavior, install e.g. `EventFlow.Hangfire`
to get support for scheduled jobs. Read below for details on how to
configure Hangfire
* Your jobs should serialize to JSON properly, see the section on
[value objects](./ValueObjects.md) for more information
* If you use the provided `PublishCommandJob`, make sure that your commands
serialize properly as well

## Create your own jobs

To create your own jobs, your job merely needs to implement the `IJob`
interface and be registered in EventFlow.

Here's an example of a job implementing `IJob`

```csharp
[JobVersion("LogMessage", 1)]
public class LogMessageJob : IJob
{
public LogMessageJob(string message)
{
Message = message;
}

public string Message { get; }

public Task ExecuteAsync(
IResolver resolver,
CancellationToken cancellationToken)
{
var log = resolver.Resolve<ILog>();
log.Debug(Message);
}
}
```

Note that the `JobVersion` attribute specifies the job name and version to
EventFlow and this is how EventFlow distinguishes between the different job
types. This makes it possible for you to reorder your code, even rename the
job type, as long as you keep the same attribute values its considered the
same job in EventFlow. If the attribute is omitted, the name will be the
type name and version will be `1`.

Here's how the job is registered in EventFlow.

```csharp
var resolver = EventFlowOptions.new
.AddJobs(typeof(LogMessageJob))
...
.CreateResolver();
```

Then to schedule the job

```csharp
var jobScheduler = resolver.Resolve<IJobScheduler>();
var job = new LogMessageJob("Great log message");
await jobScheduler.ScheduleAsync(
job,
TimeSpan.FromDays(7),
CancellationToken.None)
.ConfigureAwait(false);
```

## Hangfire

To use [Hangfire](http://hangfire.io/) as the job scheduler, install the NuGet
package `EventFlow.Hangfire` and configure EventFlow to use the scheduler
like this.

```csharp
var resolver = EventFlowOptions.new
.UseHandfireJobScheduler() // This line
...
.CreateResolver();
```

Note that the `UseHandfireJobScheduler()` does do any Hangfire configuration,
but merely registers the proper scheduler in EventFlow.
16 changes: 16 additions & 0 deletions EventFlow.sln
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventFlow.Autofac.Tests", "
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Autofac", "Autofac", "{980EEDAA-1FEF-4D7C-8811-5EF1D9729773}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Hangfire", "Hangfire", "{4741A405-DA64-40CC-A726-A2C48CA49DA3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventFlow.Hangfire", "Source\EventFlow.Hangfire\EventFlow.Hangfire.csproj", "{FB079985-722A-43C9-9F14-C7D2AFBE8826}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventFlow.Hangfire.Tests", "Source\EventFlow.Hangfire.Tests\EventFlow.Hangfire.Tests.csproj", "{35180FC7-9135-4E79-8643-0FB825B40871}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -109,6 +115,14 @@ Global
{EDCD8854-6224-4329-87C2-9ADD7D153070}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EDCD8854-6224-4329-87C2-9ADD7D153070}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EDCD8854-6224-4329-87C2-9ADD7D153070}.Release|Any CPU.Build.0 = Release|Any CPU
{FB079985-722A-43C9-9F14-C7D2AFBE8826}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FB079985-722A-43C9-9F14-C7D2AFBE8826}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FB079985-722A-43C9-9F14-C7D2AFBE8826}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FB079985-722A-43C9-9F14-C7D2AFBE8826}.Release|Any CPU.Build.0 = Release|Any CPU
{35180FC7-9135-4E79-8643-0FB825B40871}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{35180FC7-9135-4E79-8643-0FB825B40871}.Debug|Any CPU.Build.0 = Debug|Any CPU
{35180FC7-9135-4E79-8643-0FB825B40871}.Release|Any CPU.ActiveCfg = Release|Any CPU
{35180FC7-9135-4E79-8643-0FB825B40871}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -126,5 +140,7 @@ Global
{4B06F01F-ACE6-489D-A92A-012F533EFA3C} = {7951DC73-5DAF-4322-9AF0-099BF5C90837}
{BC96BEAE-E84E-4C51-B66D-DA1F43EAD54A} = {7951DC73-5DAF-4322-9AF0-099BF5C90837}
{EDCD8854-6224-4329-87C2-9ADD7D153070} = {980EEDAA-1FEF-4D7C-8811-5EF1D9729773}
{FB079985-722A-43C9-9F14-C7D2AFBE8826} = {4741A405-DA64-40CC-A726-A2C48CA49DA3}
{35180FC7-9135-4E79-8643-0FB825B40871} = {4741A405-DA64-40CC-A726-A2C48CA49DA3}
EndGlobalSection
EndGlobal
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ to the documentation.
* Microsoft SQL Server
* [**Queries:**](./Documentation/Queries.md) Value objects that represent
a query without specifying how its executed, that is let to a query handler
* [**Jobs:**](./Documentation/Jobs.md) Perform scheduled tasks at a later time,
e.g. publish a command. EventFlow provides support for these job schedulers
* [Hangfire](./Documentation/Jobs.md#hangfire) - [home page](http://hangfire.io/)
* [**Event upgrade:**](./Documentation/EventUpgrade.md) As events committed to
the event store is never changed, EventFlow uses the concept of event
upgraders to deprecate events and replace them with new during aggregate load.
Expand Down
27 changes: 26 additions & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,29 @@
### New in 0.13 (not released yet)
### New in 0.14 (not released yet)

* Breaking: All `EventFlowOptions` extensions are now `IEventFlowOptions`
instead and `EventFlowOptions` implements this interface. If you have made
your own extensions, you will need to use the newly created interface
instead. Changed in order to make testing of extensions and classes
dependent on the EventFlow options easier to test
* New: You can now bundle your configuration of EventFlow into modules that
implement `IModule` and register these by calling
`EventFlowOptions.RegisterModule(...)`
* New: EventFlow now supports scheduled job execution via e.g. Hangfire. You
can create your own scheduler or install the new `EventFlow.Hangfire` NuGet
package. Read the jobs documentation for more details
* New: Created the OWIN `CommandPublishMiddleware` middleware that can
handle publishing of commands by posting a JSON serialized command to
e.g. `/commands/ping/1` in which `ping` is the command name and `1` its
version. Remember to add authentication
* New: Created a new interface `ICommand<TAggregate,TIdentity,TSourceIdentity>`
to allow developers to control the type of `ICommand.SourceId`. Using the
`ICommand<TAggregate,TIdentity>` (or Command<TAggregate,TIdentity>)
will still yield the same result as before, i.e., `ICommand.SourceId` being
of type `ISourceId`
* New: The `AddDefaults(...)` now also adds the command type definition to the
new `ICommandDefinitonService`

### New in 0.13.962 (released 2015-09-13)

* Breaking: `EventFlowOptions.AddDefaults(...)` now also adds query handlers
* New: Added an optional `Predicate<Type>` to the following option extension
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,30 +31,30 @@ namespace EventFlow.Autofac.Extensions
{
public static class EventFlowOptionsAutofacExtensions
{
public static EventFlowOptions UseAutofacContainerBuilder(
this EventFlowOptions eventFlowOptions)
public static IEventFlowOptions UseAutofacContainerBuilder(
this IEventFlowOptions eventFlowOptions)
{
return eventFlowOptions
.UseAutofacContainerBuilder(new ContainerBuilder());
}

public static EventFlowOptions UseAutofacContainerBuilder(
this EventFlowOptions eventFlowOptions,
public static IEventFlowOptions UseAutofacContainerBuilder(
this IEventFlowOptions eventFlowOptions,
ContainerBuilder containerBuilder)
{
return eventFlowOptions
.UseServiceRegistration(new AutofacServiceRegistration(containerBuilder));
}

public static EventFlowOptions UseAutofacAggregateRootFactory(
this EventFlowOptions eventFlowOptions)
public static IEventFlowOptions UseAutofacAggregateRootFactory(
this IEventFlowOptions eventFlowOptions)
{
return eventFlowOptions
.RegisterServices(f => f.Register<IAggregateFactory, AutofacAggregateRootFactory>(Lifetime.Singleton));
}

public static IContainer CreateContainer(
this EventFlowOptions eventFlowOptions,
this IEventFlowOptions eventFlowOptions,
bool validateRegistrations = true)
{
var rootResolver = eventFlowOptions.CreateResolver(validateRegistrations);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class EventStoreEventStoreTestConfiguration : IntegrationTestConfiguratio
private IQueryProcessor _queryProcessor;
private IReadModelPopulator _readModelPopulator;

public override IRootResolver CreateRootResolver(EventFlowOptions eventFlowOptions)
public override IRootResolver CreateRootResolver(IEventFlowOptions eventFlowOptions)
{
var connectionSettings = ConnectionSettings.Create()
.EnableVerboseLogging()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,22 +31,22 @@ namespace EventFlow.EventStores.EventStore.Extensions
{
public static class EventFlowOptionsExtensions
{
public static EventFlowOptions UseEventStoreEventStore(
this EventFlowOptions eventFlowOptions)
public static IEventFlowOptions UseEventStoreEventStore(
this IEventFlowOptions eventFlowOptions)
{
return eventFlowOptions.UseEventStore<EventStoreEventStore>();
}

public static EventFlowOptions UseEventStoreEventStore(
this EventFlowOptions eventFlowOptions,
public static IEventFlowOptions UseEventStoreEventStore(
this IEventFlowOptions eventFlowOptions,
IPEndPoint ipEndPoint)
{
return eventFlowOptions
.UseEventStoreEventStore(ipEndPoint, ConnectionSettings.Default);
}

public static EventFlowOptions UseEventStoreEventStore(
this EventFlowOptions eventFlowOptions,
public static IEventFlowOptions UseEventStoreEventStore(
this IEventFlowOptions eventFlowOptions,
IPEndPoint ipEndPoint,
ConnectionSettings connectionSettings)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ namespace EventFlow.EventStores.MsSql.Extensions
{
public static class EventFlowOptionsExtensions
{
public static EventFlowOptions UseMssqlEventStore(this EventFlowOptions eventFlowOptions)
public static IEventFlowOptions UseMssqlEventStore(this IEventFlowOptions eventFlowOptions)
{
return eventFlowOptions.UseEventStore<MsSqlEventStore>();
}
Expand Down
106 changes: 106 additions & 0 deletions Source/EventFlow.Hangfire.Tests/EventFlow.Hangfire.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{35180FC7-9135-4E79-8643-0FB825B40871}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>EventFlow.Hangfire.Tests</RootNamespace>
<AssemblyName>EventFlow.Hangfire.Tests</AssemblyName>
<TargetFrameworkVersion>v4.5.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
</PropertyGroup>
<ItemGroup>
<Reference Include="FluentAssertions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\..\packages\FluentAssertions.4.0.0\lib\net45\FluentAssertions.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="FluentAssertions.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=33f2691a05b67b6a, processorArchitecture=MSIL">
<HintPath>..\..\packages\FluentAssertions.4.0.0\lib\net45\FluentAssertions.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Hangfire.Core, Version=1.4.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Hangfire.Core.1.4.6\lib\net45\Hangfire.Core.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Hangfire.SqlServer, Version=1.4.6.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Hangfire.SqlServer.1.4.6\lib\net45\Hangfire.SqlServer.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Helpz, Version=0.1.8.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\Helpz.0.1.8\lib\net451\Helpz.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="nunit.framework, Version=2.6.4.14350, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL">
<HintPath>..\..\packages\NUnit.2.6.4\lib\nunit.framework.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Integration\HangfireJobFlow.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EventFlow.Hangfire\EventFlow.Hangfire.csproj">
<Project>{fb079985-722a-43c9-9f14-c7d2afbe8826}</Project>
<Name>EventFlow.Hangfire</Name>
</ProjectReference>
<ProjectReference Include="..\EventFlow.TestHelpers\EventFlow.TestHelpers.csproj">
<Project>{571d291c-5e4c-43af-855f-7c4e2f318f4c}</Project>
<Name>EventFlow.TestHelpers</Name>
</ProjectReference>
<ProjectReference Include="..\EventFlow\EventFlow.csproj">
<Project>{11131251-778d-4d2e-bdd1-4844a789bca9}</Project>
<Name>EventFlow</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
Loading

0 comments on commit e5aa034

Please sign in to comment.