OpenFn / kit

The bits & pieces that make OpenFn work. (diagrammer, cli, compiler, runtime, runtime manager, logger, etc.)
8 stars 12 forks source link

compiler: support `.then()` and `.catch()` #721

Open josephjclark opened 5 days ago

josephjclark commented 5 days ago

Tricky one this.

Every operation is a promise*. So we should be able to do this in our job code:

fn(s => s).then(s)

This pattern eliminates the need for callbacks. Which is great, because operations with an optional options object and optional callback (which happens a lot) have really ugly signatures.

It also enables this:

fn(s => s).catch(s)

Which is badass! Suddenly I can catch any error I want! Which is covered by https://github.com/OpenFn/adaptors/issues/496 (an issue we have with this is that really I want to pass state and error into the catch, like catch( (e, s) => {}) - but I'm not quite sure how to do that technically. Maybe a custom promise?)

The PROBLEM is that the compiler hates this.

The compiler wants to move all top-level operations into an array, like this:

export default [fn(s => s).then(s)]

First off I think this breaks everything in the runtime, because that function must be deferred. The .then() will immediately invoke it. So I think the compiler needs to do this?

export default [() => fn(s => s).then(s)]

I don't know, I need to wrap my brain around that.

But secondly, and what this issue is about, is the compiler doesn't recognise x.then() as an operation. It recognises it as a method call and ignores it.

I think basically the compiler needs to treat x().then() and x().catch() specially and do some kind of magic wrapping around them to make them work properly.

josephjclark commented 5 days ago

If I can get this working, we can open up a debate about removing callbacks from all operations except iterators. Which I think would be a HUGE win