-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
ca8b3cc
commit 42b2c1d
Showing
17 changed files
with
322 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -73,6 +73,6 @@ class RxEventBusSpec extends Specification { | |
} | ||
|
||
expect: | ||
result == null | ||
result instanceof Throwable | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
dependencies { | ||
compile project(":grails-events") | ||
compile 'io.reactivex.rxjava2:rxjava:2.0.7' | ||
} |
22 changes: 22 additions & 0 deletions
22
grails-events-rxjava2/src/main/groovy/org/grails/async/events/rxjava2/EventWithReply.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package org.grails.async.events.rxjava2 | ||
|
||
|
||
import grails.async.events.Event | ||
import groovy.transform.CompileStatic | ||
|
||
/** | ||
* An event with a reply | ||
* | ||
* @since 3.3 | ||
* @author Graeme Rocher | ||
*/ | ||
@CompileStatic | ||
class EventWithReply { | ||
final Event event | ||
final Closure reply | ||
|
||
EventWithReply(Event event, Closure reply) { | ||
this.event = event | ||
this.reply = reply | ||
} | ||
} |
146 changes: 146 additions & 0 deletions
146
grails-events-rxjava2/src/main/groovy/org/grails/async/events/rxjava2/RxEventBus.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
package org.grails.async.events.rxjava2 | ||
|
||
import grails.async.events.Event | ||
import grails.async.events.emitter.EventEmitter | ||
import grails.async.events.registry.EventRegistry | ||
import grails.async.events.registry.Subscription | ||
import groovy.transform.CompileDynamic | ||
import groovy.transform.CompileStatic | ||
import groovy.util.logging.Slf4j | ||
import io.reactivex.Scheduler | ||
import io.reactivex.disposables.Disposable | ||
import io.reactivex.functions.Consumer | ||
import io.reactivex.schedulers.Schedulers | ||
import io.reactivex.subjects.PublishSubject | ||
import org.grails.async.events.bus.AbstractEventBus | ||
|
||
import java.util.concurrent.ConcurrentHashMap | ||
import java.util.concurrent.ConcurrentLinkedQueue | ||
|
||
/** | ||
* An EventBus implementation that uses RxJava | ||
* | ||
* @author Graeme Rocher | ||
* @since 3.3 | ||
* | ||
*/ | ||
@CompileStatic | ||
@Slf4j | ||
class RxEventBus extends AbstractEventBus { | ||
protected final Map<CharSequence, PublishSubject> subjects = new ConcurrentHashMap<CharSequence, PublishSubject>().withDefault { | ||
PublishSubject.create() | ||
} | ||
protected final Map<CharSequence, Collection<Disposable>> subscriptions = new ConcurrentHashMap<CharSequence, Collection<Disposable>>().withDefault { | ||
new ConcurrentLinkedQueue<Disposable>() | ||
} | ||
|
||
|
||
final Scheduler scheduler | ||
|
||
RxEventBus(Scheduler scheduler = Schedulers.io()) { | ||
this.scheduler = scheduler | ||
} | ||
|
||
@Override | ||
Subscription on(CharSequence event, Closure listener) { | ||
String eventKey = event.toString() | ||
int argCount = listener.parameterTypes?.length ?: 1 | ||
Disposable sub = subjects.get(eventKey) | ||
.observeOn(scheduler) | ||
.subscribe( { data -> | ||
|
||
Closure reply = null | ||
if(data instanceof EventWithReply) { | ||
def eventWithReply = (EventWithReply) data | ||
data = eventWithReply.event.data | ||
reply = eventWithReply.reply | ||
} | ||
|
||
try { | ||
def result | ||
if(data.getClass().isArray() && argCount == ((Object[])data).length) { | ||
result = invokeListener(listener, data) | ||
} | ||
else { | ||
result = listener.call(data) | ||
} | ||
if(reply != null) { | ||
reply.call(result) | ||
} | ||
} catch (Throwable e) { | ||
if(reply != null && reply.parameterTypes && reply.parameterTypes[0].isInstance(e)) { | ||
reply.call(e) | ||
} | ||
else { | ||
throw e | ||
} | ||
} | ||
|
||
} as Consumer, { Throwable t -> | ||
log.error("Error occurred triggering event listener for event [$event]: ${t.message}", t) | ||
} as Consumer<Throwable>) | ||
Collection<Disposable> subs = subscriptions.get(eventKey) | ||
subs.add(sub) | ||
return new RxSubscription(sub, subs) | ||
} | ||
|
||
@CompileDynamic | ||
protected Object invokeListener(Closure listener, data) { | ||
listener.call(*data) | ||
} | ||
|
||
@Override | ||
EventRegistry unsubscribeAll(CharSequence event) { | ||
String eventKey = event.toString() | ||
Collection<Disposable> subs = subscriptions.get(eventKey) | ||
for(sub in subs) { | ||
if(!sub.isDisposed()) { | ||
sub.dispose() | ||
} | ||
} | ||
subs.clear() | ||
return this | ||
} | ||
|
||
@Override | ||
EventEmitter notify(Event event) { | ||
PublishSubject sub = subjects.get(event.id) | ||
if(sub.hasObservers() && !sub.hasComplete()) { | ||
sub.onNext(event.data) | ||
} | ||
return this | ||
} | ||
|
||
@Override | ||
EventEmitter sendAndReceive(Event event, Closure reply) { | ||
PublishSubject sub = subjects.get(event.id) | ||
if(sub.hasObservers() && !sub.hasComplete()) { | ||
sub.onNext(new EventWithReply(event, reply)) | ||
} | ||
return this | ||
} | ||
|
||
private static class RxSubscription implements Subscription { | ||
final Disposable subscription | ||
final Collection<Disposable> subscriptions | ||
|
||
RxSubscription(Disposable subscription, Collection<Disposable> subscriptions) { | ||
this.subscription = subscription | ||
this.subscriptions = subscriptions | ||
} | ||
|
||
@Override | ||
Subscription cancel() { | ||
if(!subscription.isDisposed()) { | ||
subscription.dispose() | ||
} | ||
subscriptions.remove(subscription) | ||
return this | ||
} | ||
|
||
@Override | ||
boolean isCancelled() { | ||
return subscription.isDisposed() | ||
} | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
grails-events-rxjava2/src/main/resources/META-INF/services/grails.async.events.bus.EventBus
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
org.grails.async.events.rxjava2.RxEventBus |
77 changes: 77 additions & 0 deletions
77
grails-events-rxjava2/src/test/groovy/org/grails/async/events/rxjava2/RxEventBusSpec.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
package org.grails.async.events.rxjava2 | ||
|
||
import io.reactivex.schedulers.Schedulers | ||
import spock.lang.Specification | ||
|
||
/** | ||
* Created by graemerocher on 27/03/2017. | ||
*/ | ||
class RxEventBusSpec extends Specification { | ||
void 'test rx event bus single arg'() { | ||
given: | ||
RxEventBus eventBus = new RxEventBus(Schedulers.trampoline()) | ||
def result | ||
eventBus.on("test") { | ||
result = "foo $it" | ||
} | ||
eventBus.notify("test", "bar") | ||
|
||
expect: | ||
result == 'foo bar' | ||
} | ||
|
||
void 'test rx event bus multiple args'() { | ||
given: | ||
RxEventBus eventBus = new RxEventBus(Schedulers.trampoline()) | ||
def result | ||
eventBus.on("test") { | ||
result = "foo $it" | ||
} | ||
eventBus.notify("test", "bar", "baz") | ||
|
||
expect: | ||
result == 'foo [bar, baz]' | ||
} | ||
|
||
void 'test rx event bus multiple args listener'() { | ||
given: | ||
RxEventBus eventBus = new RxEventBus(Schedulers.trampoline()) | ||
def result | ||
eventBus.on("test") { String one, String two -> | ||
result = "foo $one $two" | ||
} | ||
eventBus.notify("test", "bar", "baz") | ||
|
||
expect: | ||
result == 'foo bar baz' | ||
} | ||
|
||
void 'test rx event bus send and receive'() { | ||
given: | ||
RxEventBus eventBus = new RxEventBus(Schedulers.trampoline()) | ||
def result | ||
eventBus.on("test") { String data -> | ||
"foo $data" | ||
} | ||
eventBus.sendAndReceive("test", "bar") { | ||
result = it | ||
} | ||
expect: | ||
result == 'foo bar' | ||
} | ||
|
||
void 'test rx event bus error handling'() { | ||
given: | ||
RxEventBus eventBus = new RxEventBus(Schedulers.trampoline()) | ||
def result | ||
eventBus.on("test") { String data -> | ||
throw new RuntimeException("bad") | ||
} | ||
eventBus.sendAndReceive("test", "bar") { | ||
result = it | ||
} | ||
|
||
expect: | ||
result instanceof Throwable | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 0 additions & 1 deletion
1
grails-events-spring/src/main/resources/META-INF/services/grails.async.events.bus.EventBus
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.