Giter Site home page Giter Site logo

groupon / grox Goto Github PK

View Code? Open in Web Editor NEW
339.0 23.0 18.0 6.33 MB

Grox helps to maintain the state of Java / Android apps.

License: Apache License 2.0

XSLT 18.33% Shell 4.69% Java 76.98%
java android state-management rxjava rxjava-android rxjava2 redux flux cyclejs groupon

grox's People

Contributors

alin-turcu avatar code-twister avatar gracefulife avatar saguinav avatar stephanenicolas avatar wongcain avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

grox's Issues

Add full License

The license file we use is the short header for source files.
We should also have a long license which won't be checked by the license plugin.

core-rx and core-rx2 have class name collision when used in same project

Surprising as it may sound, I have a project with RxJava1/Grox Rx1 in one module, and RxJava2/Grox Rx2 in another. They work fine on their own, but when bringing them together, there's a collision as grox-core-rx and grox-core-rx2 use the same package and class name.

Most libraries solve this evolution problem by namespacing the Rx related classes under rx1 or rx2. Would this be something Grox would be willing to support?

Change the sample to use concat instead of startWith

There is a subtle problem in your use of startWith() in LoginCommand.java: you use startWith() on the io() scheduler: that means, that the LogInProgressAction will not be emitted right away: so when you use this initial state to disable the login button, there is a possibility that the user presses the button twice.

So we should use concat:

Observable
  .just(LogInProgressAction)
  .concatWith( loginApiClient
    …
  )

StateChangeListener being called after unsubscribing [concurrency]

onStateChanged method from a StateChangeListener can be called after it has unsubscribe d.

Steps:

  1. We have a Store S and Listener L.
  2. In Thread 1, S starts notifying listeners using NotifySubscribersMiddleware .
  3. CopyOnWriteArrayList is used to keep the listeners. Therefore, we iterate using a copy of the list that won't be changed during the iterator loop.
  4. In Thread 2, L calls unsubscribe to unsubscribe from the Store S. This happens before step 3 is over and L is notified.
  5. S notifies L calling onStateChanged, even thought it is already unsubscribed.

The scenario looks difficult to reproduce, however the consequences can be fatal.

State modification is visible too early to subscribers

if there are 2 subscribers (S0 & S1), and S0 modifies the state of the store in its RxChain, then S1 will see the state after modification by S1.

It shouldn't be llike this.
--> S0 & S1 should both see the original state and they both see the modified state after.

Grox doesn't notify anyone when an action produces an error when trying to change the state

Grox store don't call any listener / "subscriber of the states(store)" when an error happens during the action's newState method. The errors seem to just be swallowed by Grox.

Here is an example stackTrace:

at com.groupon.newdealdetails.local.grox.RefreshDealAction.newState(RefreshDealAction.java:47)
                                                                      at com.groupon.newdealdetails.local.grox.RefreshDealAction.newState(RefreshDealAction.java:16)
                                                                      at com.groupon.grox.Store$CallReducerMiddleware.intercept(Store.java:186)
                                                                      at com.groupon.grox.RealMiddlewareChain.proceed(RealMiddlewareChain.java:76)
                                                                      at com.groupon.misc.DebugMiddlewareChain.logStateAndAction(DebugMiddlewareChain.java:44)
                                                                      at com.groupon.misc.DebugMiddlewareChain.intercept(DebugMiddlewareChain.java:31)
                                                                      at com.groupon.grox.RealMiddlewareChain.proceed(RealMiddlewareChain.java:76)
                                                                      at com.groupon.grox.Store$NotifySubscribersMiddleware.intercept(Store.java:198)
                                                                      at com.groupon.grox.RealMiddlewareChain.proceed(RealMiddlewareChain.java:76)
                                                                      at com.groupon.grox.Store.emitSequentially(Store.java:86)
                                                                      at com.groupon.grox.Store.dispatch(Store.java:79)
                                                                      at com.groupon.newdealdetails.local.LocalDealDetailsFragment$$Lambda$10.call(Unknown Source:4)
                                                                      at rx.internal.util.ActionSubscriber.onNext(ActionSubscriber.java:39)
                                                                      at rx.observers.SafeSubscriber.onNext(SafeSubscriber.java:134)
                                                                      at rx.internal.operators.OnSubscribeOnAssembly$OnAssemblySubscriber.onNext(OnSubscribeOnAssembly.java:124)
                                                                      at rx.observers.SerializedObserver.onNext(SerializedObserver.java:91)
                                                                      at rx.observers.SerializedSubscriber.onNext(SerializedSubscriber.java:94)
                                                                      at rx.internal.operators.OnSubscribeConcatMap$ConcatMapSubscriber.innerNext(OnSubscribeConcatMap.java:182)
                                                                      at rx.internal.operators.OnSubscribeConcatMap$ConcatMapInnerSubscriber.onNext(OnSubscribeConcatMap.java:335)
                                                                      at rx.internal.operators.OnSubscribeOnAssembly$OnAssemblySubscriber.onNext(OnSubscribeOnAssembly.java:124)
                                                                      at rx.internal.producers.SingleProducer.request(SingleProducer.java:65)
                                                                      at rx.internal.producers.ProducerArbiter.setProducer(ProducerArbiter.java:126)
                                                                      at rx.internal.operators.OnSubscribeConcatMap$ConcatMapInnerSubscriber.setProducer(OnSubscribeConcatMap.java:329)
                                                                      at rx.Subscriber.setProducer(Subscriber.java:205)
                                                                      at rx.internal.operators.SingleLiftObservableOperator$WrapSubscriberIntoSingle.onSuccess(SingleLiftObservableOperator.java:76)
                                                                      at rx.internal.operators.OnSubscribeOnAssemblySingle$OnAssemblySingleSubscriber.onSuccess(OnSubscribeOnAssemblySingle.java:70)
                                                                      at rx.internal.operators.SingleOnErrorReturn$OnErrorReturnsSingleSubscriber.onSuccess(SingleOnErrorReturn.java:61)
                                                                      at rx.internal.operators.OnSubscribeOnAssemblySingle$OnAssemblySingleSubscriber.onSuccess(OnSubscribeOnAssemblySingle.java:70)
                                                                      at rx.internal.operators.SingleOnSubscribeMap$MapSubscriber.onSuccess(SingleOnSubscribeMap.java:74)
                                                                      at rx.internal.operators.OnSubscribeOnAssemblySingle$OnAssemblySingleSubscriber.onSuccess(OnSubscribeOnAssemblySingle.java:70)
                                                                      at rx.internal.operators.SingleDoOnEvent$SingleDoOnEventSubscriber.onSuccess(SingleDoOnEvent.java:63)
                                                                      at rx.internal.operators.OnSubscribeOnAssemblySingle$OnAssemblySingleSubscriber.onSuccess(OnSubscribeOnAssemblySingle.java:70)
                                                                      at rx.Single$13$1$1.onSuccess(Single.java:2021)
                                                                      at rx.internal.operators.OnSubscribeOnAssemblySingle$OnAssemblySingleSubscriber.onSuccess(OnSubscribeOnAssemblySingle.java:70)
                                                                      at rx.internal.operators.SingleFromCallable.call(SingleFromCallable.java:48)
                                                                      at rx.internal.operators.SingleFromCallable.call(SingleFromCallable.java:29)
                                                                      at rx.internal.operators.OnSubscribeOnAssemblySingle.call(OnSubscribeOnAssemblySingle.java:47)
                                                                      at rx.internal.operators.OnSubscribeOnAssemblySingle.call(OnSubscribeOnAssemblySingle.java:28)
                                                                      at rx.Single.subscribe(Single.java:1967)
                                                                      at rx.Single$13$1.call(Single.java:2039)
                                                                      at rx.internal.schedulers.CachedThreadScheduler$EventLoopWorker$1.call(CachedThreadScheduler.java:230)
                                                                      at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
                                                                      at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:457)
                                                                        at java.util.concurrent.Futu

Generic Commands?

I am curious why Command does not make use of generics like Action does. Wouldn't it be better to define Command like this?

public interface Command<STATE> {
  Observable<? extends Action<STATE> actions();
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.