Get Ip from TcpClient using f# - f#

Hi I have a question.
I am having simple server that looks like :
let private Listener ip port =
async {
let listener = new TcpListener(ip, port)
listener.Start()
_logger.Info(printfn "Server binded to IP: %A - Port: %i" ip port)
while listener.Pending() = false do
try
let! client = listener.AcceptTcpClientAsync() |> Async.AwaitTask
clientConnectionPool.Add(client) |> ignore
_logger.Info(printfn "Client connected: %O" client.Client.RemoteEndPoint)
with
| :? ServerListenerException as ex -> _logger.Error(printfn "Exception while starting server listener - %s" ex.Message); ()
}
And well it works, problem is now I want to get client Ip addres, normally in c# i would use:
((IPEndPoint)entry.Client.RemoteEndPoint).Address
And I believe in F# translate into:
let clientIp : IPAddress = (client.Client.RemoteEndPoint :> IPEndPoint).Address
But problem is I am getting message
Type constraint mismatch. The type 'EndPoint' is not compatible with type 'IPEndPoint'
What could be the issue??

In F# upcast and downcast are two separate things. This makes sense: upcast never fails, never results in a null, never throws an exception. Downcast may fail. What if that RemoteEndPoint value turns out not to be an instance of IPEndPoint?
As such, upcast and downcast are represented by two different operators. The one you're using - :> - is upcast. It only works if the target type is a supertype of the source type. Which in your case it is not - that's what the error is telling you.
The downcast operator is :?>. Try this:
let clientIp : IPAddress = (client.Client.RemoteEndPoint :?> IPEndPoint).Address

Related

Handle exceptions thrown by F# type provider in FSX script

I have an FSX script which includes a type provider. When the script is run, I would like to show a user-friendly message when the type provider throws an exception. (For example, when the SqlDataProvider cannot connect to the database.)
Is that possible?
This obviously won't work, but illustrates the idea:
type Sql =
try
SqlDataProvider< DatabaseVendor = databaseVendor, ConnectionString = connectionString, TableNames = tableNames >
with ex ->
printfn "Cannot connect to the database."
Here is a gist that can be used to test potential solutions.
When the script runs, the exception will be thrown, but not until you use or instantiate the type from the Type Provider.
In your case, you wouldn't wrap the definition of the type in a try, but rather the usage:
type Sql = SqlDataProvider<...>
// When you go to _use_ the type, handle exceptions:
try
let ctx = Sql.GetDataContext ()
// .. use
with
| :? SomeExceptionType as ex -> printfn "Cannot connect to the database."

Does the >>= operator not take a function?

I'm working on a side project and I'm using Hopac for the first time. I ran into an odd (to me) compilation issue that I haven't been able to grok. I suspect that I'm the problem here, and not Hopac.
The program is supposed to be a simple console app that consumes notifications from various services. Here's the problematic module:
module Provider
open System
open System.IO
open Hopac
open BitThicket.NotificationHelper.Core
open BitThicket.NotificationHelper.Providers
let defaultProviderTypes =
[| typeof<GitHub.GitHubNotificationProvider> |]
type Provider = {
getCh : Ch<Providers.INotification seq>
}
let giveLatest ch latest =
Ch.give
let start config logger (providerType:Type) = Job.delay <| fun () ->
let providerImpl = Activator.CreateInstance(providerType) :?> Providers.INotificationProvider
let p = { getCh = Ch() }
let rec server =
let latest = providerImpl.GetLatestNotificationsAsync(None) |> Job.fromAsync
latest >>= Ch.give p.getCh // error here
}
Job.start server
In this case, the compiler complains: Expecting a type supporting the operator '>>=' but given a function type. You may be missing an argument to a function.
Similarly, if I use a slightly different syntax:
// ...
let rec server =
let latest = providerImpl.GetLatestNotificationsAsync(None) |> Job.fromAsync
latest >>= fun l -> Ch.give p.getCh l // error here
// ...
In this case, the error is: This function takes too many arguments, or is used in a context where a function is not expected.
I asked haf about his in slack, and his suggestion was to check for alternative definitions of >>=. The tooling doesn't really do much to help me figure that one out, but the only namespace/module I have opened that defines >>= is Hopac (the BitThicket ones are just trivially simple namespaces with some type definitions in them).
What am I doing wrong here?
I'm looking at the source code, and I see that the bind operator is actually defined in Hopac.Infixes, not in Hopac.

Topshelf, Owin selfhost, F# and explicit fields

I've installed the package Topshelf.FSharp, and there is an example of how to use it here:
https://gist.github.com/haf/4252121
Part of the example defines an "Svc" (service) class like this:
type Svc() =
member x.Start() =
printfn "Started"
member x.Stop() =
printfn "Stopped"
With Owin selfhost you call one of the various static overloads of IDisposable WebApp.Start(...) to start a web server, and then dispose it to stop it. In C#, if you want to combine Topshelf and Owin, you can store the IDisposable result of Start() in a private local field of the Svc class when Start() is called, and then call Dispose() on it in the Stop() method.
In F# you can declare an unitialized field of type IDisposable using "explicit fields" (http://msdn.microsoft.com/en-us/library/dd469494.aspx), but this seems somewhat awkward, is there a better way?
You do not have to use an explicit field to produce an "uninitialized" IDisposable value. For example, to define a restartable service, you can use an implicit webApp field like this:
// Example 1: Using an implicit mutable IDisposable field.
type Svc() =
let mutable webApp = null
member __.Start() =
if webApp = null then webApp <- WebApp.Start<Startup> "http://localhost:12345"
member __.Stop() =
if webApp <> null then webApp.Dispose(); webApp <- null
// Example 2: Using an implicit mutable IDisposable option field.
type Svc'() =
let mutable webApp = None
member __.Start() =
match webApp with
| Some _ -> ()
| None -> webApp <- Some(WebApp.Start<Startup> "http://localhost:12345")
member __.Stop() =
match webApp with
| Some webAppValue -> webAppValue.Dispose(); webApp <- None
| None -> ()
If the service does not have to be restartable, I would use an (immutable) implicit lazy field instead, as #Tom suggested.
Could you make the member a Lazy<T> instead and have it automatically initialise when it is first accessed? I am not quite sure of the requirements of F# in this case i.e. why exactly this is a problem, but for deferred initialisation, Lazy would seem to be a good choice.

Log in function or function using it?

Is it best (I'm aware of that there's no silver bullet, but there may be some advantage by using one over the other) - to log in the calling function, or the function calling it?
Examples:
Approach 1
module MongoDb =
let tryGetServer connectionString =
try
let server = new MongoClient(connectionString).GetServer()
server.Ping()
Some server
with _ -> None
Usage:
match MongoDb.tryGetServer Config.connectionString with
| None ->
logger.Information "Unable to connect to the database server."
// ... code ...
| Some srv ->
logger.Information "Successfully connected to the database server."
// ... code ...
Approach 2
module MongoDb =
let tryGetServer connectionString =
try
let server = new MongoClient(connectionString).GetServer()
server.Ping()
Some server
with _ -> None
let tryGetServerLogable connectionString logger =
match tryGetServer connectionString with
| None ->
logger.Information "Unable to connect to the database server."
None
| Some srv ->
logger.Information "Successfully connected to the database server."
Some srv
Usage:
match MongoDb.tryGetServerLogable Config.connectionString logger with
| None ->
// ... code ...
| Some srv ->
// ... code ...
Approach 2 is better. In general, logging is a Cross-Cutting Concern, so it's best decoupled from implementation details. Cross-Cutting Concerns are best addressed via Composition; in OOD, this can be done with Decorators or Interceptors. In FP, we can sometimes learn from OOD, because many of the principles translate from objects to closures.
However, instead of using Approach 2 above verbatim, I'd rather prefer something like this:
module MongoDb =
let tryGetServer connectionString =
try
let server = MongoClient(connectionString).GetServer()
server.Ping()
Some server
with _ -> None
Notice that the MongoDb module has no knowledge of logging. This follows the Single Responsibility Principle, which is also valuable in Functional Programming.
The tryGetServer function has this signature:
string -> MongoServer option
Now you can define a logging function, totally decoupled from the MongoDb module:
module XyzLog =
type Logger() =
member this.Information message = ()
let tryGetServer f (logger : Logger) connectionString =
match f connectionString with
| None ->
logger.Information "Unable to connect to the database server."
None
| Some srv ->
logger.Information "Successfully connected to the database server."
Some srv
Here, you can imagine that XyzLog is a placeholder for a particular logging module, utilising Serilog, Log4Net, NLog, your own custom logging framework, or similar...
The f argument is a function with the generic signature 'a -> 'b option, of which MongoDb.tryGetServer is a specialization.
This means that you can now define a partially applied function like this:
let tgs = XyzLog.tryGetServer MongoDb.tryGetServer (XyzLog.Logger())
The function tgs also has the signature
string -> MongoServer option
So any client that depends on a function with this signature can use MongoDb.tryGetServer or tgs interchangeably, without knowing the difference.
This enables you to change you mind or refactor both MongoDb.tryGetServer and your logging infrastructure independently of each other.
There is a more general way to implement cross-cutting concerns such as logging with a functional language. The example I have is from an async service library (think ASP.NET MVC and ActionFilters) but the same applies here as well. As stated by Mark, the function tryGetServer is of type string -> MongoServer option. Suppose we abstract it to:
type Service<'a, 'b> = 'a -> 'b option
Then suppose we also have a type as follows:
type Filter<'a, 'b> = 'a -> Service<'a, 'b> -> 'b option
A filter is a function which takes a value 'a and a Service<'a, 'b> and then returns a value of the same type as the Service<'a, 'b> function. The simplest filter is a function which simply passes the 'a it receives directly to the service and returns the value it gets from the service. A more interesting filter would be a function which prints a log message after receiving output from the service.
let loggingFilter (connStr:string) (tryGetServer:string -> MongoServer option) : Filter<string, MongoServer option> =
let server = tryGetServer connStr
match tryGetServer connStr with
| Some _ ->
logger.Information "Successfully connected to the database server."
server
| None ->
logger.Information "Unable to connect to the database server."
server
Then if you have the following defined:
type Continuation<'a,'r> = ('a -> 'r) -> 'r
module Continuation =
let bind (m:Continuation<'a, 'r>) k c = m (fun a -> k a c)
module Filter =
/// Composes two filters into one which calls the first one, then the second one.
let andThen (f2:Filter<_,,_>) (f1:Filter<_,_>) : Filter<_,_> = fun input -> Continuation.bind (f1 input) f2
/// Applies a filter to a service returning a filtered service.
let apply (service:Service<_,_>) (filter:Filter<_,_>) : Service<_,_> = fun input -> filter input service
/// The identity filter which passes the input directly to the service and propagates the output.
let identity : Filter<_,_> = fun (input:'Input) (service:Service<_,_>) -> service input
You can apply a filter to a service and get back the original service type but which now does logging:
let tryGetServerLogable = Filter.apply tryGetServer loggingFilter
Why bother? Well, now you can compose filters together. For example you may add a filter which measures the time it takes to create a connection and you can then combine them using Filter.andThen. The gist I originally made is here.
Another approach to consider is the use of a writer monad. With the writer monad, you can defer the actual printing of log messages until some well defined point, but still have similar composition characteristics.

Emitting Generated Types in F# type providers

I have created a simple generating type provider that takes the path to an assembly at reorganizes the types, to bring them under the type providers namespace, (sort of Internalising if you like).
The link to the code concerned is here
https://github.com/colinbull/Playground
Now the types seem to be provided correctly,
let[<Literal>]assemblyPath = #"D:\Appdev\Playground\SimpleLib\bin\Debug\SimpleLib.dll"
type T = Inno.InternalisingProvider<assemblyPath>
type C = T.Class1
[<EntryPoint>]
let main argv =
let c = new C()
printfn "Result: %A" c.X
System.Console.ReadLine() |> ignore
0
since the displays in VS without any reported errors. However when I compile this assembly the IL seems to get emitted incorrectly with the following error.
Error 1: A problem occurred writing the binary 'obj\Debug\TypeProviders.Tests.exe': Error in pass3 for type Program, error: Error in GetMethodRefAsMethodDefIdx for mref = ".ctor", error: Exception of type 'Microsoft.FSharp.Compiler.AbstractIL.ILBinaryWriter+MethodDefNotFound' was thrown. FSC 1 1 TypeProviders.Tests
Examples given for generated types given in samples pack doesn't seem to have any StaticParameters defined which requires a type with the provided type name to be returned. In this case how do I emit the types in the provided assembly? Currently I am doing the following
let provideAssembly (reqType:ProvidedTypeDefinition) assemblyPath =
let name = Path.GetFileName(assemblyPath)
let providedAssembly = ProvidedAssembly.RegisterGenerated(assemblyPath)
for t in providedAssembly.GetExportedTypes() do
let ty = createGeneratedType t
ty.SetAssembly(providedAssembly)
reqType.AddMember(ty)
reqType
Thanks in advance
Disclaimer: browser compiled solutions
I believe here you don't need to create generated types that will wrap exiting types => this should work
let provideAssembly (reqType:ProvidedTypeDefinition) assemblyPath =
let existingAssembly = Assembly.LoadFrom(assemblyPath)
for ty in providedAssembly.GetExportedTypes() do
reqType.AddMember(ty)
reqType
You can also try this one:
let provideAssembly (reqType:ProvidedTypeDefinition) assemblyPath =
reqType.AddAssemblyTypesAsNestedTypesDelayed(fun() -> Assembly.LoadFrom assemblyPath)
reqType
this one will preserve namespace so declaration of type C will look like
type C = T.SimpleLib.Class1

Resources