I have a web project which requires stats/logs on a web page to be updated from an external soap service. The approach I have decided to take with this is to use signalR, by having code that would execute a service method and return the results to all connected clients. This code will be continuously executed, with a delay between service calls.
I am having trouble putting all of the pieces together, probably because I am not sure where everything should go! Here is a rough breakdown at what I have done so far
class Data { ... }
interface IDataService
{
Task GetDataAsync(TimeSpan interval, CancellationToken cancellationToken, Action<Data> callback);
}
class DataService : IDataService
{
private readonly ExternalService _externalService;
public async Task GetDataAsync(TimeSpan interval, CancellationToken cancellationToken, Action<Data> callback)
{
while (!cancellationToken.IsCancellationRequested)
{
var data = await this._externalService.GetData();
callback(data);
await Task.Delay(interval).ConfigureAwait(false);
}
}
}
So above is the logic that gets the data from the external service, and executes a callback. As for signalR, the only thing I have done is as follows
public class DataHub : Hub
{
private readonly IDataService _service;
public DataHub(IDataService service)
{
this._service = service;
}
public async Task GetData()
{
var tenSeconds = new TimeSpan(0, 0, 10);
var token = new CancellationToken();
await _service.GetDataAsync(tenSeconds, token, d =>
{
// signal all connected clients
});
}
}
The GetData()
method can be called when clients connect (if it isn't already running) and the token can be cancelled when there are no more clients connected to the hub.
(Potential) Problems:
- SignalR hubs are not singletons are they? I assume they are created when needed and disposed when not needed anymore (request has finished). In which case I will have multiple instances of the
GetData
method running (unless I make the DataService class a singleton/injected as a singleton). - A hub doesn't feel like the right place to do this. A hub should be treated like an MVC/Web Api controller? So a request comes in, hub handles it, request is finished. End of story.
- Another way to do this would be to pass the hub into the dataservice. And then it can call the clients. But I don't really want to be passing around IHubContext objects. I want to keep the service as simple as possible.
- Would an ASP.NET background task be more appropriate here?
Would be grateful if someone can point me to the right/best approach!