diff --git a/CHANGES.md b/CHANGES.md index 880ac19..95bf6d2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,12 @@ # Reductor Releases # +### Version 0.13.0 - January 2, 2017 + +#### New Module: ReductorObservable + +Added [ReductorObservable](https://github.com/Yarikx/reductor/tree/master/reductor-observable) module that mimics [redux-observable](https://github.com/redux-observable/redux-observable). +This allows to dispatch async actions and do side-effects in composable way using RxJava. + ### Version 0.12.0 - December 17, 2016 #### New feature: Dispatcher and Cursor diff --git a/build.gradle b/build.gradle index 3344ab1..6eb7c53 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,7 @@ buildscript { project.ext { bintrayUser = project.hasProperty('BINTRAY_USER') ? project.property('BINTRAY_USER') : "" bintrayKey = project.hasProperty('BINTRAY_KEY') ? project.property('BINTRAY_KEY') : "" - reductorVersion = '0.12.0' + reductorVersion = '0.13.0' } diff --git a/reductor-observable/README.md b/reductor-observable/README.md new file mode 100644 index 0000000..397b074 --- /dev/null +++ b/reductor-observable/README.md @@ -0,0 +1,45 @@ +# Reductor Observable + +Combine RxJava streams to dispatch async actions and handle side effects. + +### Epic + +The core primitive is `Epic`. Epic is defined as a simple interface: + +```java +public interface Epic { + Observable run(Observable actions, Store store); +} +``` + +Epic is run once `Store` is created. +It's basically a function that takes a stream of actions and returns stream of actions. +Each object emitted by returned Observable will be dispatched back to `Store`. + +A simple example of async flow is Ping-Pong Epic which listens for `PING` action and responds with `PONG` after one second. + +```java +Epic pingPongEpic = (actions, store) -> + actions.filter(Epics.ofType("PING")) + .delay(1, TimeUnit.SECONDS) + .map(action -> Action.create("PONG")); +``` + +Each 'PONG' message will be dispatched back to store to be handled by `Reducer`. + +### Creating Middleware + +To connect `Epic` to `Store`, create `EpicMiddleware` with provided epic. +Once middleware is created, it can be passed to `Store.create`: + +```java +EpicMiddleware middleware = EpicMiddleware.create(pingPongEpic); + +Store store = Store.create(reducer, middleware); +``` + +#### Combining epics + +EpicMiddleware takes only one rootEpic in `EpicMiddleware.create`. +However, you can combine more than one epics into single Epic by using `Epics.combineEpics(epics)`. +This will simply merge all returned streams into one. diff --git a/reductor-observable/build.gradle b/reductor-observable/build.gradle index c96dbaa..b771088 100644 --- a/reductor-observable/build.gradle +++ b/reductor-observable/build.gradle @@ -1,6 +1,6 @@ apply plugin: 'java' apply plugin: 'me.tatarka.retrolambda' -//apply from: '../gradle/publishing.gradle' +apply from: '../gradle/publishing.gradle' apply from: '../gradle/jacoco.gradle' dependencies { diff --git a/reductor-observable/src/main/java/com/yheriatovych/reductor/observable/Epic.java b/reductor-observable/src/main/java/com/yheriatovych/reductor/observable/Epic.java index fe3326d..0f75d2c 100644 --- a/reductor-observable/src/main/java/com/yheriatovych/reductor/observable/Epic.java +++ b/reductor-observable/src/main/java/com/yheriatovych/reductor/observable/Epic.java @@ -12,10 +12,10 @@ *

* Ping-Pong example: *


- * Epic pingPong = (actions, store) ->
+ * Epic<String> pingPong = (actions, store) ->
  *         actions.filter(Epics.ofType("PING"))
  *                 .delay(1, TimeUnit.SECONDS)
- *                 .map(action -> Action.create("PONG"));
+ *                 .map(action -> Action.create("PONG"));
  * 
* * @param state type of {@link Store} diff --git a/reductor-observable/src/test/java/com/yheriatovych/reductor/observable/EpicMiddlewareTest.java b/reductor-observable/src/test/java/com/yheriatovych/reductor/observable/EpicMiddlewareTest.java index 91bfc65..752db34 100644 --- a/reductor-observable/src/test/java/com/yheriatovych/reductor/observable/EpicMiddlewareTest.java +++ b/reductor-observable/src/test/java/com/yheriatovych/reductor/observable/EpicMiddlewareTest.java @@ -10,8 +10,6 @@ import rx.observers.TestSubscriber; import rx.subjects.PublishSubject; -import java.util.concurrent.TimeUnit; - import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.*; @@ -80,11 +78,4 @@ public void testUnsubscriptionEpic() { assertFalse("epic observable is unsubscibed after middleware.unsubscribe", epicObservable.hasObservers()); } - public void pingpong() { - Epic pingPong = (actions, store) -> - actions.filter(Epics.ofType("PING")) - .delay(1, TimeUnit.SECONDS) - .map(action -> Action.create("PONG")); - } - } \ No newline at end of file