Skip to content

fix(rush): treat non-terminal statuses as non-terminal #5277

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"comment": "Do not run afterExecuteOperation if the operation has not actually completed.",
"type": "none",
"packageName": "@microsoft/rush"
}
],
"packageName": "@microsoft/rush",
"email": "[email protected]"
}
Original file line number Diff line number Diff line change
Expand Up @@ -263,14 +263,19 @@ export class OperationExecutionManager {
const onOperationCompleteAsync: (record: OperationExecutionRecord) => Promise<void> = async (
record: OperationExecutionRecord
) => {
try {
await this._afterExecuteOperation?.(record);
} catch (e) {
this._reportOperationErrorIfAny(record);
record.error = e;
record.status = OperationStatus.Failure;
// If the operation is not terminal, we should _only_ notify the queue to assign operations.
if (!record.isTerminal) {
this._executionQueue.assignOperations();
} else {
this._onOperationComplete(record);
Copy link
Contributor

Choose a reason for hiding this comment

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

This goes after _afterExecuteOperation because that call can change the status (in addition to the status change in the error handler)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@dmichon-msft From my read of this code, _onOperationComplete expects (or at least expected) a terminal operation to then handle propagating various states to other operations - the actual status changes happen in OperationExecutionRecord.executeAsync?

Copy link
Contributor

Choose a reason for hiding this comment

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

The behavior of _onOperationComplete varies depending on the current status of record.status, and both this._afterExecuteOperation(record) and the error handler thereof are allowed to alter that status, importantly by potentially changing a success to a failure.

Even more importantly, _onOperationComplete is the call that unblocks the execution of dependent operations, and various plugins use afterExecuteOperation to perform work that must complete before those dependent operations can start.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yup that makes sense, but moving to isTerminal shouldn't change that logic since the dependent operations should only be blocked/unblocked on terminal statuses (Success/Error not Executing or Waiting as is happening right now).

try {
await this._afterExecuteOperation?.(record);
} catch (e) {
this._reportOperationErrorIfAny(record);
record.error = e;
record.status = OperationStatus.Failure;
}
Comment on lines +270 to +277
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
this._onOperationComplete(record);
try {
await this._afterExecuteOperation?.(record);
} catch (e) {
this._reportOperationErrorIfAny(record);
record.error = e;
record.status = OperationStatus.Failure;
}
try {
await this._afterExecuteOperation?.(record);
} catch (e) {
this._reportOperationErrorIfAny(record);
record.error = e;
record.status = OperationStatus.Failure;
}
this._onOperationComplete(record);

Copy link
Contributor

Choose a reason for hiding this comment

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

This is what I want fixed.

}
this._onOperationComplete(record);
};

const onOperationStartAsync: (
Expand All @@ -296,8 +301,8 @@ export class OperationExecutionManager {
const status: OperationStatus = this._hasAnyFailures
? OperationStatus.Failure
: this._hasAnyNonAllowedWarnings
? OperationStatus.SuccessWithWarning
: OperationStatus.Success;
? OperationStatus.SuccessWithWarning
: OperationStatus.Success;

return {
operationResults: this._executionRecords,
Expand Down Expand Up @@ -431,13 +436,13 @@ export class OperationExecutionManager {
this._hasAnyNonAllowedWarnings = this._hasAnyNonAllowedWarnings || !runner.warningsAreAllowed;
break;
}
}

if (record.isTerminal) {
// If the operation was not remote, then we can notify queue that it is complete
this._executionQueue.complete(record);
} else {
this._executionQueue.assignOperations();
default: {
throw new InternalError(`Unexpected operation status: ${status}`);
}
}

// If the operation was not remote, then we can notify queue that it is complete
this._executionQueue.complete(record);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Array [
},
Object {
"kind": "O",
"text": "[green]\\"operation2 (success)\\" completed successfully in 15.00 seconds.[default]
"text": "[green]\\"operation2 (success)\\" completed successfully in 10.00 seconds.[default]
",
},
Object {
Expand All @@ -56,7 +56,7 @@ Array [
},
Object {
"kind": "O",
"text": "[green]\\"operation (success)\\" completed successfully in 15.00 seconds.[default]
"text": "[green]\\"operation (success)\\" completed successfully in 10.00 seconds.[default]
",
},
Object {
Expand Down Expand Up @@ -212,7 +212,7 @@ Array [
},
Object {
"kind": "E",
"text": "[yellow]\\"operation2 (success with warnings)\\" completed with warnings in 15.00 seconds.[default]
"text": "[yellow]\\"operation2 (success with warnings)\\" completed with warnings in 10.00 seconds.[default]
",
},
Object {
Expand Down Expand Up @@ -240,7 +240,7 @@ Array [
},
Object {
"kind": "E",
"text": "[yellow]\\"operation (success with warnings)\\" completed with warnings in 15.00 seconds.[default]
"text": "[yellow]\\"operation (success with warnings)\\" completed with warnings in 10.00 seconds.[default]
",
},
Object {
Expand Down