3. Solving a basic problem
“Your valuable users don’t like waiting”
4. The Age of Asynchronous
Fact #1:
– HTTP request thread is critical path
– Do the barely necessary for fast rendering
– If it‟s long*, do it in a separate thread
5. The Age of Asynchronous
Fact #2:
– Creating new Threads needs caution
– Context switching hurts performances
– Concurrent programming is tricky*
6. The Age of Asynchronous
Fact #3:
– Burden on your application is never constant
– Scaling Up is a good start…
– …And Scaling Out is only next
7. Dilemma
So I have to use background threads ?
But using them might lead to issues and
headaches ?
And what if I really need to scale out ?
8. Reactive programming
• Adding a level of indirection :
Driving your application with Events
• Laziness is key
• Scale up/out by tweaking dispatching
9. The big picture
Events
Bus
Point to point
Service
Consumer
Service
Consumer
Service
Consumer
Service
Consumer
Service
Consumer
Application
14. The new deal
• New features. And quite a few.
– Streaming data, Selectors, Queue
• Based on a solid foundation – Reactor
– Where Platform-core Events best ideas have leaked
• Semantic changes
– But relatively easy migration path
15. So what Grails Events is about
• Grails Apps and Plugins can use Events to:
– Listen for plugins/app events
– Start simple with in-memory eventing
– Do Asynchronous calls (default)
– Increase in flexibility if required
18. Semantics: Consumer
• A Consumer:
– Accepts an Event
– Is registered in a Service or Events artifact, or by calling on()
– Can be thread safe
• Depending on the dispatcher type
• Assuming the consumer is not registered more than once
19. Semantics: Selector
• A Selector:
– Matches an event key
– Is paired with a consumer during its registration
20. Semantics: Reactor
• A Reactor:
– Is a dedicated Consumer Registry
– Has an assigned Dispatcher
– Uses a specific Event Router
• Usually, if the Dispatcher doesn‟t need to be adapted,
reuse the default reactor grailsReactor
21. Platform Core: Sending Events
def user = new User(params).save()
//non-blocking call, will trigger application listeners for this topic
event('mailRegistration', user)
//blocking call :
//event('mailRegistration', user).waitFor()
//can also be written like that
//event topic:'mailRegistration', data:user
//and if you need to reuse the current thread
//event topic:'mailRegistration', data:user, fork:false
render(view:'sendingRegistrationMail’)
22. Events: Sending Events
def user = new User(params).save()
//non-blocking call, will trigger application listeners for this topic
event('mailRegistration', user)
//Do things on each reply :
//event('mailRegistration', user){
if(it == ‘end’){
cancel()
}
}
//can also be written like that
//event key:'mailRegistration', data:user
render(view:'sendingRegistrationMail')
23. Platform Core Events : Consuming Events
class UserService{
//use method name 'mailRegistration' as topic name
//can also use custom topic name using topic arg: @Listener(topic='test')
@grails.events.Listener
def mailRegistration(User user){
sendMail{
to user.mail
subject "Confirmation"
html g.render(template:"userMailConfirmation")
}
}
//Can also receive an EventMessage to get more information on this particular event)
@grails.events.Listener(topic="mailRegistration")
def mailRegistration2(org.grails.plugin.platform.events.EventMessage msg){
sendMail{
to msg.data.mail
subject "Confirmation"
html g.render(template:"userMailConfirmation")
}
}
}
24. Events : Consuming Events
class UserService{
//use method name 'mailRegistration' as topic name
//can also use custom topic name using topic arg: @Selector(‘test')
@reactor.spring.annotation.Selector
def mailRegistration(User user){
sendMail{
to user.mail
subject "Confirmation"
html g.render(template:"userMailConfirmation")
}
}
//Can also receive an Event to get more information on this particular event)
@reactor.spring.annotation.Selector("mailRegistration")
def mailRegistration2(reactor.event.Event msg){
sendMail{
to msg.data.mail
subject "Confirmation"
html g.render(template:"userMailConfirmation")
}
}
}
28. Reactor awesomeness : Promise API
• Grails 2.3 Promises become a Reactor Promises
• Benefits from Dispatcher overriding
• Powerful once Combined with Consumers
29. Reactor awesomeness : Routing
• During event dispatching, consumers list is selected
• Publish Subscribe is the default
• Possible to assign different routing strategy
31. GORM events
• GORM is now an extension
– Using ext(‘gorm’, true) on any candidate reactor
– Applicable Selectors: simple topic form (beforeInsert...)
– A boolean reply is evaluated as a cancel directive
40. The Bad Stuff
• events-si : Events API on top of Spring Integration
– Not here (just) yet
• events-vertx : Abandoned experiment
– Working around Distributed Reactor
• Stream DSL could be optimized
– Reducing the number of objects
41. Roadmap
• events:
– Document, especially for Migration from Platform Core
– Stick with latest awesome features from Reactor
• Still Many API to expose: Processors, Buffer, TCP, Queues,
Sequencer…
• events-push -> events-atmosphere :
– More robust subscription mech
– Update atmosphere client
– Add support for replyTo
– Add support for binary
42. Roadmap
• events-sockjs:
– Involves Reactor work here
• events-si:
– Supports new events plugin
• events-xx:
– The plugin where you are the hero
43. Learn More. Stay Connected.
• Follow-up
– Reactor repository: http://github.com/reactor/
– Mail: @smaldini / smaldini@gopivotal.com
• Talk to us on Twitter: @springcentral
• Find Session replays on YouTube: spring.io/video
Editor's Notes
Challenge long* Long is sometimes ok or a necessary evil.