Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
eulerfx committed Feb 18, 2013
0 parents commit 9ed1fc9
Show file tree
Hide file tree
Showing 17 changed files with 13,417 additions and 0 deletions.
96 changes: 96 additions & 0 deletions .gitignore
@@ -0,0 +1,96 @@
#################
## Visual Studio
#################

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.

# User-specific files
*.suo
*.user
*.sln.docstates

# Build results
[Dd]ebug/
[Rr]elease/
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.vspscc
.builds
*.dotCover

## TODO: If you have NuGet Package Restore enabled, uncomment this
#packages/

# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf

# Visual Studio profiler
*.psess
*.vsp

# ReSharper is a .NET coding add-in
_ReSharper*

# Installshield output folder
[Ee]xpress

# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html

# Click-Once directory
publish

# Others
[Bb]in
[Oo]bj
sql
TestResults
*.Cache
ClientBin
stylecop.*
~$*
*.dbmdl
Generated_Code #added for RIA/Silverlight projects

# Backup & report files from converting an old project file to a newer
# Visual Studio version. Backup files are not needed, because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML



############
## Windows
############

# Windows image file caches
Thumbs.db

# Folder config file
Desktop.ini
20 changes: 20 additions & 0 deletions DDDInventoryItemFSharp.sln
@@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "DDDInventoryItemFSharp", "DDDInventoryItemFSharp\DDDInventoryItemFSharp.fsproj", "{4198FAD2-A8B5-491F-A2B3-6B719C27BF5D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4198FAD2-A8B5-491F-A2B3-6B719C27BF5D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4198FAD2-A8B5-491F-A2B3-6B719C27BF5D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4198FAD2-A8B5-491F-A2B3-6B719C27BF5D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4198FAD2-A8B5-491F-A2B3-6B719C27BF5D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
25 changes: 25 additions & 0 deletions DDDInventoryItemFSharp/Aggregate.fs
@@ -0,0 +1,25 @@
/// Aggregate framework.
[<RequireQualifiedAccess>]
module Aggregate

/// Represents an aggregate.
type Aggregate<'TState, 'TCommand, 'TEvent> = {

/// An initial state value.
zero : 'TState;

/// Applies an event to a state returning a new state.
apply : 'TState -> 'TEvent -> 'TState;

/// Executes a command on a state yielding an event.
exec : 'TState -> 'TCommand -> 'TEvent;
}

type Id = System.Guid

/// Creates a persistent command handler for an aggregate.
let makeHandler (aggregate:Aggregate<'TState, 'TCommand, 'TEvent>) (load:Id -> 'TEvent seq, commit:Id * int -> 'TEvent -> unit) =
fun (id,version) command ->
let state = load id |> Seq.fold aggregate.apply aggregate.zero
let event = aggregate.exec state command
event |> commit (id,version)
71 changes: 71 additions & 0 deletions DDDInventoryItemFSharp/DDDInventoryItemFSharp.fsproj
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.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>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>4198fad2-a8b5-491f-a2b3-6b719c27bf5d</ProjectGuid>
<OutputType>Library</OutputType>
<RootNamespace>DDDInventoryItemFSharp</RootNamespace>
<AssemblyName>DDDInventoryItemFSharp</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<Name>DDDInventoryItemFSharp</Name>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<Tailcalls>false</Tailcalls>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<DocumentationFile>bin\Debug\DDDInventoryItemFSharp.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<Tailcalls>true</Tailcalls>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<WarningLevel>3</WarningLevel>
<DocumentationFile>bin\Release\DDDInventoryItemFSharp.XML</DocumentationFile>
</PropertyGroup>
<PropertyGroup>
<MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets" Condition=" Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')" />
<ItemGroup>
<Compile Include="Aggregate.fs" />
<Compile Include="InventoryItem.fs" />
<Compile Include="EventStore.fs" />
<Compile Include="Serialization.fs" />
<Compile Include="IntegrationTests.fs" />
<Content Include="Projections.js" />
</ItemGroup>
<ItemGroup>
<Reference Include="EventStore.ClientAPI">
<HintPath>..\lib\EventStore.ClientAPI.dll</HintPath>
</Reference>
<Reference Include="mscorlib" />
<Reference Include="FSharp.Core, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<Private>True</Private>
</Reference>
<Reference Include="Newtonsoft.Json">
<HintPath>..\lib\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="protobuf-net">
<HintPath>..\lib\protobuf-net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Numerics" />
</ItemGroup>
<!-- 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>
33 changes: 33 additions & 0 deletions DDDInventoryItemFSharp/EventStore.fs
@@ -0,0 +1,33 @@
module EventStore

open System
open System.Net
open EventStore.ClientAPI

/// Creates and opens an EventStore connection.
let conn () =
let conn = EventStoreConnection.Create()
conn.Connect(IPEndPoint(IPAddress.Parse("127.0.0.1"), 1113))
conn

/// Creates an event store functions with an InventoryItem-specific serializer.
let make (conn:EventStoreConnection) (serialize:InventoryItem.Event -> string * byte array, deserialize: string * byte array -> InventoryItem.Event) =

let streamId id = "InventoryItem-" + id.ToString().ToLower()

let load id =
let streamId = streamId id
let eventsSlice = conn.ReadStreamEventsForward(streamId, 1, Int32.MaxValue, false)
eventsSlice.Events
|> Seq.map (fun e -> deserialize(e.Event.EventType, e.Event.Data))

let commit (id,expectedVersion) (e:InventoryItem.Event) =
let streamId = streamId id
let eventType,data = serialize(e)
let metaData = [||] : byte array
let eventData = new EventData(Guid.NewGuid(), eventType, true, data, metaData)
if expectedVersion = 0
then conn.CreateStream(streamId, Guid.NewGuid(), true, metaData)
conn.AppendToStream(streamId, expectedVersion, eventData)

load,commit
23 changes: 23 additions & 0 deletions DDDInventoryItemFSharp/IntegrationTests.fs
@@ -0,0 +1,23 @@
module IntegrationTests

let conn = EventStore.conn()

let handleCommand =
Aggregate.makeHandler
{ zero = InventoryItem.State.Zero; apply = InventoryItem.apply; exec = InventoryItem.exec }
(EventStore.make conn Serialization.serializer)

[<Xunit.Fact>]
let createInventoryItem() =
//let id = System.Guid.NewGuid()
let id = System.Guid.Parse("88085239-6f0f-48c6-b73d-017333cb99ba")
let version = 0
InventoryItem.Create(id,"Pool Pump") |> handleCommand (id,version)

[<Xunit.Fact>]
let renameInventoryItem() =
let id = System.Guid.Parse("88085239-6f0f-48c6-b73d-017333cb99ba")
let version = 1
InventoryItem.Rename("Cooler Pool Pump") |> handleCommand (id,version )


67 changes: 67 additions & 0 deletions DDDInventoryItemFSharp/InventoryItem.fs
@@ -0,0 +1,67 @@
/// An inventory item.
[<RequireQualifiedAccess>]
module InventoryItem

/// Represents the state of an inventory item.
type State = {
isActive : bool;
}
with static member Zero = { isActive = false }

/// An inventory item command.
type Command =
| Create of System.Guid * string
| Deactivate
| Rename of string
| CheckInItems of int
| RemoveItems of int

/// An inventory item event.
type Event =
| Created of string
| Deactivated
| Renamed of string
| ItemsCheckedIn of int
| ItemsRemoved of int

/// Applies a inventory item event to a state.
let apply item = function
| Created _ -> { item with State.isActive = true; }
| Deactivated _ -> { item with State.isActive = false; }
| Renamed _ -> item
| ItemsCheckedIn _ -> item
| ItemsRemoved _ -> item

/// Assertions used to maintain invariants upon command execution.
module private Assert =
let validName name = if System.String.IsNullOrEmpty(name) then invalidArg "name" "The name must not be null."
let validCount count = if count <= 0 then invalidArg "count" "Inventory count must be positive."
let inactive item = if item.isActive = true then failwith "The item is already deactivated."

/// Executes an inventory item command.
let exec item =

let apply event =
let newItem = apply item event
event

function

| Create(id, name) ->
Created(name) |> apply

| Deactivate ->
item |> Assert.inactive
Deactivated |> apply

| Rename(name) ->
name |> Assert.validName
Renamed(name) |> apply

| CheckInItems(count) ->
count |> Assert.validCount
ItemsCheckedIn(count) |> apply

| RemoveItems(count) ->
count |> Assert.validCount
ItemsRemoved(count) |> apply
20 changes: 20 additions & 0 deletions DDDInventoryItemFSharp/Projections.js
@@ -0,0 +1,20 @@
fromAll().
when({
"Created": function (s, e) {
var inventoryItemName = e.body["Name"];
//linkTo(
//emit("ByName-" + e.eventStreamId, "Created", { "name" : inventoryItemName })
},
"Deactivated": function (s, e) {

},
"Renamed": function (s, e) {
var newName = parseInt(e.body["Name"]);
},
"ItemsCheckedIn": function (s, e) {
var checkedInCount = parseInt(e.body["Count"]);
},
"ItemsRemoved": function (s, e) {
var removedCount = parseInt(e.body["Count"]);
}
});

0 comments on commit 9ed1fc9

Please sign in to comment.