I am using bugsnag in a symfony 5 project to keep track of exeptions. I also use symfony messenger with rabbit for heavy processing.
Everything works fine overall, except the fact that in some cases, inside a messenger middleware (RejectRedeliveredMessageMiddleware) an exception is thrown in some particular cases in order to trigger a message reque while avoiding a possible infinite loop (RejectRedeliveredMessageException).
The exception should be there, and the behavior is correct. For example if a process stopped unexpectedly (a hard reboot or a kill), the message is requed. The logic works well, autorecovery works perfectly.
The only problem is that bugsnag registers itself as a subscriber for all kernel events, treated or not (code below)
$listeners = [
KernelEvents::REQUEST => ['onKernelRequest', 256],
KernelEvents::EXCEPTION => ['onKernelException', 128],
];
Normally exceptions are caught in our app before getting to the general event dispatcher and so they are not reported if they shouldn't. But, because that is in the middleware, and an event is risen it gets reported even though is already treated by the autoretry mechanism and because of that it generates a lot of noise and fake positives.
What I would need to do is unsubscribe for a particular event, but since I can't touch the 3rd party code (bugsnag and messenger) I can't find a way to do it.
Is there a way to programatically remove an event from a subscriber?
Inject EventDispatcherInterface and use removeSubscriber() method. You can do this in you custom middleware https://symfony.com/doc/current/messenger.html#middleware
It's hard to tell if this would work, but it's an angle - when you detect your Event is handled properly, you could invoke $event->stopPropagation(), perhaps from your own listener, which should: "... tell the dispatcher to stop all propagation of the event to future listeners (i.e. to not notify any more listeners)"
https://symfony.com/doc/current/components/event_dispatcher.html#stopping-event-flow-propagation
Related
I have came across a requirement where i want axon to wait untill all events in the eventbus fired against a particular Command finishes their execution. I will the brief the scenario:
I have a RestController which fires below command to create an application entity:
#RestController
class myController{
#PostMapping("/create")
#ResponseBody
public String create(
org.axonframework.commandhandling.gateway.CommandGateway.sendAndWait(new CreateApplicationCommand());
System.out.println(“in myController:: after sending CreateApplicationCommand”);
}
}
This command is being handled in the Aggregate, The Aggregate class is annotated with org.axonframework.spring.stereotype.Aggregate:
#Aggregate
class MyAggregate{
#CommandHandler //org.axonframework.commandhandling.CommandHandler
private MyAggregate(CreateApplicationCommand command) {
org.axonframework.modelling.command.AggregateLifecycle.apply(new AppCreatedEvent());
System.out.println(“in MyAggregate:: after firing AppCreatedEvent”);
}
#EventSourcingHandler //org.axonframework.eventsourcing.EventSourcingHandler
private void on(AppCreatedEvent appCreatedEvent) {
// Updates the state of the aggregate
this.id = appCreatedEvent.getId();
this.name = appCreatedEvent.getName();
System.out.println(“in MyAggregate:: after updating state”);
}
}
The AppCreatedEvent is handled at 2 places:
In the Aggregate itself, as we can see above.
In the projection class as below:
#EventHandler //org.axonframework.eventhandling.EventHandler
void on(AppCreatedEvent appCreatedEvent){
// persists into database
System.out.println(“in Projection:: after saving into database”);
}
The problem here is after catching the event at first place(i.e., inside aggregate) the call gets returned to myController.
i.e. The output here is:
in MyAggregate:: after firing AppCreatedEvent
in MyAggregate:: after updating state
in myController:: after sending CreateApplicationCommand
in Projection:: after saving into database
The output which i want is:
in MyAggregate:: after firing AppCreatedEvent
in MyAggregate:: after updating state
in Projection:: after saving into database
in myController:: after sending CreateApplicationCommand
In simple words, i want axon to wait untill all events triggered against a particular command are executed completely and then return to the class which triggered the command.
After searching on the forum i got to know that all sendAndWait does is wait until the handling of the command and publication of the events is finalized, and then i tired with Reactor Extension as well using below but got same results: org.axonframework.extensions.reactor.commandhandling.gateway.ReactorCommandGateway.send(new CreateApplicationCommand()).block();
Can someone please help me out.
Thanks in advance.
What would be best in your situation, #rohit, is to embrace the fact you are using an eventually consistent solution here. Thus, Command Handling is entirely separate from Event Handling, making the Query Models you create eventually consistent with the Command Model (your aggregates). Therefore, you wouldn't necessarily wait for the events exactly but react when the Query Model is present.
Embracing this comes down to building your application such that "yeah, I know my response might not be up to date now, but it might be somewhere in the near future." It is thus recommended to subscribe to the result you are interested in after or before the fact you have dispatched a command.
For example, you could see this as using WebSockets with the STOMP protocol, or you could tap into Project Reactor and use the Flux result type to receive the results as they go.
From your description, I assume you or your business have decided that the UI component should react in the (old-fashioned) synchronous way. There's nothing wrong with that, but it will bite your *ss when it comes to using something inherently eventually consistent like CQRS. You can, however, spoof the fact you are synchronous in your front-end, if you will.
To achieve this, I would recommend using Axon's Subscription Query to subscribe to the query model you know will be updated by the command you will send.
In pseudo-code, that would look a little bit like this:
public Result mySynchronousCall(String identifier) {
// Subscribe to the updates to come
SubscriptionQueryResult<Result> result = QueryGateway.subscriptionQuery(...);
// Issue command to update
CommandGateway.send(...);
// Wait on the Flux for the first result, and then close it
return result.updates()
.next()
.map(...)
.timeout(...)
.doFinally(it -> result.close());
}
You could see this being done in this sample WebFluxRest class, by the way.
Note that you are essentially closing the door to the front-end to tap into the asynchronous goodness by doing this. It'll work and allow you to wait for the result to be there as soon as it is there, but you'll lose some flexibility.
I cant seem to get this working properly.
I've got two ViewModels. VM1 registers a message with the following code
Messenger.Default.Register<PropertyChangedMessage<int>>(
this,
(action) => DispatcherHelper.CheckBeginInvokeOnUI(() => UpdateOverlayIcon(action.NewValue))
);
VM2 fires the RaisePropertyChanged when property is being set.
// Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
RaisePropertyChanged(UnreadTweetsPropertyName, oldValue, value, true);
Now, shouldn't the VM1.UpdateOverlayIcon() method run right after the RaisePropertyChanged is fired in VM2? Or have i missed an essential part of this, because it doesn't work for me? I have been struggling with this all day long and tried a number of different methods.
This should work quite easily - just make sure that the Message Register code is being registered before the RaisePropertyChanged notification is called.
The other thing to check is that your types match - so you are listening for a Message with INT - is this the type of UnreadTweetsPropertyName? (it wont receive it if they dont match).
The problem with this approach is that ANY int property that is broadcasting will be received... I would like to be able to pass in a token so that I can match them up...
I am using MVVM Light and am using Messages to communicate between ViewModels to let a ViewModel know when it is ok to execute something. My problem is that I register for a message and then it receives it multiple times. so to keep from my program executing something more than once I have to create boolean flags to see if it has already been recieved. Any idea why it does this and how I can stop it?
Make sure you unregister your message handlers once you do not need them anymore. The Messenger keeps a reference to the registered methods and this prevents them from being garbage collected.
Therefore, for ViewModels: make sure that you call Cleanup once you done (or implement IDisposable and call Cleanup from there).
For Views (Controls, Windows, or similar) call Messenger.Unregister in an event that occurs on the teardown of the view, e.g. the Unloaded event.
This is a known behaviour of the MVVM and has been discussed in several places.
Very old question but I solved the problem by doing this:
static bool isRegistered = false;
and then, in the constructor:
if( !isRegistered )
{
Messenger.Default.Register<MyMessage>(this, OnMessageReceived);
isRegisterd = true;
}
I have seen this issue before. It had to do with the Messenger.Default.Register being called more than once. The MVVMLight Messenger class will register the same item 'x' number of times. This is why when you call the Send you get it many times.
Anyone know how to prevent MVVMLight from registering multiple times?
really old but thought I would answer just in case somebody needs it. I was fairly new to silverlight at the time and the issue ended up being a memory leak as the viewModel, which had multiple instances, was still in memory.
As other contributors mentioned, the same message is being registered multiple times. I have noticed this behavior taking place while navigating to View X then navigating back to View Z where the message is registered in the constructor of the Z ViewModel. One solution is to set the NavigationCacheMode property to Required
<Page
........
........
NavigationCacheMode="Required">
I need to call FileReference.save() after a web service call has completed, but this method has a restriction: "In Flash Player, you can only call this method successfully in response to a user event (for example, in an event handler for a mouse click or keypress event). Otherwise, calling this method results in Flash Player throwing an Error exception." (from the documentation here)
This restriction is a bit vague. Does it mean that I can only call the FileReference.save() method from within an event handler function that is registered as a listener for certain types of user events? If so then exactly which user events are valid? (Perhaps there's an event that will never be dispatched by user interaction with my application and I could register an event handler function for that event type and make the save() call from within that function?)
My difficulty is that I can't safely call the FileReference.save() method until my web service returns with the data that will be used as the argument of the FileReference.save() method call, so the event that triggers the FileReference.save() call is actually a ResultEvent rather than a user event, and I'm leery of dispatching a new (faux) user event type in order to be able to trigger the FileReference.save() call unless it's definitely a user event that would never be dispatched as a result of actual user interaction with my application.
In a nutshell what I'm doing now is this: I have a function that is registered as a handler for a button click. In this function I make my web service call to fetch data from the server. I also have a result handler function which gets invoked when the web service call completes, and it's in here that I want to call the FileReference.save() method since it's at this point that I know that the data is ready to be saved to a file. But the aforementioned restriction is blocking me from doing this -- I get an error:
Error #2176: Certain actions, such as those that display a pop-up window,
may only be invoked upon user interaction, for example by a mouse click
or button press.
I've tried many things to get around this such as creating a second mouse click event handler function with the FileReference.save() call within and calling it after a timeout interval (to give the web service time to complete), but I keep running into the same error -- maybe that approach doesn't work since the second function isn't registered as an event listener for the event type used as its argument.
I'm new to Flex development so perhaps I'm just not thinking about this in the right way. If anyone can suggest another approach I'd really appreciate it. Thanks in advance for your comments or suggestions.
--James
Adobe does this as a sort of security measure to ensure users are the ones messing with files rather than potentially harmful code. My understanding is that they enforce this by only allowing handlers of (click?) events that originate from UI components to execute the FileReference methods, so generating your own events programmatically will not work, although I have not tried to verify this. Unfortunately the best resolution I've found is to re-work the UI a bit to conform to this constraint. In your particular situation, you could make this a two click process with a button that says something like "Prepare Download", which changes to "Download File" after the web service is complete. This is less than ideal from a user perspective, but I don't think there's much else that can be done unless you can somehow complete your web service call prior to displaying the button that triggers the FileReference.save() call.
After struggling for that for well, a couple hours I found a workaround: you can use both mouseDown AND mouseUp events instead of just click.
For instance:
s:Button
mouseDown="prepare_PDF()"
mouseUp="save_PDF()"
Works fine for me!
Happy coding!
--Thomas
As a workaround I used the ExternalInterface class. I created a javascript function with this code
function downloadFile (url) {
window.open(url);
}
An in AS3 I call
var url = 'www.example.com/downloadfile.php?file_id=xxx';
ExternalInterface.call('downloadAttachmentFile', url);
So with that I transfer the file handling to JS/HTML.
This is a comment on Thomas' answer (I don't have enough XP to comment yet): The mousedown and mouseup workaround works nicely. Just a note that if you make any changes in prepare_PDF() that need 'undoing' in save_PDF(), then its a good idea to call that code on the mouseout event as well, since there might be a case that the user mousedown's on the button, but then moves the mouse away from the button.
This was particularly relevant for my case, in which we increase the size of a watermark on an image when the user clicks the download button (that triggers the .save() call). I reduce the size of the watermark down to normal on the mousedown and mouseout events.
I had this same issue, I chose to use flash.net methods. Call flash.net.navigateToURL(url); from an actionscript or navigateToURL(url); from mxml.
What i do to solve this is to show an alert message with an anonymous function so i don't have to create a button.
Alert.show("Do you wish to download the file?", "Confirm", Alert.OK | Alert.CANCEL, this, function (eventObj:CloseEvent):void {
if (eventObj.detail == Alert.OK) {
fileReference.save(zipOut.byteArray, dateFormater_titulo.format(new Date ()) + ".zip");
}//if
}/*function*/, null, Alert.OK);
There's a few questions on stack overflow on this topic but I'm still unclear:
I know the flash engine is single threaded so when it receives an event, does it essentially break off, execute any registered event listeners (in no guaranteed order) then return to the current scope?
If I have this code:
addListener("stuff", function():void {
// some stuff
});
addListener("stuff", someFunc);
dispatch(new Event("stuff"));
trace("Done.");
I want to know:
Can I guarantee that both listeners have executed by the time I reach the trace("Done"); line?
edit:
or
can I guarantee that the current function will complete before any of the event listeners execute? ie trace("Done"); will ALWAYS execute first.
or
Neither.
It is guaranteed that both event handlers will be called before trace because user code generated events are synchronous:
Does dispatching an event interrupt a function?
From what I know, when you dispatch an event it gets added to the event queue, but won't actually run until the currently-executing event finishes. In other words, you'll trace "Done.", then your function ends, control passes back to the event handler, and only then does it (maybe) start executing one of your events.
Yes, you can guarantee both assertions in this exact situation.
Meaning, that if adding your event listeners and dispatching your event is in the same code block it will happen in sequence. However, from a practical POV that's completely useless.
#kryoko: player events get precedence over user events, but they do not 'force' themselves through. Meaning that if user code is running, the player event handling is suspended. That's why it's possible to 'freeze' a flash movie with heavy, intensive code. (Or with a simple infinite loop, of course)