For this kind of tasks I usually create a private Firefox extension which gives me access to extended browser capabilities and the ability to lift some security-related restrictions. I run it in a sandboxed browser, much like I would do with something like Selenium or Puppeter, but I have much more options to hand-tune the automation.
HN user
elierotenberg
It reminds me of a lightning talk I gave at ReactConf some time ago :)
Basically forward-shuffling the component tree to produce HTML that will be really hard to match using CSS Selectors usually found in adblockers and other DOM-targeting scripts.
It seems like monotonicity (or a subset, stronger monotinicity, still covering many practical use cases) can be statically enforced in an algrebraic type system. With some generics magic you can encode monotonicity as a type assertion on (optionally asynchronous) function calls mapping an underlying transport/RPC mechanism (REST over HTTP, RPC over Websocket, custom protocol over TCP/domain socket...).
In TypeScript for example you can strongly type your communication protocol (web requests/reponses, websockets, parent/worker ipc, etc) and get some guarantees at compile time. For example, you can guarantee that your state updates over the wire are eventually consistent.
The same goes of course for other algebraic type systems by encoding monotonicity in the form of static type assertions (Flow, Caml, Haskell...).
Is React Resolver related to React Nexus[1]?
One really useful pattern is React higher-order components, eg. https://github.com/elierotenberg/react-nexus#componentgetnex...
The pattern is
function decorate(params) {
return (Component) => class extends React.Component {
... // some code using params
render() {
return <Component {...this.props} />
}
};
}
my2c.This benchmark is indeed very interesting.
I think I may have failed to express my point, though. I'm not building a message queue, as it is certainly a very hard problem that has been engineered for years by people way smarter than me :) I'm merely leveraging the goodness of their implementations (in my case redis, but RabbitMQ is also an option I've considered explicitly in my post).
The chat is a contrived example to show that even under high load, full-scale flux over the wire is a reasonable option. As for "any kind of serious load", well, maybe my example fails to meet the requirements, but unless I'm building Facebook, I think I've faced something serious enough to be able to think about my next step.
Oh, you're absolutely right, 10M/s is a mistake, which I've corrected.
Few remarks though:
- it's still way below the number of actions we're talking about here (~100k/s)
- since redis is only used as a generic MQ and not as a store, it can be sharded at the app level without the pain usually associated with redis clustering
- I've deployed a similar (but less performant) design for the player of a gaming website, which is in use in production for more than a year, and works like a charm (we're talking ~5-50k users per channel on a daily basis). This is definitely a "second-system" pattern, but I try to avoid the associated pitfalls :)
I'd be genuinely interested by your feedback!
Actually this whole stack is designed with SSR in mind, see the related package react-nexus (which I will soon blog about, too!) :)
Unless you need to handle a very small number of concurrent connections, using 1 process per connection seems to be a huge overhead, although I can think of some use cases.
However, I can imagine a similar tool doing multi/demultiplexing, eg the handler process would take input text lines prepended with a connection identifier (eg. "$socketID $message") and output using a similar formatting. Pretty much like websocketd but with multiplexing and unixy/pipe-friendly (eg. you can apply grep/awk/etc before and after).
How would this fit compared to websocketd?
Thanks for your feedback. Several other comments point in the same direction: automatic (or assisted) handling of optimistic updates. I think this is actually relatively easy, since there are clear hooks in the Nexus Flux API to implement dispatch-time and update-time behaviour, but I will definitely provide an example, or even better, an implementation of this that just works out of the box.
Its shouldJS. An assertion lib with a fun chainable DSL. Basically whatever.should.predicate desugars to assert(predicate(whatever)). See https://github.com/shouldjs/should.js :)
Native (mutable) Maps and Weakmaps are coming up with ES6, and are already (mostly) polyfilled by things like core.js.
Immutable provides (immutable) implementations of Map, OrderedMap, Set, etc. See http://facebook.github.io/immutable-js/ :)
That was nearly exactly my initial approach! :)
However I realized actual diffing was really slow, especially for large collections, as it involves scanning the entire structure for changes, when in fact all changes could simply be flagged upon mutation. Conceptually, it performs diffing (ie. it gives you a diff object), its just much, much faster!
Very interesting pointer, thanks.
Remutable.Patch objects represent a collection of map edits, ie. a set of { key, value } pairs indicating that 'key' should be replaced by 'value' (and value can be void 0 to indicate deletion). They also embed a version and a hash for faster matching, but they can already be reverted/combined (for undo/redo stack or batching). I will read more about OTs!
Absolutely. I plan to include it in the framework ultimately, although it requires implementing an optimistic client-side dispatcher in JS which mocks the optimistic behaviour of the actual, eventually true server-side dispatcher (which may not always be implemented in full JS, eg. if it needs to sync with a db).
Conflicts are handled by the server-side dispatcher logic. Many applications can handle conflicts easily (eg. chat rooms which only append new messages), others can be more complex (eg. document editing). As mentionned in another comment, Remutable.Patch leaves room for rebase-like algorithms. Its definitely a very promising further work! :)
I didn't now about ShareJS, but I'll definitely check it out. At its core, the patch abstraction is commutative (and more importantly, reversible), so I should be able to implement the 'rebase'-like operation. My feeling is that it would be more efficient to perform this at a higher level though, by replaying Actions in the right order in every client to get eventual consistency.
You're right, although its fairly easy to implement optimistic updates on top of this. Since patch objects are reversible, you can use a simple logical clock and an undo/redo stack to perform optimistic updates locally, and undo them/redo them when the remote SSoT sends updates.
Wow, a crashed site presenting a web architecture surely isn't classy! Sorry about that, I'm working on it.
Fair enough, I've edited the topic name to clarify, thanks for your feedback!
Despite the name, it has nothing to do with Ruby-on-Rails. The name, coined by @Vjeux, is more about the purpose: provide a full-stack, batteries included framework for making apps with React. It embraces the React core principles all the way, from the data backend all the way up.
Also see the starterkit: https://github.com/elierotenberg/react-rails-starterkit