-
Notifications
You must be signed in to change notification settings - Fork 145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add pause/resume feature to MBassador #122
Comments
I want this too! |
👍 Can we get some input from collaborators....? |
The interface looks good. But I am quite unsure about the implications for the existing implementation. I have the feeling that this feature would require a lot of changes in the core. Currently there is no awareness of running iterators. Can you outline the necessary changes that you see fit to support that feature? |
It's been a while since I've looked at this... but I just pushed the changes I had made to my remote fork. So you can take a look here: https://github.com/bgroenks96/mbassador/tree/add-event-bus-pause-resume |
Hi, I just took a quick look at the code you used to support the pause/resume feature. I don't have the time to make more specific comments but wouldn't it be easier to just swap in a queue that has no workers attached (pause()) and then switch back the old queue on resume(). You could drain the intermediate queue into the working queue while checking for the |
Are you referring to the 'pauseAsync' stuff or the code in AbstractPubSubPauseSupport? I haven't fully implemented and/or reviewed how this will work with async. I actually was hoping for your input on that xD |
I would suggest you have a look at the mbassador-spring repository. The entire extension is based on a decorator like pattern. Instead of extending the core, the transactional bus wraps the sync-async bus, adds additional methods and delegates existing ones (adding extra code where necessary). I would advice you to take the same approach. In your method delegates to publish / publishAsync you just check for the AtomicBoolean and either route messages to your intermediate queue or to the underlying bus' method. Whenever resume is triggered you drain the queue (until paused again or queue is empty). Depending on your usecase you might need separate queues for sync and async publication. But maybe you can go with one and drain its content just into the async queue of Mbassador. I hope I could make myself clear. |
How does this look? |
At first glance it looks fine. Good job! But I would change/add the constructor to consume a bus instance as parameter. This way it would be possible to write adapters that mix in various flavors. E.g. you could have a ResumableAndTransactionalBus(-Adapter) -- welcome to Spring Framework naming patterns :) I am also not sure about draining the queue using synchronous publish. This would make resume() a blocking call. Maybe it could be extended to have a boolean param to decide which publication method to use. Regarding unit tests: They should cover concurrent scenarios (use the helpers to spin up concurrent workloads) and then check invariants. One approach would be to have handlers that synchronize on the same monitor (another atomic boolean) that is set atomically together with the pause()/resume() of the bus. The handlers throw an exception in case they receive messages while being in paused state. |
Ok, I added another constructor and a new 'resumeAsync' method. How does that look? Now you just need unit tests? |
The implementation of publish() and publishAsync() violates the DRY principle and needs to be refactored. Have a go with unit tests and we will see how the code works, then. |
So would you prefer to just have something like I think I actually find having a separate |
@bennidi I think I have discovered several issues with taking the spring-like wrapper pattern you suggested:
In conclusion, I just don't think the wrapper/injection approach is going to work. Feel free to correct me if I have missed something, though. In the meantime, I am going to return to my original approach of injecting the Let me know what you think @bennidi. I'll keep working on unit tests in the meantime. |
Notes on resume() methods: PubSubPauseSupport.resume() takes a single parameter, an enum type FlushMode that determines the behavior or subsequent calls to pause while the queue flush is in progress. The default setting is FlushMode.ATOMIC, which will engage a lock that causes calls to 'pause()' to block until resume returns. FlushMode.NONATOMIC will cause 'resume()' to flush until either the queue is empty OR 'pause()' is called again. AsyncPubSubPauseSupport defines another enum PublishMode which differentiates between synchronous or asynchronous publishing of events on resume. The class is implemented by AbstractPauseSyncAsyncMessageBus (subclass of pre-existing AbstractSyncAsyncMessageBus) from which MBassador now inherits. Closes bennidi#122
@bgroenks96 Sorry for this long pause in communication. I had my priorities shifted to other projects. Looking at your commit I believe that you did a good job. Can you rebase that to the current master branch and make a new PR (I made small API changes that will also affect your code). Would be great if you could add a test that uses the different types of flush modes. I will profile the performance impact of your changes and have a look at the complete code base in my IDE. I won't promise that it makes it to the next release because I am very careful with additions to core but it looks promising and would be a great addition. |
Notes on resume() methods: PubSubPauseSupport.resume() takes a single parameter, an enum type FlushMode that determines the behavior or subsequent calls to pause while the queue flush is in progress. The default setting is FlushMode.ATOMIC, which will engage a lock that causes calls to 'pause()' to block until resume returns. FlushMode.NONATOMIC will cause 'resume()' to flush until either the queue is empty OR 'pause()' is called again. AsyncPubSubPauseSupport defines another enum PublishMode which differentiates between synchronous or asynchronous publishing of events on resume. The class is implemented by AbstractPauseSyncAsyncMessageBus (subclass of pre-existing AbstractSyncAsyncMessageBus) from which MBassador now inherits. Closes bennidi#122
Hi,
I've been working on a pull request to add a 'pause' and 'resume' feature to the message bus. Here are the methods from the new interface 'PubSubPauseSupport' with Javadoc comments to explain the concept:
This is especially useful in event-based applications that go through "transitions" i.e. a short period of time in which no Handler is able to receive events, yet it is problematic for inbound events to be completely lost. Being able to 'pause' the event publishing, queueing published events until it is resumed, solves this problem. There shouldn't be any performance cost on normal operation either.
The only thing that's tripping me up a bit is how to support
publishAsync
calls? ShouldAbstractSyncAsyncMessageBus
keep another queue separate from the normalBlockingQueue
or should that be the implementation's job?I would appreciate any feedback, and let me know if you want me to go ahead an push the pull request so you can see the rest of the changes.
The text was updated successfully, but these errors were encountered: