The most popular client for EventStoreDB is the dotnet client, so naturally, this makes the library easy to use in F# as well. The first part is creating a project.
Disclaimer #1: I am still new to FSharp/F# so it is likely that the code is not as elegant as you would expect.
Disclaimer 2: This uses F# 6
dotnet new console -lang "F#" -o project_folder_name
Next we need to import the following libraries
https://www.nuget.org/packages/EventStore.Client.Grpc
https://www.nuget.org/packages/EventStore.Client.Grpc.Streams
dotnet add package EventStore.Client.Grpc --version 22.0.0
dotnet add package EventStore.Client.Grpc --version 22.0.0
You should be ready to use the library. Let’s get started with connecting to an EventStoreDB instance.
Import the library with:
open EventStore.Client
Then connect to the instance by providing a connection string.
let client = EventStoreClientSettings.Create "esdb://127.0.0.1:2113?tls=false"
|> EventStoreClient
The code above initialises an EventStoreDB client with a connection string telling the telling to connect to a single EventStoreDB instance running in insecure mode on localhost listening on the default HTTP port 2113.
After that you have to create a list of events to write. You can do that as follows:
let streamName = "sample_stream"
let eventData = EventData(
Uuid.NewUuid(),
"event_type",
ReadOnlyMemory<byte>(Encoding.UTF8.GetBytes("{\"some\":\"json data here\"}"))
)
let eventsList = List<EventData>()
eventsList.Add(eventData)
Feel free to wrap this in style with a record and functions to make it sexy. Basically we are create one event and adding it to a System.Collections.Generic List. You will likely need to import this.
After that writing events can be done as follows:
try
let result = client.ConditionalAppendToStreamAsync(streamName, StreamState.Any, eventsList).Result
match result.Status with
| ConditionalWriteStatus.Succeeded -> printfn "Events were written!"
| ConditionalWriteStatus.StreamDeleted -> printfn $"Didn't expect stream to be deleted"
| ConditionalWriteStatus.VersionMismatch -> printfn $"You should read https://developers.eventstore.com/clients/dotnet/21.2/appending.html#idempotence"
| _ -> printfn $"unknown outcome! {result.Status}"
with
| _ as e -> printfn$"{e.Message}"
We are trying to write with ConditionalAppendToStreamAsync, synchronously waiting for the result and matching the status with different outcomes. At the moment we have the versioning to Any, you might want to read about what that means and idempotency in EventStoreDB: https://developers.eventstore.com/clients/dotnet/21.2/appending.html#idempotence
Reading the event written is a bit trickier, you have to use TaskSeq to handle the IAsyncEnumerable returned. So you will first need to import https://github.com/fsprojects/FSharp.Control.TaskSeq
dotnet add package FSharp.Control.TaskSeq --version 0.3.0
You can then do a read backwards, of 1 event (1L means one Long) starting from the end of the stream.
client.ReadStreamAsync(Direction.Backwards,
streamName,
StreamPosition.End,
1L,
true)
|> TaskSeq.iter (fun event -> printfn$"
data: {Encoding.UTF8.GetString(event.OriginalEvent.Data.ToArray())}")
|> ignore
//probably need to wait here
I hope this has helped you get started with FSharp/F# and EventStoreDB. In this short post we have seen how to write and read events. There are more exciting things that you can do with EventStoreDB, so let me know if you would like to see more posts like this!