Skip to content
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

Discussion: Full Stack Redux #313

Closed
wmertens opened this issue Jul 23, 2015 · 13 comments
Closed

Discussion: Full Stack Redux #313

wmertens opened this issue Jul 23, 2015 · 13 comments

Comments

@wmertens
Copy link
Contributor

Concept: Redux actions are sent to the web server, over some channel, likely a websocket. The server can also send actions to the browser.

  • How are actions sent to the server?
    • Middleware?
    • How to ensure delivery / how to handle failure?
  • How are actions from the server dispatched in the browser?
    • How to prevent loops?
  • Should sent actions be filtered or transformed?
  • What would the advantages be? When should it not be used?
  • How would it interact with undo/redo?
  • Can this replace REST-y Ajax calls?
  • Should the server run Redux as well?
    • how should the server state be persisted?
      • Can the state be a shim for a database?
@wmertens
Copy link
Contributor Author

Some possibilities:

  • Causing server-side changes
    • the browser sends an action, server handles it, dispatching actions to the browser as appropriate
      • No special client code needed for server connection, API is simply Redux
      • If server-side Redux, handling is a side-effect in a higher-order reducer
        • Redux on the server allows decoupling, scaling, retries, replay, undo/redo, etc just like CQRS/ES (very similar concepts)
    • When an action doesn't get an acknowledgement from the server in time, there could be a timeout action to notify the user, and the action is periodically retried.
      • actions should probably be handled in-order server-side, meaning a sequence number must be passed. Ordering could be made optional by also passing a required parent action id. Needs more thought.
    • While the browser is offline, server-destined actions can be queued
  • Keeping app state across browser sessions
    • server has to store actions and/or state snapshots
      • server-maintained state copy
        • browser sends state deltas
          • possibility to ignore part of the state
      • or server simply stores all actions
    • on browser connect, app state is restored
      • if actions are stored:
        • start from initial state or snapshot, replay actions
        • requires fully stateless app
        • requires replay mode which disables side effects like network access
      • otherwise simply load the state

A very similar architecture is what https://github.com/share/ShareJS uses to provide multi-user manipulation of shared state. There are probably important lessons and shareable code there. It would also be simple to embed ShareJS operations into actions for having a subtree of the state shared.

@sergey-lapin
Copy link

Maybe this issues are relevant in some way #211 #307
I implemented pretty raw syncing stores here, I will publish to npm soon.

@wmertens
Copy link
Contributor Author

  • Requesting server-side data
    • Browser sends data request action to server via middleware
    • Server responds with data action, gets dispatched by middleware
  • Redux only handles in-memory state, whereas a server's database is likely larger than available RAM. In that case the server will be using Redux to store state about the database accesses, not the data itself. One option would be to store promises and keep them for a while after resolution to serve as a read cache.
  • There may be multiple servers handling the client actions, which requires careful consideration of state. Luckily the separation between change events and queries makes it easier to reason about this, since there is an explicit understanding that currently stored state may not be up-to-date.
  • Depending on the use case, the server may only respond when spoken to. Then the interaction is very similar to REST calls, except that you're making the request be an object that is retryable. There is also no problem with API versioning, simply use a different constant.

Preliminary conclusions:

  • There is not one way to do this, so this will boil down to a bunch of patterns with some helpers in Redux. In particular:
    • a network middleware that takes care of sending and receiving actions in a queue, handling retries and notifying about network events
    • Some way to distinguish network-bound actions: a naming scheme? An attribute?
  • Server-side Redux seems like a useful pattern that requires further exploration. Pushing side-effects to the edges of the application makes for simpler and testable code.
  • The naive concept of sending all app actions to the server and vice versa, storing the same state in two places, does not seem useful.

@gaearon
Copy link
Contributor

gaearon commented Jul 26, 2015

The naive concept of sending all app actions to the server and vice versa, storing the same state in two places, does not seem useful.

I know @elierotenberg has done a lot of experimentation with this. See his work on Nexus Flux. Only the needed state should be synced.

@nsisodiya
Copy link

I wrote a detailed blog on Advantage of having Flux on WebWorker. Flux on Server or Webworker work exactly same. communication differs.

@nsisodiya
Copy link

I made my first implementation of "Flux inside Webworkers" using "Bridge API" - Bridge API can load your code into webworker - https://github.com/nsisodiya/bl-layer-loader . Its a Communication API. Bridge API load Flux inside Local UI thread for the Browsers which do not support WebWorkers.

@nsisodiya
Copy link

Bridge API has Two Adapter -

  1. Local
  2. postMessageAPI (Web workers)
    I am trying to write another adapter so can FLUX can work on Server using WebSocket.

@jokeyrhyme
Copy link

Could be related to the Netflix Falcor discussion: #560

@tiye
Copy link

tiye commented Aug 21, 2015

I started a project called Cumulo exploring similar ideas. The Web Servers are to maintain the store(like an in-memory database), all clients are synced with the server.

In Cumulo, an app is divided into some parts: Database, Store, View, Action.

  • View and Acton are like Flux
  • Database is like MongoDB server
  • Store is referring to the data Model in client like browsers.

The data flow is like:

Database --> Stores --> Views
   ^------ Actions ------/

Considering the networks it's like

Database --> Stores(Server) --> WebSocket --> Store(each Client) --> View
   ^--------- Actions --------- WebSocket <--------- Actions ---------/

I name the function from Database to Store expand. It's somehow like what React.render does with Store, but now with Database.

We already knew React is using diff/patch to keep View consistent to its store. And in Cumulo I'm trying to perform JSON diff/patch to keep Stores synced with Database. It's like saying:

Stores are DataViews rendered by Database, and updated with JSON patch, also, over the wire.

Cumulo is currently in very early stage, you may see here if interested: https://github.com/Cumulo
And some experiments at https://github.com/Cumulo/immutable-chat/tree/master/src/backend

By the way my current problems are dealing with database backend(raw JSON by now) and merge operation sequences in various orders(due to network delay), and diffing data could be slow(even on immutable data).

@gaearon
Copy link
Contributor

gaearon commented Sep 24, 2015

I'm closing this as inactive.
Please feel free to continue the discussion.
This is not currently on our radar, but I'm happy to see userland developments here.

@gaearon gaearon closed this as completed Sep 24, 2015
@wmertens
Copy link
Contributor Author

Yup, I'm working on a proposal of what a server would look like given a
message bus and the Redux architecture…

On Thu, Sep 24, 2015, 14:44 Dan Abramov [email protected] wrote:

I'm closing this as inactive.
Please feel free to continue the discussion.
This is not currently on our radar, but I'm happy to see userland
developments here.


Reply to this email directly or view it on GitHub
#313 (comment).

Wout.
(typed on mobile, excuse terseness)

@quirinpa
Copy link

I would love this from what i understand..

@wmertens
Copy link
Contributor Author

WiP: https://gist.github.com/wmertens/a408e15a08301081ebad but you get the idea

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants