This is my first attempt at creating a small module to wrap the .NET library EasyNetQ in F# to make it more functional.
I am pretty new to F# and I would like to get feedbacks on everything: types, naming conventions, functional thinking, etc.
RabbitMQ.fs
:
module RabbitMQ
open EasyNetQ
open System
type BusConnection = {
Address: string
Port: uint16
Username: string
Password: string
}
type NamingConventions = {
RetrieveQueueName: Type -> string -> string
RetrieveExchangeName: Type -> string
RetrieveErrorQueueName: MessageReceivedInfo -> string
RetrieveErrorExchangeName: MessageReceivedInfo -> string
}
type Subscription<'T> = {
Id: string
OnMessageReceived: 'T -> unit
}
let private buildConnectionString (busConnection: BusConnection) =
sprintf "host=%s:%d;username=%s;password=%s"
busConnection.Address
busConnection.Port
busConnection.Username
busConnection.Password
let createBus (connection: BusConnection) =
let connectionString = buildConnectionString connection
RabbitHutch.CreateBus(connectionString)
let publishAsync<'T> (bus: IBus) (message: 'T) = bus.PubSub.PublishAsync<'T>(message)
|> Async.AwaitTask
let subscribeAsync<'T> (bus: IBus) (subscription: Subscription<'T>) = bus.PubSub.SubscribeAsync<'T>(subscription.Id, subscription.OnMessageReceived).AsTask()
|> Async.AwaitTask
let setNamingConventions (bus: IBus) (namingConventions: NamingConventions) =
bus.Advanced.Conventions.QueueNamingConvention <- new QueueNameConvention(namingConventions.RetrieveQueueName)
bus.Advanced.Conventions.ExchangeNamingConvention <- new ExchangeNameConvention(namingConventions.RetrieveExchangeName)
bus.Advanced.Conventions.ErrorQueueNamingConvention <- new ErrorQueueNameConvention(namingConventions.RetrieveErrorQueueName)
bus.Advanced.Conventions.ErrorExchangeNamingConvention <- new ErrorExchangeNameConvention(namingConventions.RetrieveErrorExchangeName)
Program.fs
:
open RabbitMQ
type Message = {
Text: string
}
[<EntryPoint>]
let main argv =
let busConnection = {
Address = "localhost"
Port = 5672 |> uint16
Username = "guest"
Password = "guest"
}
let namingConventions = {
RetrieveQueueName = fun messageType subscriptionId -> "Queue: " + (messageType.FullName + subscriptionId)
RetrieveExchangeName = fun messageType -> "Exchange: " + messageType.FullName
RetrieveErrorQueueName = fun messageReceivedInfo -> messageReceivedInfo.Queue + " - Error"
RetrieveErrorExchangeName = fun messageReceivedInfo -> messageReceivedInfo.Exchange + " - Error"
}
use bus = createBus busConnection
setNamingConventions bus namingConventions
let subscription = {
Id = "subscription_id"
OnMessageReceived = fun (message: Message) -> printfn "%A" message
}
async {
let! result = subscribeAsync<Message> bus subscription
do! publishAsync<Message> bus {Text = "1"}
do! publishAsync<Message> bus {Text = "2"}
do! publishAsync<Message> bus {Text = "3"}
} |> Async.RunSynchronously
Console.waitPressKey
0
Console.fs
module Console
open System
let waitPressKey = Console.ReadKey() |> ignore