aws / aws/jsii

JSii blocks the node process when the JS code is not being called by the host

Open
#4,133 4 comments 0 reactions 0 assignees View on GitHub
feature-request p2
Dominant language
TypeScript
Stars
2.9k
Forks
267
Avg merge
1d 25m
Merged PRs (30d)
14

Description

### Describe the bug

In (at least) Java, the node process is blocked while it is waiting for new method calls.

Specifically, promises that are running in the JSii-ed node process don't run at all when the host process has no active calls to the JSii-ed process.

I have a small repro of this bug in [this repository](https://github.com/TimothyJones/jsii-async-issue). Here's a breakdown of what's in that repo:

* There is a [JS class](https://github.com/TimothyJones/jsii-async-issue/blob/main/jsii-module/src/index.ts#LL7C3-L7C3) that kicks off a "tick" promise chain which [logs to console every quarter second](https://github.com/TimothyJones/jsii-async-issue/blob/main/jsii-module/src/index.ts#L1), and will print these logs even after `longRunningSomething()` has completed.
*The console logs have a number in them that tell you which call of `longRunningSomething()` those logs were kicked off by.
* When called from JS, this tick prints every quarter second (as expected) - this isn't in the repo, but is easy to demonstrate with:
```
new Example().longRunningSomething();
console.log("Long running something complete")
await new Promise((resolve) => setTimeout(resolve, 5000)); // logs will keep printing while waiting for this to complete
```
* When [called from Java](https://github.com/TimothyJones/jsii-async-issue/blob/main/java-host/untitled/src/main/java/org/example/Main.java#L11), the ticks only and print when the execution is with node.
* When node returns to Java, the ticks stop.
* The ticks restart again [if further calls to JS are made](https://github.com/TimothyJones/jsii-async-issue/blob/main/java-host/untitled/src/main/java/org/example/Main.java#L15).

Although this is an `async` example, the blocking of the node process happens regardless of whether or not the call in to it is async. I only made an async example so that I could make `longRunningSomething()` take a while so you can see that the ticks run while node is doing something that it is planning to return to java.

### Expected Behavior

When the java code at that link is run, I expect the `(1)` ticks to continue after the call to `longRunningSomething()` while the Java thread is doing something else.

### Current Behavior

When the java code at that link is run, the `(1)` ticks stop once the JS returns to Java.

The `(1)` ticks restart when

### Reproduction Steps

With JDK 20.0.1 (this is just the version I know works, others probably do too):

```
git clone git@github.com:TimothyJones/jsii-async-issue.git
cd java-host/untitled
./gradlew run
```

Observe that the ticks stop printing when Java is waiting

### Possible Solution

My guess is that the stdin/out protocol for communicating between JSii and the host uses blocking calls on the JS side. I suspect that non-blocking calls would solve this problem, and possibly several others.

Because JSii communicates across a stdin/out protocol with another process, I think there's quite a bit of flexibility in the way that async is treated - one side could see it as async, while the other sees it as sync (and vice versa).

### Additional Information/Context

This is related to [this issue](https://github.com/aws/jsii/issues/3016) in that I think this is the cause, rather than aync hairiness.

(that issue describes the exact situation that I have in my real code, though)

This is a blocking issue for me, I would be happy to look in to it (but definitely would need some guidance on where to look)

### SDK version used

jsii@5.1.1

### Environment details (OS name and version, etc.)

node 18.13.0, JVM 20.0.1, MacOS 13.3.1 (a)

Contributor guide

Open the contributing guide

Research direction

Run ./gradlew run from java-host/untitled in the linked reproduction, then inspect jsii-module/src/index.ts and java-host/untitled/src/main/java/org/example/Main.java. Trace the stdin/stdout behavior while Java is idle; done means the tick logs continue after longRunningSomething() returns instead of waiting for another JS call.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, node.js, typescript
Domain
devtools
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
30/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.