F# Singleton and disposing internal resources - f#

In my AWS lambda function, I need to access secret values from the AWS Secret manager. I am using the AWSSDK.SecretsManager.Caching package to achieve this. To get the most out of the provided caching mechanism, I have decided to create a simple singleton wrapper around the SecretsManagerCache:
namespace MyProject
open Amazon.SecretsManager.Extensions.Caching
type SecretsProvider private () =
let secretsCache = new SecretsManagerCache()
static let instance =
SecretsProvider()
static member Instance = instance
member this.GetSecretString key =
secretsCache.GetSecretString key
This seems to be fine, but there is one thing that concerns me. The SecretsManagerCache implements IDisposable. I have tried writing
use secretsCache = new SecretsManagerCache()
but that gives me a compiler error saying 'use' bindings are not permitted in primary constructors. Is it OK to simply use the let keyword? Or should I implement a finalizer?
override this.Finalize() =
secretsCache.Dispose()
Or is there another way how to safely dispose an internal resource from a singleton?

You can wrap your SecretsManager in a SecretsProvider like you have done but implementing IDisposable to dispose of the SecretsManager object.
type ISecretsProvider =
abstract member GetSecretString : key:string -> string
type SecretsProvider () =
let secretsCache = new SecretsManagerCache()
interface IDisposable with
member x.Dispose() = ()
secretsCache.Dispose()
interface ISecretsProvider with
member this.GetSecretString key =
secretsCache.GetSecretString key
You can then declare your dependencies in your functions e.g:
f : ISecretsProvider->int->'T
g : 'T->unit
h : ISecretsProvider->unit
For a console application you can provide the only instance of this dependency in your entry point function:
[<EntryPoint>]
let main _ =
use sp = new SecretsProvider()
let a = f sp 2
g a
h sp
If you're using ASP.NET core you can do so with configureServices:
let configureServices (services : IServiceCollection) =
services.AddSingleton<ISecretsProvider, SecretsProvider>() |> ignore
Update: As Discussed with #Panagiotis Kanavos the SecretsProvider may not be necessary. You may use SecretsManager instead of ISecretsProvider an SecretsProvider in the above code. However, to achieve loose coupling interfaces are good practice, this will depend more on the complexity and goals of your overall solution.

Related

NancyFx F# App with parameter

I am trying to get this example translated from C# to F#
public class MyModule : NancyModule
{
private IMyDependency _dependency;
public MyModule(IMyDependency dependency)
{
_dependency = dependency;
Get["/"] = x =>
{
};
// Register other routes
}
}
(source 1)
However adding a parameter to constructor
type HelloModule(dependency) as self =
inherit NancyModule()
do
self.Get.["/"] <- fun _ -> "Hello" :> obj
(source 2)
results in a run-time exception: System.InvalidOperationException: 'Something went wrong when trying to satisfy one of the dependencies during composition ...
How can I correctly add a dependency like a data-source to the code? Or, generally, how do I pass something from outside of HelloModule to the inside?
I'm guessing this might be caused by not specifying the type of the dependency parameter of the constructor in your F# code. This would result in the F# compiler assigning that parameter a generic type, and then Nancy's dependency injection framework doesn't know what to inject.
Try the following and see if it fixes your problem:
type HelloModule(dependency : IMyDependency) as self =
inherit NancyModule()
do
self.Get.["/"] <- fun _ -> "Hello" :> obj
P.S. Naturally, for this to work, you'll also need to have some type that implements the IMyDependency interface, and have told the Nancy framework about that type. From this part of the Nancy documentation that you linked to, it looks like merely declaring the type is enough, but if that's not actually enough then you'll have to register the type manually. I'm not familiar enough with Nancy to give you specific advice there beyond what the documentation says.

Why Moq verify method call throws exception?

I can't get this piece of code to pass.
[<Test>]
member public this.Test() =
let mock = new Mock<IList<string>>()
let mockObj = mock.Object
mockObj.Add("aaa")
mock.Verify(fun m -> m.Add(It.IsAny<string>()), Times.Once())
Exception I get:
System.ArgumentException : Expression of type 'System.Void' cannot be used for constructor parameter of type 'Microsoft.FSharp.Core.Unit'
I believe it has something to do with F# not inferring properly the data type of labda expression but I don't know how to fix that.
You are correct, this an issue with F# type inference when calling an overloaded method that accepts either Action or Func.
One option is to download the Moq.FSharp.Extensions from Nuget and change your Verify to an explicit VerifyAction, i.e.
open Moq.FSharp.Extensions
type MyTests() =
[<Test>]
member public this.Test() =
let mock = new Mock<IList<string>>()
let mockObj = mock.Object
mockObj.Add("aaa")
mock.VerifyAction((fun m -> m.Add(any())), Times.Once())
Underneath the covers the Moq.FSharp.Extensions simply defines an extension method VerifyAction that only takes an Action to avoid ambiguity:
type Moq.Mock<'TAbstract> when 'TAbstract : not struct with
member mock.VerifyAction(expression:Expression<Action<'TAbstract>>) =
mock.Verify(expression)
Another option is to use Foq, a mocking library with a similar API to Moq but designed specifically for use from F#, also available via Nuget:
[<Test>]
member public this.Test() =
let mock = Mock.Of<IList<string>>()
mock.Add("aaa")
Mock.Verify(<# mock.Add(any()) #>, once)

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.

Alternatives to functors in F#

I would like to write the following:
module A =
type Token
let foo Token =
module B =
type Token
let foo Token =
let run (m : module) =
m.B
|> m.foo
basically a function that's generic in the module. Is there a way to do this in F#?
As kvb pointed out in a comment, it is hard to give an answer without a realistic example, because the best approach will depend on what you're actually trying to do.
In this trivial example, I would probably use F# interface to represent Token and add Foo as a member. Assuming that Foo returns an int, you can write the definition like this:
type Token =
abstract Foo : unit -> int
Then you can implement different tokens either using classes (which is quite heavyweight) or using object expressions. For example:
let tok = { new Token with
member x.Foo () = 42 }
The code that corresponds to your run function is just a call of the Foo member: tok.Foo()

why is the implementation of my abstract member not public

I've been struggling to get this to compile for about an hour. It must be something stupid. Can you spot it?
in my lib project:
namespace TravelerStuff
open System
type Traveler =
abstract GetData : unit -> unit
type public DeltaTraveler() =
interface Traveler with
member v.GetData () =
printf "hello"
and in my console test app:
[<EntryPoint>] let main _ =
let traveler = new TravelerStuff.DeltaTraveler()
traveler.GetData // this line won't compile: (The field, constructor or member 'GetData' is not defined)
As gradbot says, F# doesn't currently implicitly convert values to interfaces when searching for members. Also, F# only uses explicit interface implementation (as known from C#) and not implicit implementation where members are not only compiled as implementation of an interface, but also as ordinary (directly visible) members of the type.
Aside from casting, you can duplicate the member in the type definition:
type DeltaTraveler() =
member v.GetData () = printf "hello"
interface Traveler with
member v.GetData () = v.GetData()
Also, if you just want to implement an interface, but don't need to add any members, you can use F# object expressions (which are more lightweight):
let deltaTraveler() =
{ new Traveler with
member v.GetData () = printf "hello" }
// The function directly returns value of type 'Traveler'
let t = deltaTraveler()
t.GetData()
You need to upcast. F# currently won't do it for you in this situation.
(traveler :> TravelerStuff.Traveler).GetData()
// open the namespace to reduce typing.
open TravelerStuff
(traveler :> Traveler).GetData()
Snip from F# docs.
In many object-oriented languages,
upcasting is implicit; in F#, the
rules are slightly different.
Upcasting is applied automatically
when you pass arguments to methods on
an object type. However, for let-bound
functions in a module, upcasting is
not automatic, unless the parameter
type is declared as a flexible type.
For more information, see Flexible Types (F#).

Resources