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

Continuing a fiber through a promise callback? #8

Open
TazmanianD opened this issue Aug 30, 2017 · 3 comments
Open

Continuing a fiber through a promise callback? #8

TazmanianD opened this issue Aug 30, 2017 · 3 comments
Labels

Comments

@TazmanianD
Copy link

TazmanianD commented Aug 30, 2017

@bjouhier This is a question similar to the last one I just posted but we have some cases where we're using promise based libraries that have some callback components to them. For example, if you want to do a bunch of work in a database transaction, you call a tx function that expects a "worker" function as a "callback". That worker function is expected to return a promise and the tx function also returns a promise. To use your library, this code would look like this (I've created a dumb "replica" of the tx function from the library which is what we can't change in our code).

function tx(worker: (transaction: any) => Promise<any>): Promise<any> {
  return new Promise((resolve, reject) => {
    worker(null).then(resolve, reject);
  });
}

function doSomeWork() {
  wait(tx((transaction: any) => {
    return run(() => doWorkInTransaction(transaction));
  }));
}

function doWorkInTransaction(transaction) {
  // Lots of stuff
}

run(() => doSomeWork())
  .then(console.log, console.error);

The problem is that this creates a second fiber with the promise inside the transaction even though all that code really is part of the same operation and should logically be a single fiber. Is there any way to "continue" execution on the current fiber instead of creating a new one via your "run" function.

@bjouhier
Copy link
Member

I need to investigate this one. It should be possible to run the whole operation on a single fiber but this will require a different API (probably more complex).

You can avoid the proliferation of wait/run calls in your code by wrapping tx as:

function tx2(worker: (transaction: any) => any): any {
  return wait(tx((transaction: any) => run(() => worker(transaction))));
}

function doSomeWork() {
  return tx2(doWorkInTransaction);
}

@TazmanianD
Copy link
Author

@bjouhier My main motivation for this request is that I'd like to use fibers to recreate what in Java are called thread locals. You can attach state to a fiber that can give you access to things like some "global" context information. A good use case is for error logging. When an error occurs, it can be useful to include information about the user the request is being processed on behalf of in the log for the error. But unless you pass around the current user to every function of you application, then any log calls won't have access to info. If you put it on the fiber, then the logging system can grab it from there.

@bjouhier
Copy link
Member

bjouhier commented Oct 6, 2017

@TazmanianD. There is already a TLS API in f-promise (https://github.com/Sage/f-promise#cls-continuation-local-storage). We use it extensively in our code.

The state is not attached to the fiber but it gets propagated across callbacks. Did you try it?

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

No branches or pull requests

2 participants