F# Invoke Timer doesn't work due to reflection w/ System.Threading.Tasks.Task
- Dominant language
- C#
- Stars
- 1.2k
- Forks
- 378
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 5
Description
## Expected Behavior
I should be able to register a Timer in an F# Actor and have it call the appropriate method.
## Actual Behavior
The dotnet sdk throws an error on `ValidateTimerCallback`.
The first error occurs on [`Actor.cs ln:335`](https://github.com/dapr/dotnet-sdk/blob/master/src/Dapr.Actors/Runtime/Actor.cs#L335) is:
`Timer callback method: {callback} does not exist in the Actor class: {actorTypeName}`
This can be worked around by prefixing the method name (callback argument) with "get_". For example the `Tick` method must be registered to the timer as `get_Tick`.
The second error is when validating that the return type is a `Task`. Even if the method just returns `Task.CompletedTask` [this line ](https://github.com/dapr/dotnet-sdk/blob/master/src/Dapr.Actors/Runtime/Actor.cs#L348) will throw an error saying that the return type is not a task.
When I inspect the ReturnType while debugging I see that the F# `Task` is: `Microsoft.FSharp.Core.FSharpFunc``2[[Microsoft.FSharp.Core.Unit, FSharp.Core, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a],[System.Threading.Tasks.Task, System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], FSharp.Core, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a`
If I remove the Validation function I run into an exception on [this line](https://github.com/dapr/dotnet-sdk/blob/master/src/Dapr.Actors/Runtime/ActorManager.cs#L220) when it tries to cast the method call into a Task:
The tick method can be invoked via the dotnet sdk without issues via:
(POST {{daprUrl}}/v1.0/actors/MyActor/myactorid/method/Tick)
Maybe the dotnet sdk can fall back to calling the method the same way the InvokeMethod does without trying to cast the method to a `Task`?
[DispatchInternalAsync does work when invoking the method](https://github.com/dapr/dotnet-sdk/blob/master/src/Dapr.Actors/Runtime/ActorManager.cs#L321)
[DispatchWithoutRemoting](https://github.com/dapr/dotnet-sdk/blob/master/src/Dapr.Actors/Runtime/ActorManager.cs#L128)
## Steps to Reproduce the Problem
From an F# actor call the Start method:
(POST {{daprUrl}}/v1.0/actors/MyActor/myactorid/method/Start)
`
member this.Start() =
task {
do!
this.RegisterTimerAsync(
"Tick",
"get_Tick",
null,
TimeSpan.FromMilliseconds(float 1000),
TimeSpan.FromMilliseconds(float 1000)
)
|> Async.AwaitTask
|> Async.Ignore
} :> Task
`
The tick method can be:
`member this.Tick() = Task.CompletedTask`
## Release Note
RELEASE NOTE:
Contributor guide
Assessment
This issue has not been assessed yet.