Header menu logo FCQRS

Bootstrapping

The ultimate objective of write side bootstrapping is to make a call to FCQRS.Actor.api which initializes the actor system and starts the write side. This API requires a configuration and a logger factory. The configuration is used to configure the actor system and the logger factory is used to log messages from the actor system.

open System.IO
open Microsoft.Extensions.Configuration
open Hocon.Extensions.Configuration
open Microsoft.Extensions.Logging

let configBuilder =
    ConfigurationBuilder()
        .AddHoconFile(Path.Combine(__SOURCE_DIRECTORY__, "config.hocon"))

let config = configBuilder.Build()

let loggerFactory =
    LoggerFactory.Create(fun builder -> builder.AddConsole() |> ignore) 

You don't have to use HOCON configuration. You can use any configuration system you like , as long as you can build a configuration object that implements IConfiguration.

let actorApi = FCQRS.Actor.api config loggerFactory

actorApi.InitializeSagaStarter (fun _ -> [])

Next we create a shard for the User aggregate. A shard is like parent of aggregate actors. And initilize the shard.

let env = new Environments.AppEnv(config,loggerFactory)

let userShard = User.factory env actorApi

User.init env actorApi |> ignore

We create a helper function to send commands to the actor. cid means corralation id and it is used to track the command.

let userSubs cid =  actorApi.CreateCommandSubscription userShard cid

Finally we initialize the query side. But also gets subscription for the query side.

let sub handleEventWrapper offsetCount = 
    FCQRS.Query.init actorApi offsetCount (handleEventWrapper env)
namespace System
namespace System.IO
namespace Microsoft
namespace Microsoft.Extensions
namespace Microsoft.Extensions.Configuration
namespace Hocon
namespace Hocon.Extensions
namespace Hocon.Extensions.Configuration
namespace Microsoft.Extensions.Logging
val configBuilder: IConfigurationBuilder
Multiple items
type ConfigurationBuilder = interface IConfigurationBuilder new: unit -> unit member Add: source: IConfigurationSource -> IConfigurationBuilder member Build: unit -> IConfigurationRoot member Properties: IDictionary<string,obj> member Sources: IList<IConfigurationSource>
<summary> Builds key/value-based configuration settings for use in an application. </summary>

--------------------
ConfigurationBuilder() : ConfigurationBuilder
type Path = static member ChangeExtension: path: string * extension: string -> string static member Combine: path1: string * path2: string -> string + 4 overloads static member EndsInDirectorySeparator: path: ReadOnlySpan<char> -> bool + 1 overload static member Exists: path: string -> bool static member GetDirectoryName: path: ReadOnlySpan<char> -> ReadOnlySpan<char> + 1 overload static member GetExtension: path: ReadOnlySpan<char> -> ReadOnlySpan<char> + 1 overload static member GetFileName: path: ReadOnlySpan<char> -> ReadOnlySpan<char> + 1 overload static member GetFileNameWithoutExtension: path: ReadOnlySpan<char> -> ReadOnlySpan<char> + 1 overload static member GetFullPath: path: string -> string + 1 overload static member GetInvalidFileNameChars: unit -> char array ...
<summary>Performs operations on <see cref="T:System.String" /> instances that contain file or directory path information. These operations are performed in a cross-platform manner.</summary>
Path.Combine(paths: System.ReadOnlySpan<string>) : string
Path.Combine([<System.ParamArray>] paths: string array) : string
Path.Combine(path1: string, path2: string) : string
Path.Combine(path1: string, path2: string, path3: string) : string
Path.Combine(path1: string, path2: string, path3: string, path4: string) : string
val config: IConfigurationRoot
IConfigurationBuilder.Build() : IConfigurationRoot
val loggerFactory: ILoggerFactory
Multiple items
type LoggerFactory = interface ILoggerFactory interface IDisposable new: unit -> unit + 5 overloads member AddProvider: provider: ILoggerProvider -> unit member CreateLogger: categoryName: string -> ILogger member Dispose: unit -> unit static member Create: configure: Action<ILoggingBuilder> -> ILoggerFactory
<summary> Produces instances of <see cref="T:Microsoft.Extensions.Logging.ILogger" /> classes based on the given providers. </summary>

--------------------
LoggerFactory() : LoggerFactory
LoggerFactory(providers: System.Collections.Generic.IEnumerable<ILoggerProvider>) : LoggerFactory
LoggerFactory(providers: System.Collections.Generic.IEnumerable<ILoggerProvider>, filterOptions: LoggerFilterOptions) : LoggerFactory
LoggerFactory(providers: System.Collections.Generic.IEnumerable<ILoggerProvider>, filterOption: Extensions.Options.IOptionsMonitor<LoggerFilterOptions>) : LoggerFactory
LoggerFactory(providers: System.Collections.Generic.IEnumerable<ILoggerProvider>, filterOption: Extensions.Options.IOptionsMonitor<LoggerFilterOptions>, options: Extensions.Options.IOptions<LoggerFactoryOptions>) : LoggerFactory
LoggerFactory(providers: System.Collections.Generic.IEnumerable<ILoggerProvider>, filterOption: Extensions.Options.IOptionsMonitor<LoggerFilterOptions>, ?options: Extensions.Options.IOptions<LoggerFactoryOptions>, ?scopeProvider: IExternalScopeProvider) : LoggerFactory
LoggerFactory.Create(configure: System.Action<ILoggingBuilder>) : ILoggerFactory
val builder: ILoggingBuilder
(extension) ILoggingBuilder.AddConsole() : ILoggingBuilder
(extension) ILoggingBuilder.AddConsole(configure: System.Action<Console.ConsoleLoggerOptions>) : ILoggingBuilder
val ignore: value: 'T -> unit
val actorApi: FCQRS.Common.IActor
namespace FCQRS
module Actor from FCQRS
val api: env: 'a -> FCQRS.Common.IActor (requires 'a :> FCQRS.Common.IConfigurationWrapper and 'a :> FCQRS.Common.ILoggerFactoryWrapper)
abstract FCQRS.Common.IActor.InitializeSagaStarter: (obj -> ((string -> Akkling.Cluster.Sharding.IEntityRef<obj>) * FCQRS.Common.PrefixConversion * obj) list) -> unit
val env: Environments.AppEnv
module Environments
Multiple items
type AppEnv = interface IConfigurationWrapper interface ILoggerFactoryWrapper new: config: IConfiguration * loggerFactory: ILoggerFactory -> AppEnv
<summary> Composition root for the application environment. While being a god object is an anti-pattern, it plays nicely with F# partial application. Much better than DI magic with reflection. It wraps IConfiguration and ILoggerFactory. </summary>

--------------------
new: config: IConfiguration * loggerFactory: ILoggerFactory -> Environments.AppEnv
val userShard: (string -> Akkling.Cluster.Sharding.IEntityRef<obj>)
module User
val factory: env: 'a -> actorApi: FCQRS.Common.IActor -> entityId: string -> Akkling.Cluster.Sharding.IEntityRef<obj> (requires 'a :> FCQRS.Common.IConfigurationWrapper and 'a :> FCQRS.Common.ILoggerFactoryWrapper)
val init: env: 'a -> actorApi: FCQRS.Common.IActor -> Akkling.Cluster.Sharding.EntityFac<obj> (requires 'a :> FCQRS.Common.IConfigurationWrapper and 'a :> FCQRS.Common.ILoggerFactoryWrapper)
val userSubs: cid: FCQRS.Model.Data.CID -> (FCQRS.Model.Data.ActorId -> 'a -> ('b -> bool) -> Async<FCQRS.Common.Event<'b>>)
val cid: FCQRS.Model.Data.CID
abstract FCQRS.Common.IActor.CreateCommandSubscription: (string -> Akkling.Cluster.Sharding.IEntityRef<obj>) -> FCQRS.Model.Data.CID -> FCQRS.Model.Data.ActorId -> 'b -> ('c -> bool) -> Async<FCQRS.Common.Event<'c>>
val sub: handleEventWrapper: (Environments.AppEnv -> int64 -> obj -> 'a list) -> offsetCount: int64 -> FCQRS.Query.ISubscribe<'a>
val handleEventWrapper: (Environments.AppEnv -> int64 -> obj -> 'a list)
val offsetCount: int64
module Query from FCQRS
val init<'TDataEvent,'TPredicate,'t> : actorApi: FCQRS.Common.IActor -> offsetCount: int64 -> handler: (int64 -> obj -> 'TDataEvent list) -> FCQRS.Query.ISubscribe<'TDataEvent>

Type something to start searching.