Node-fiber NOTE OF OBSOLESCENCE

Interesting. This presentation also contains some slides where benjmn explains why mimicking Fibers with async/await (as I was hoping for) might be a bad idea. But maybe this could only be restricted to Meteor’s pseudo-synchronous API?

I do have a question.
I remember the days when you could meteor deploy your app for free.
I know Galaxy has free hosting for a period of time, and that there are business reasons behind charging for it but if personally, I could deploy my Meteor apps just like I do with my Netlify ones that would be really really awesome.

Is the free hosting ever making a comeback? (sorry if this was asked before)

At this point in my career I would be able to actually spend the money on a tiny container for my side project apps, but it is a fact that early on and for a lot of people in my country this would represent making a sacrifice somewhere to get that going. I hope I make sense.

Still rooting for Meteor, thanks for all the hard work!

1 Like

This post above explains it

Yes, I saw that, but I thought it was pretty cryptic. To me, coroutines and async/await do not look that different. When you set an await statement, this is pretty much the same as placing a yield. Ok, the await returns the result of the async operation, while a yield typically returns something comparable to a Promise. But actually, the async op returns a Promise, too, which you can see if you don’t await the call. So the await it’s more or less syntactic sugar (plus it allows to try/catch the statement). Maybe he was relating to the special form of Meteor‘s fibers that also hold some Meteor-specific state?

Coroutines is something that doesn’t exists in Node.js codebase, the closest native implementation is Worker Threads.

At the same time Fibers “C-extension” brings coroutines implementation to Node.js allowing blocking in separate “fibers” (e.g. threads), as well as assigning context/state to a “thread”.

As I understand initially Fibers were used to solve two Node.js issues:

  1. Session context/state on server (needed to maintain DDP/WebSocket “private” sessions);
  2. Parallelization (e.g. multi-thread).

Thread blocking was a bonus-feature in that case. Having done() as a last argument in methods, or this.ready() as we have in subscriptions, or support returning Promise from method would ease transition to asynchronous implementation.

Hope that helps to understand coroutines and what tasks were solved using it.

Feel free to jump in if I’m wrong or missed something.

4 Likes

Very good summary @dr.dimitru. If someone wants a deeper dive, there is this article on how async/await differs from coroutines. Uses Go’s goroutines for comparison. https://danoctavian.com/2019/03/25/thinking-coroutines-nodejs/

3 Likes

An issue I always have with async/await is if the function is deep into a series of function calls. Using async/await require transforming the entire function hierarchy into async.

Seems like this is a clear advantage of fibers. I think moving to workers will have the same issue (but I just used them sparingly and not much adept with it)

3 Likes

There’s no magic in async/await, nor in Promises, — it’s just a way to write asynchronous code which looks like synchronous, more readable, and potentially easier to maintain.

With node.js Workers idea is to block the thread until Worker returns response, for example with while loop.

I believe if one of the major Meteor releases will introduce support for asynchronous Methods — there will be no need for thread blocking in its core.

And use node.js Workers for parallelization and “context(ed) threads”.

4 Likes

That would be truly awesome.

1 Like

How different would it be with either this.unblock() or Meteor.defer()?

Doesn’t Node support generators? That‘s how Unity implements coroutines on top of C#.

By default you can run only single Meteor.Method on the Client, calling this.unblock() would simply allow to call another Client-to->Server method(s) in parallel.

Meteor.defer() is a wrapper for process.nextTick on the Server and setTimeout on the Client, made to provide isomorphic API across platforms, and would take care of “running inside Fiber”.

Yes. Generators won’t solve this (generators doesn’t run in parallel to main thread):

Think of generators as of stateful functions with ability to stop in the middle of a function, best example is DB’s cursors.

I can’t say much at this point but we are working in this direction :wink:

7 Likes

This. Would. Be. Freaking. Awesome.

If thread-blocking was a bonus-feature, I’m sure we can find a way around the rest, but thread-blocking is - at least to me - the biggest backwards-incompatibility.

It’s like @rjdavid said:

An issue I always have with async/await is if the function is deep into a series of function calls. Using async/await require transforming the entire function hierarchy into async.

To me this reflects our conflict about backwards compatibility best. Many functions - first and foremost database calls - allow to and are therefore often used in a thread-blocking way. Basically every function would have to be rewritten to be async-await-aware :worried: But it might not be a bad way to provide an easy way to untie yourself from these limitations :smirk:

If there are other changes we’d have to make along the way, I (as an average user of Meteor) might be astonished at the way this is realised when diving into it, but would mostly care about how well it allows me to focus on my application.

Just to put this on as well … Thread-blocking makes debugging quite hard, and the other goodies seem to be incompatible with async-hooks (https://nodejs.org/api/async_hooks.html) - e.g. when using the package https://github.com/Meteor-Community-Packages/meteor-elastic-apm. Yes, I know async-hooks are experimental, but they’d be very helpful for debugging if they’d work properly with Meteor …

Just my 0.02$ as a Meteor developer who doesn’t have all too much insight into the Meteor core.

Many functions - first and foremost database calls - allow to and are therefore often used in a thread-blocking way. Basically every function would have to be rewritten to be async-await-aware

Agreed with @rjdavid and @simonsimcity : moving to plain async / await means massive rewrites - not only on the server side, but also on the client side, minimongo calls and all their surrounding call stack turning async because of isomorphic api (and for no other reason since they are in fact synchronous on the client) means large parts of clent code becoming async - which has a non-minor perf impact.

Fibers allow the same code to be written for the client and server sides , while the underlying APIs can be synchronous on one side and asynchronous on the other. That isomorphism is kind of the core of the whole Meteor concept…

8 Likes

Thanks to fibers, some very good packages like f-promise or f-streams allows development look like a pure synchronous code without contamination of async / await keywords thought the whole stack.

The best scenario to prevent any breaking changes to applications depending on fibers would be that node.js provides directly coroutines in its core implementation.

A community like meteor could have maybe a weight to convince node.js core developers to provide it one day…

6 Likes

And in case this won’t Happen we could still ask to transition fibers (or fork it) and keep it alive.

The cool thing about javascript is, that the control flow is very simple to follow and
with async/await it’s always clear whether a function will yield or not. But fibers hide that, any function can yield.

This basically make js-with-fibers another language that is not 100% compatible with non-fibers-js.

Take this function

const a = () => {
  b();
  c();
}

without fibers, its clear that b and c always run in order whenever a is called. With fibers, when b or c happen to yield, the order is no longer guaranteed. Imaging that c is yielding, but takes some time. When a is now called multiple times, b might run multiple times before the first c has finished. This can lead to bugs when these function rely e.g. on shared variables.

This is not theory, this problem happens in practise:

So i don’t think that node-fibers will ever land in node. When I learned about async/await i was also wondering why we have to annotate these functions with these keywords and thought this was unnecessary and it took me some time (and the bugs above) to realize, why it is useful.

5 Likes