Rebus - Exit application from Handle method - rebus

I'm implementing an enricher pattern (https://www.enterpriseintegrationpatterns.com/patterns/messaging/DataEnricher.html) using a command/consumer queue where the consumer is the enricher and publishes the enriched message to a separate endpoint (SQL database in this case). The consumer is running as a HostedService which implements cancellation token.
Because I'm consuming commands from one transport and publishing events to another there is a possibility that the transport I'm publishing to is down while the one I'm consuming from is up. In that case I'd like to log an error and stop my Hosted service. However, I cannot see how that would work since whatever calls the Handle method already handles exceptions, and I cannot access my cancellation token. Does anyone have any ideas?
This is a draft of what I want to do.
public async Task Handle(EditedEventData message)
{
var enricher = _enricherFactory.GetEnricher(message);
object #event = await enricher.EnrichAsync(message);
var transformers = _transformerFactory.GetTransformers(message);
var messages = new List<object>();
foreach (var transformer in transformers)
{
messages.AddRange(transformer.Transform(#event, message));
}
foreach (var item in messages)
{
try
{
await _bus.Publish(item);
}
catch (Exception ex)
{
_logger.LogCritical("Publishing event message {#item} failed with error {ex}", item, ex);
//how do I exit from here?
}
}
}

If I were you, I would come up with some kind of application service, e.g. IApplicationControlService, which you can configure to be injected into your handlers using whichever IoC container you're using.
It could look somewhat like this:
public interface IApplicationControlService
{
void RequestApplicationShutdown();
}
and then your code could simply
public class YourHandler : IHandleMessages<EditedEventData>
{
readonly IApplicationControlService applicationControlService;
public YourHandler(IApplicationControlService applicationControlService)
{
this.applicationControlService = applicationControlService;
}
public async Task Handle(EditedEventData message)
{
// (...)
foreach (var item in messages)
{
try
{
await _bus.Publish(item);
}
catch (Exception ex)
{
_logger.LogCritical("Publishing event message {#item} failed with error {ex}", item, ex);
applicationControlService.RequestApplicationShutdown();
}
}
}
}
to request the application be stopped, when an error occurs.
An implementation of IApplicationControlService could then be something like
public class BruteForceApplicationControlService : IApplicationControlService
{
public void RequestApplicationShutdown()
{
Environment.FailFast("you should probably not do THIS 😉");
}
}
or something more gentle 😁 – the point is, that you will be able to provide a way to request your application to shut down "from the outside", most likely from the place where your application is assembled (i.e. the "composition root")

Related

Blazor WebAssembly SignalR HubConnection causing javascript error on reload

I have a SignalR HubConnection within my Blazor WebAssembly application and whilst it works most of the time, if I reload the page (via the browser reload) then I often am getting the following error in the console and the connection is not made:
Uncaught Error: The delegate target that is being invoked is no longer available. Please check if it has been prematurely GC'd.
at Object.invoke_delegate (dotnet.5.0.4.js:1)
at WebSocket. (dotnet.5.0.4.js:1)
Here's a rough, simplified view of the code where I create the HubConnection (and dispose it).
#inherits LayoutBase
#attribute [Authorize]
<AuthorizeView>
<Authorized>
//...
</Authorized>
<NotAuthorized>
//...
</NotAuthorized>
</AuthorizeView>
public class LayoutBase : LayoutComponentBase, IAsyncDisposable
{
[Inject] public IAccessTokenProvider AccessTokenProvider { get; set; }
private readonly HubConnection _hubConnection;
protected override async Task OnInitializedAsync()
{
_hubConnection = new HubConnectionBuilder()
.AddNewtonsoftJsonProtocol(c =>
{
//...
})
.WithUrl(notificationHubUrl, option => option.AccessTokenProvider = GetAccessToken)
.WithAutomaticReconnect()
.Build();
_hubConnection.Closed += HubConnectionOnClosed;
_hubConnection.Reconnected += HubConnectionOnReconnected;
_hubConnection.Reconnecting += HubConnectionOnReconnecting;
await _hubConnection.StartAsync()
await base.OnInitializedAsync();
}
private async Task<string> GetAccessToken()
{
var tokenResult = await AccessTokenProvider.RequestAccessToken(...)
// etc...
}
// .. Event Handlers
public ValueTask DisposeAsync()
{
_logger.LogInformation($"Disposing Hub: {_hubConnection.ConnectionId}");
_hubConnection.Closed -= HubConnectionOnClosed;
_hubConnection.Reconnected -= HubConnectionOnReconnected;
_hubConnection.Reconnecting -= HubConnectionOnReconnecting;
return _hubConnection.DisposeAsync();
}
}
Previously I had it as an injected service but I eventually simplified it to this structure but it continues to get this error on reload. It's not every time I reload but most times.
I have tried changing the dispose pattern without success. I can't find any information on the error anywhere else.
Any ideas?
I don't have a definitive answer as to the underlying reason but I suspect that this is a bug somewhere in the SignalR/dotnet framework resulting in the GCing of a delegate because something drops a reference to it.
One way I've managed to provoke this error reasonably consistently is to have a handler returning just a Task, e.g.
_hubConnection.On<TEvent>(eventType.Name, OnEvent);
where OnEvent looks like this:
// THIS IS THE BROKEN SIGNATURE - DO NOT USE
private async Task OnEvent<TEvent>(TEvent e)
{
}
A workaround which appears to have fixed it for me is to make the handler actually return something. This seems to make something deeper in the framework hold a reference for longer so that it doesn't get GC'ed. E.g.
// WORKS ON MY MACHINE - Note the return type of Task<object>
private async Task<object> OnEvent<TEvent>(TEvent e)
{
// ... Do stuff
return null;
}

Flutter and external JAR Library: android.os.NetworkOnMainThreadException

Im trying to use olingo with Flutter on Android. I set up my channel and I can call the library but I keep getting this message:
E/AndroidRuntime(28391): FATAL EXCEPTION: main
E/AndroidRuntime(28391): Process: com.example.odata, PID: 28391
E/AndroidRuntime(28391): org.apache.olingo.client.api.http.HttpClientException: android.os.NetworkOnMainThreadException
E/AndroidRuntime(28391): at org.apache.olingo.client.core.communication.request.AbstractODataRequest.doExecute(AbstractODataRequest.java:312)
So it looks like it is running on the main thread - which is a no go as this would block. I tried the looper to ask Java to run on the UI Thread:
public void onMethodCall(MethodCall call, Result result) {
// Note: this method is invoked on the main thread.
Log.i("test", "using " + call.method);
String serviceUrl = "http://services.odata.org/OData/OData.svc/";
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
if (call.method.equals("getMetaData")) {
String metadata;
final Edm edm = ODataClientFactory.getClient().getRetrieveRequestFactory().getMetadataRequest(serviceUrl).execute().getBody();
metadata = edm.toString();
if (metadata != "") {
result.success(metadata);
} else {
result.error("UNAVAILABLE", "Metadata cannot read.", null);
}
} else {
result.notImplemented();
}
}
});
But Im still getting the same error.
So how exactly can I deal with external JAR Library which are doing blocking operations ? To my understanding an external call is a Future anyway so it will not block my Flutter thread anyway - but Android Java does not think so ...
This is my method call in flutter
Future<void> _getMetaData() async {
String metadata;
try {
final String result = await platform.invokeMethod('getMetaData');
metadata = result;
} on PlatformException catch (e) {
metadata = e.message;
}
setState(() {
_metadata = metadata;
});
}
Thanks for the answer, this is the solution for anyone that may be interested:
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("getMetaData")) {
class MetadataLoader extends AsyncTask<String , Integer, String> {
#Override
protected String doInBackground(String... urls) {
// call your Java library method here, including blocking methods
return your_return_value;
}
protected void onPostExecute(String _result) {
// your_return_value is now passed in _result
result.success(_result);
}
}
new MetadataLoader().execute(); // Start the Async
}
On the flutter side,
Future<void> _getMetaData() async {
String metadata;
try {
final String result = await platform.invokeMethod('getMetaData');
// do something with the result
// the Flutter thread will stop at the await and resume when the Java
// will call result.success
}
}
You will need to create a new Java thread or Worker. (Note that the "main" thread and the "UI" thread are the same thing - so by posting to the main looper you've ended up in the same place - trying to do network i/o on the main thread.)
Yes, the Flutter engine is running in different threads, but you still need to leave the main native thread unblocked as it is responsible for detecting user input, etc.
Also note that when your blocking activity completes - on its non-main thread - it will likely want to deliver the response to Dart. To do this it will need to use part of your code above - to post the results back to the main thread, which can then invoke method channel operations.
You'll probably want to use your method channel bi-directionally. From flutter to native to request an operation (returning, say, a sequence number), and from native to flutter to deliver the results (quoting the sequence number so that the result can be tied back to the request).

Working with static method Asp.Net

Good night guys!
I'm having the following problem ...
I have a web application that runs a "thread" that takes messages from the queue (MSMQ) ... Everything works correctly .. the problem is when I get this message, I can not display .. because the method that returns the message content is a "static" ..
I need to perform a function in JS to display this message.
conclusion:
The method "ProcessMessage" can not be named because he is not a static method ...
My main goal is to call a function in JS passing as parameter (m.Body.ToString ()) which is the content of the message.
Can anyone help me?
Thank you for sharing your knowledge!
This is my code.
public void StartThread()
{
try
{
while (true)
{
PrepareQueue();
}
}
catch (Exception)
{ }
}
public static void PrepareQueue()
{
MessageQueue myQueue = new MessageQueue(".\\private$\\CTIQueue");
myQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(String) });
// Add an event handler for the ReceiveCompleted event.
myQueue.ReceiveCompleted += new ReceiveCompletedEventHandler(MyReceiveCompleted);
// Define wait handles for multiple operations.
WaitHandle[] waitHandleArray = new WaitHandle[10];
for (int i = 0; i < 10; i++)
{
// Begin asynchronous operations.
waitHandleArray[i] = myQueue.BeginReceive().AsyncWaitHandle;
}
// Specify to wait for all operations to return.
WaitHandle.WaitAll(waitHandleArray);
return;
}
private static void MyReceiveCompleted(Object source, ReceiveCompletedEventArgs asyncResult)
{
try
{
Thread.Sleep(2000);
MessageQueue mq = (MessageQueue)source;
// End the asynchronous receive operation.
System.Messaging.Message m = mq.EndReceive(asyncResult.AsyncResult);
ProcessMessage(m.Body.ToString()); <-- MY PROBLEM
}
catch (MessageQueueException)
{ }
return;
}
public void ProcessMessage(string message)
{
ScriptManager.RegisterStartupScript(this, GetType(), "popup", "NewCaller('" + message + "');", true);
}
Why not instantiate an object of the class and call ProcessMessage on it? Static methods can instantiate an object of the enclosing class and invoke instance methods on it.
private static void MyReceiveCompleted(Object source, ReceiveCompletedEventArgs asyncResult)
{
try
{
Thread.Sleep(2000);
MessageQueue mq = (MessageQueue)source;
// End the asynchronous receive operation.
System.Messaging.Message m = mq.EndReceive(asyncResult.AsyncResult);
new MyClass().ProcessMessage(m.Body.ToString()); <-- MY PROBLEM
}
catch (MessageQueueException)
{ }
return;
}
But if you are planning to invoke a client side code from server side, with reactive action happening at the server's end(which I think is your case) -- then I would prefer you use ASP.NET SignalR to signal the client that something interesting has happened at the server's end.

Synchronous responses to `Gdx.net.sendHttpRequest` in LibGDX

I'm making a small game in LibGDX. I'm saving the player's username locally as well as on a server. The problem is that the application is not waiting for the result of the call so the online database's ID is not saved locally. Here's the overall flow of the code:
//Create a new user object
User user = new User(name);
//Store the user in the online database
NetworkService networkService = new NetworkService();
String id = networkService.saveUser(user);
//Set the newly generated dbase ID on the local object
user.setId(id);
//Store the user locally
game.getUserService().persist(user);
in this code, the id variable is not getting set because the saveUser function is returning immediately. How can I make the application wait for the result of the network request so I can work with results from the server communication?
This is the code for saveUser:
public String saveUser(User user) {
Map<String, String> parameters = new HashMap<String, String>();
parameters.put("action", "save_user");
parameters.put("json", user.toJSON());
HttpRequest httpGet = new HttpRequest(HttpMethods.POST);
httpGet.setUrl("http://localhost:8080/provisioner");
httpGet.setContent(HttpParametersUtils.convertHttpParameters(parameters));
WerewolfsResponseListener responseListener = new WerewolfsResponseListener();
Gdx.net.sendHttpRequest (httpGet, responseListener);
return responseListener.getLastResponse();
}
This is the WerewolfsResponseListener class:
class WerewolfsResponseListener implements HttpResponseListener {
private String lastResponse = "";
public void handleHttpResponse(HttpResponse httpResponse) {
System.out.println(httpResponse.getResultAsString());
this.lastResponse = httpResponse.getResultAsString();
}
public void failed(Throwable t) {
System.out.println("Saving user failed: "+t.getMessage());
this.lastResponse = null;
}
public String getLastResponse() {
return lastResponse;
}
}
The asynchrony you are seeing is from Gdx.net.sendHttpRequest. The methods on the second parameter (your WerewolfsResponseListener) will be invoked whenever the request comes back. The success/failure methods will not be invoked "inline".
There are two basic approaches for dealing with callbacks structured like this: "polling" or "events".
With polling, your main game loop could "check" the responseListener to see if its succeeded or failed. (You would need to modify your current listener a bit to disambiguate the success case and the empty string.) Once you see a valid response, you can then do the user.setId() and such.
With "events" then you can just put the user.setId() call inside the responseListener callback, so it will be executed whenever the network responds. This is a bit more of a natural fit to the Libgdx net API. (It does mean your response listener will need a reference to the user object.)
It is not possible to "wait" inline for the network call to return. The Libgdx network API (correctly) assumes you do not want to block indefinitely in your render thread, so its not structured for that (the listener will be queued up as a Runnable, so the earliest it can run is on the next render call).
I would not recommend this to any human being, but if you need to test something in a quick and dirty fashion and absolutely must block, this will work. There's no timeout, so again, be prepared for absolute filth:
long wait = 10;
while(!listener.isDone())
{
Gdx.app.log("Net", "Waiting for response");
try
{
Thread.sleep(wait *= 2);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
public static class BlockingResponseListener implements HttpResponseListener
{
private String data;
private boolean done = false;
private boolean succeeded = false;
#Override
public void handleHttpResponse(HttpResponse httpResponse)
{
Gdx.app.log("Net", "response code was "+httpResponse.getStatus().getStatusCode());
data = httpResponse.getResultAsString();
succeeded = true;
done = true;
}
#Override
public void failed(Throwable t)
{
done = true;
succeeded = false;
Gdx.app.log("Net", "Failed due to exception ["+t.getMessage()+"]");
}
public boolean succeeded()
{
return succeeded;
}
public boolean isDone()
{
return done;
}
public String getData()
{
return data;
}
}

nhibernate session manager implementation

I am new to Nhibernate and slowing working my way thru learning it. I tried to implement a session manager class to help me get the session for my db calls. Below is the code for it. Can someone please say if this is architecturally correct and foresee any issue of scalability or performance?
public static class StaticSessionManager
{
private static ISession _session;
public static ISession GetCurrentSession()
{
if (_session == null)
OpenSession();
return _session;
}
private static void OpenSession()
{
_session = (new Configuration()).Configure().BuildSessionFactory().OpenSession();
}
public static void CloseSession()
{
if (_session != null)
{
_session.Close();
_session = null;
}
}
}
and in my data provider class, I use the following code to get data.
public class GenericDataProvider<T>
{
NHibernate.ISession _session;
public GenericDataProvider()
{
this._session = StaticSessionManager.GetCurrentSession();
}
public T GetById(object id)
{
using (ITransaction tx = _session.BeginTransaction())
{
try
{
T obj = _session.Get<T>(id);
tx.Commit();
return obj;
}
catch (Exception ex)
{
tx.Rollback();
StaticSessionManager.CloseSession();
throw ex;
}
}
}
}
and then
public class UserDataProvider : GenericDataProvider<User>
{
public User GetUserById(Guid uid)
{
return GetById(uid)
}
}
Final usage in Page
UserDataProvider udp = new UserDataProvider();
User u = udp.GetUserById(xxxxxx-xxx-xxx);
Is this something that is correct? Will instantiating lot of data providers in a single page cause issues?
I am also facing an issue right now, where if I do a same read operation from multiple machines at the same time, Nhibernate throws random errors- which I think is due to transactions.
Please advice.
From what I can see you are building the session factory if you have a null session. You should only call BuildSessionFactory() once when the application starts.
Where you do this is up to you, some people build the SessionFactory inside Global.asax in the method application_start or in your case have a static property for sessionFactory instead of session in your StaticSessionManager class.
I suspect your errors are due to the fact that your session factory is being built multiple times!
Another point is that some people open a transaction _session.BeginTransaction() at the beginning of each request and either commit or rollback at the end of each request. This gives you a unit of work which means you can lose the
using (ITransaction tx = _session.BeginTransaction())
{
...
}
on every method. All of this is open for debate but I use this method for 99% of all my code with no trouble at all.

Resources