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

test: Add test case for canceling async worker tasks #1202

Merged
merged 4 commits into from
Sep 26, 2022

Conversation

JckXia
Copy link
Member

@JckXia JckXia commented Aug 29, 2022

Adding a small test case for Async workers' Cancel functionality, where if the cancellation is successful neither OnOk or OnError should be invoked.

Copy link
Member

@legendecas legendecas left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great job!

}

void OnError(const Error&) override {
NAPI_THROW_IF_FAILED_VOID(this->Env(), napi_generic_failure);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be more intuitive if we can throw an error with an explicit message about the reason here:

Suggested change
NAPI_THROW_IF_FAILED_VOID(this->Env(), napi_generic_failure);
Napi::Error::New(env, "Unreachable").ThrowAsJavaScriptException();

}

void OnOK() override {
NAPI_THROW_IF_FAILED_VOID(this->Env(), napi_generic_failure);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

static void DoWork(const CallbackInfo& info) {
Function cb = info[0].As<Function>();
std::string echo = info[1].As<String>();
for (int i = 1; i < MAX_CANCEL_THREADS; i++) {
Copy link
Member

@legendecas legendecas Sep 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can get the cpu number with JS API and fill the worker threads with that number of workers? In that case, the test can be more stable.

With JS specified worker filling number, we can also test that cancelWorker->Cancel() throws if the cancel worker has started the work.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey Legendecas! Thank you for the review. By cpu numbers do you mean the size of the Libuv's thread pool? I tested this by setting UV_THREADPOOL_SIZE to smaller numbers such as 2 or 3 and it seems to work reliably in that the CancelWorker is able to cancel the queue'd task.

Also, I am running into some difficulties testing that Cancel() throws if the worker has started the task. Initially, I just passed the value 0 as the threadNum to queue a task for the Cancel worker to cancel, expecting an error to be thrown. For some reason, this exception is only thrown once by Cancel().

After doing some investigation, it looks like we run this test using common.runTest where we run the test function using 4 different node-gyp configs in rapid succession. Could it be that by the second time the test function is invoked, the thread pool is busy and cancellation is successful? If that's the case is there a way where we could check to make sure the threads are idle before running the test suite? Thanks.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we already have a similar test case in core (https://github.com/nodejs/node/blob/main/test/node-api/test_async/test_async.c#L140) and it has been running in a quite stable way for a long time. If that's the case, I'm fine with the current pattern as it is the simplest way to test the API.

Yeah, if the test case is mixed up with other test suites, we can not guarantee that the threadpool is ready to execute the work immediately. But I believe we can still facilitate mutexes and conditional variables to notify the JS thread when the Worker is started to execute. However, this increases the complexity of this test case and I assume it is fine to do it in a follow up PR.

@JckXia JckXia merged commit 793268c into nodejs:main Sep 26, 2022
@JckXia
Copy link
Member Author

JckXia commented Sep 26, 2022

Landed as 793268c

@JckXia JckXia deleted the add_test_for_async_cancel branch September 26, 2022 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants