Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens the job cancellation flow to prevent unintended cancellations caused by non-user link visits (e.g., link scanners/previews), by making GET /CancelProcessing non-destructive and requiring an explicit POST confirmation to cancel. It also adjusts container shutdown behavior so user-initiated cancellation can exit cleanly.
Changes:
- Updated
CancelProcessingto render a confirmation UI onGET, and only cancel onPOST, with execution-status checks before showing the stop option. - Enhanced cancellation logging with request diagnostics and refined fallback behavior when execution mapping is unavailable.
- Updated container entrypoint cancellation handling to attempt a “successful exit” on user-requested cancellation and slowed the polling interval.
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
entrypoint.sh |
Adds signal handling and cancellation marker file; changes cancellation polling interval and termination behavior. |
azure-function/src/functions/CancelProcessing.js |
Implements non-destructive GET confirmation flow, status checks, richer logging, and cooperative cancellation behavior. |
.gitignore |
Ignores additional AI agent working directories. |
Comments suppressed due to low confidence (1)
azure-function/src/functions/CancelProcessing.js:515
- After a user opens the confirmation page, the execution could finish before they submit the POST. In the mapping/cooperative branch, the POST handler does not re-check whether the target execution is still running before returning success, so users can get a “cancelled successfully” response even though nothing was stopped. Consider re-checking execution status in the POST flow (or returning a completed/not-running message) before marking cancelled / removing the mapping.
// Found in cache, let the container's cancellation checker stop itself.
structuredLog(
context,
"info",
"Marked job execution for cooperative cancellation",
{
jobName,
executionName,
resourceGroup,
},
);
// Mark as cancelled only after confirming the cooperative path is valid
markAsCancelled(executionId);
// Remove from mapping cache
removeExecutionMapping(executionId);
}
return createResponse(
request,
true,
"Processing has been cancelled successfully.",
200,
{ executionId, executionName },
);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
This PR fixes accidental job cancellation from cancel-link visits (#104) and improves the cancellation flow.
Changes:
GET /CancelProcessingnon-destructive.POST /CancelProcessingto actually cancel a job.client.jobs.beginStopExecutionAndWait(...).client.jobsExecutions.delete(...)usage.cancelledTeams notifications from inside the container when cancellation is confirmed.SIGTERMexits143,SIGINTexits130, and user-requested cancellation can exit0.javascript:window.close()link from the confirmation page.Why it worked before but started failing now
The old cancellation endpoint accepted both
GETandPOST, and aGETrequest immediately cancelled the job.That worked for months because nothing was regularly visiting the cancel URL before the user clicked it. Recently, something in the message/link path appears to have started touching the URL automatically, likely one of:
The Azure logs showed
CancelProcessingbeing invoked even when the user had not clicked the cancel button. Once that endpoint was invoked, it marked the execution as cancelled, then the container’sCheckCancellationpoll saw the cancelled state and terminated the job.The root issue was that cancellation was implemented as a destructive
GET, which is unsafe because links can be visited by systems other than the user.Fix
GET /CancelProcessingnow only renders a confirmation/status page.The actual cancellation only happens when the user submits the confirmation form, which sends
POST /CancelProcessing.The confirmation page checks Container App Job execution status first:
RunningorProcessing, the user sees the stop confirmation.On confirmed cancel, the Function marks the execution as cancelled, then stops the Container App Job execution using
client.jobs.beginStopExecutionAndWait(...).The container handles user cancellation as a best-effort graceful path:
SIGTERM.CheckCancellation.NOTIFICATION_TYPE=cancelledthrough the existing notification script.0for user-requested cancellation.Cancelled notification behavior
Cancelled notifications are sent from inside the container, not directly from the Azure Function.
This lets cancelled notifications reuse the same metadata already available for failed/completed notifications:
PARTICIPANTS_JSONMEETING_SUBJECTPROJECT_NAMEMEETING_DURATIONThat means cancelled notifications can go to the same participant list as failed/completed notifications.
Known limitation / TODO
The cancelled marker currently uses Azure Function in-memory state.
That means the cancelled Teams notification is best-effort only: if
CheckCancellationis served by a different Function instance than the one that handled the cancel POST, the container may not see the cancelled marker before it is stopped.The job stop itself is reliable because it uses the Container Apps API, but the cancelled Teams notification can still be missed in a cross-instance case.
TODO:
CheckCancellationread from that shared store.User impact
Users now get an explicit confirmation step before stopping analysis.
Security scanners, link previews, or accidental URL visits can no longer cancel a meeting analysis job.
If the job has already finished by the time the user opens the cancel link, the page tells them it has likely completed instead of showing a misleading stop button.
When cancellation is confirmed and the container observes the cancellation marker, participants receive a cancelled Teams notification.
Validation
CancelProcessingbeing invoked beforeCheckCancellationreturned cancelled.beginStopExecutionAndWait(...)onclient.jobs;jobsExecutionsonly supportslist().client.jobsExecutions.delete(...).entrypoint.shsyntax withbash -n entrypoint.sh.