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

Fix/abort listener execution #484

Open
wants to merge 39 commits into
base: master
Choose a base branch
from

Conversation

joshLong145
Copy link
Contributor

PR for discussion on issue #479

…workerpool into fix/abort-listener-execution
update execOptions

update abort tests
@joshLong145 joshLong145 marked this pull request as ready for review February 17, 2025 17:37
Comment on lines +34 to +51
* @property {PromiseLike<void>} [abortPromise] PromiseLike Object which resolves or rejects when the abort operation concludes.
*
*/

/**
* @typedef {Object} AbortResolutionArgs
* @property {Error | undefined} [error] An error which occured during the abort operation. If an error did not occure the value will be `undefined`.
* @property {number} [id] identifier of the task.
* @property {boolean} [isTerminating] A flag which indicates the termination status of the worker which ececuted the task.
*/

/**
* @typedef {Object} ExecOptions
* @property {(payload: any) => unknown} [on] An event listener, to handle events sent by the worker for this execution.
* @property {Object[]} [transfer] A list of transferable objects to send to the worker. Not supported by `process` worker type. See ./examples/transferableObjects.js for usage.
* @property {(payload: any) => AbortResolutionArgs} [onAbortResolution] An event listener triggered when whenever an abort operation concludes.
* @property {(payload: AbortStartArgs) => void} [onAbortStart] An event listener triggered when a task throws a Timeout or Canceltion exception and cleanup is starting.
* @property {{ promise: import('./Promise.js').Promise<any, Error>; resolve: Function; reject: Function; }} [abortResolver] Defered Promise which resolves or rejects when the abort operation for the task concludes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am torn on if this is a good mechanism for allowing callers access to the promise which controls the abort operation. In AbortResolutionArgs we provide the promise for tracking the abort operations. We are able to provide the promise from the tracking deferred promise created internally.

We also allow the deferred promise for the abort operation to be provided through the ExecOptions. Since we need a deferred promise we cannot simply provide an instance of Promise.

This means the promise for the abort operation is exposed as two different types. Which is not ideal, but I am unsure if there is a way to unify them without breaking backwards compatibility.

Copy link
Owner

Choose a reason for hiding this comment

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

I'm not sure how abortResolver would work, isn't it duplicate with onAbortResolution?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

onAbortResolution is called after the abort handlers have executed and passes the taskId and error if the abort handlers threw an error, and a flag to determine if the worker is shutting down or not.

abortResolver is just allowing the user to provide the promise that is used as the tracking promise for a tasks abort operation.

The idea is to give control of the promise to the caller, so they do not need to get it from event args. but it can be misused easily.

Copy link
Owner

@josdejong josdejong left a comment

Choose a reason for hiding this comment

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

Thanks Josh! I've made some inline comment, can you have a look at those?

settlePromise,
timeoutPromise
]).then(function() {
return new Promise(function (resolve, reject) {
Copy link
Owner

Choose a reason for hiding this comment

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

Not sure, but can we use Promise.any([...]) here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We can, but I was trying to not use any implementation of Promise from outside of the repo.

/**
* @typedef {Object} ExecOptions
* @property {(payload: any) => unknown} [on] An event listener, to handle events sent by the worker for this execution.
* @property {Object[]} [transfer] A list of transferable objects to send to the worker. Not supported by `process` worker type. See ./examples/transferableObjects.js for usage.
* @property {(payload: any) => AbortResolutionArgs} [onAbortResolution] An event listener triggered when whenever an abort operation concludes.
Copy link
Owner

Choose a reason for hiding this comment

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

Is there an actual use case for the onAbortResolution and onAbortStart callbacks? If there is no clear use case I would prefer to not implement it right now, to keep things simple.

Copy link
Contributor Author

@joshLong145 joshLong145 Mar 6, 2025

Choose a reason for hiding this comment

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

The main usage is to give more context to the user on life cycle of the task. but onAbortStart does provide access the to promise.
It is also useful in tests to confirm that after the resolution of the abort operation the busyWorker count is correct as this cannot be asserted on from within the resolution of cancel or timeout promises.

If we are to remove these callbacks then we should keep abortResolver so the user knows when the abort operation concludes.

Comment on lines +34 to +51
* @property {PromiseLike<void>} [abortPromise] PromiseLike Object which resolves or rejects when the abort operation concludes.
*
*/

/**
* @typedef {Object} AbortResolutionArgs
* @property {Error | undefined} [error] An error which occured during the abort operation. If an error did not occure the value will be `undefined`.
* @property {number} [id] identifier of the task.
* @property {boolean} [isTerminating] A flag which indicates the termination status of the worker which ececuted the task.
*/

/**
* @typedef {Object} ExecOptions
* @property {(payload: any) => unknown} [on] An event listener, to handle events sent by the worker for this execution.
* @property {Object[]} [transfer] A list of transferable objects to send to the worker. Not supported by `process` worker type. See ./examples/transferableObjects.js for usage.
* @property {(payload: any) => AbortResolutionArgs} [onAbortResolution] An event listener triggered when whenever an abort operation concludes.
* @property {(payload: AbortStartArgs) => void} [onAbortStart] An event listener triggered when a task throws a Timeout or Canceltion exception and cleanup is starting.
* @property {{ promise: import('./Promise.js').Promise<any, Error>; resolve: Function; reject: Function; }} [abortResolver] Defered Promise which resolves or rejects when the abort operation for the task concludes.
Copy link
Owner

Choose a reason for hiding this comment

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

I'm not sure how abortResolver would work, isn't it duplicate with onAbortResolution?

var {Promise} = require('../src/Promise');
var Pool = require('../src/Pool');
var tryRequire = require('./utils').tryRequire
var assert = require("assert");
Copy link
Owner

Choose a reason for hiding this comment

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

I see you have different coding style configured in your IDE 😅 . We should really setup a linter for the project, let me see if I can set up Biomejs (if so we can run it after merging this PR, otherwise we'll have a lot of merge conflicts).

Is it possible to revert the coding style changes, so I can see which unit tests are added/updated?

Copy link
Contributor Author

@joshLong145 joshLong145 Mar 6, 2025

Choose a reason for hiding this comment

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

Yes sorry I switched Editors recently and format on save was default enabled...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I reverted back to the upstream master and applied my changes to the abort handler test suite. there are a couple formatting changes that I'll clean up. but the tests where largely re written to wait until the abort operation concludes to assert on the pool status. Which makes it a larger diff.

@joshLong145 joshLong145 force-pushed the fix/abort-listener-execution branch from 9bd3e90 to 361bccd Compare March 6, 2025 02:44
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.

2 participants