Skip to content

Task lifecycle change events are emitted only from the HTTP resource layer (internal, workflow and bulk transitions stay silent) #29038

Description

@manerow

Rewritten 2026-07-28 after re-verifying against main (2.0.0-SNAPSHOT, OSS 7cb9ffbb44).
The original scope (HTTP endpoints emit nothing) shipped in #30248. What remains is the layer
the emission was implemented at.

Status: partially fixed

TaskResource.resolveTask, closeTask and applySuggestion now set
CHANGE_CUSTOM_HEADER = EventType.ENTITY_UPDATED (TaskResource.java:1126,1302,1396), added by
#30248 on 2026-07-21. addComment was given the same header earlier in #29023.

Verified live on a clean main deploy: one single-task resolve plus one single-task close
produce exactly two rows.

SELECT entityType, eventType, COUNT(*) FROM change_event GROUP BY 1,2;
task   entityCreated   3
task   entityUpdated   2      <- resolve + close

Note this never affected 1.12 / 1.13: TaskResource and entity/tasks/task.json do not exist on
those branches. It is a main / 2.0 concern only.

What is still broken

The emission lives in the resource layer, so it only fires for a single-task HTTP turnaround.
Every other path that transitions a task stays silent:

Silent path Call site
Incident resolve (test case resolution) TestCaseResolutionStatusRepository.java:388 -> resolveTaskWithWorkflow
Incident reopen TestCaseResolutionStatusRepository.java:361 -> reopenTaskWithWorkflow
Workflow rerun superseding a prior task CreateTask.java:745 -> closeTask
Bulk operations TaskResource.bulkOperation (verified: bulk Cancel produced zero rows)
Any future external sync (JIRA / ServiceNow inbound) non-HTTP by definition

There is also no /reopen endpoint at all on TaskResource, so a task reopen can never emit a
change event through the response-filter mechanism, by any caller.

Fix: move the emission into the workflow handler

Emit from TaskWorkflowHandler.resolveTask / closeTask / reopenTask instead of from the
resource. That class already has the exact machinery, used today to record the target entity
patches a task resolution applies:

// TaskWorkflowHandler.java:744 (recordChangeEvent)
ChangeEvent changeEvent = FormatterUtil.createChangeEventForEntity(user, changeType, entityInterface);
changeEvent = ChangeEventHandler.copyChangeEvent(changeEvent);
Entity.getCollectionDAO().changeEventDAO().insert(JsonUtils.pojoToJson(changeEvent));

Extend the same helper to the task's own transition, then drop the three
CHANGE_CUSTOM_HEADER lines from TaskResource so a single HTTP resolve does not emit twice.

One choke point covers HTTP, bulk (#29041), incident-driven transitions, and workflow-driven
transitions.

Event type stays entityUpdated. That was settled by #30248 and matches every other entity.
taskResolved / taskClosed remain reachable only through the legacy FeedRepository route and
are handled in #29039.

Prerequisite for a meaningful event: the emitted changeDescription currently does not name
status or resolution (see the stale-diff sub-issue of this epic). Relocating the emission
without fixing the diff produces an event that says a workflow stage changed, not that a task was
resolved.

Acceptance criteria

  • Resolving, closing and reopening a task emits exactly one change_event row with entityType=task, eventType=entityUpdated, regardless of whether the caller is HTTP, bulk, an incident flow, or a governance workflow.
  • A single HTTP /resolve emits one row, not two (headers removed from TaskResource).
  • TestCaseResolutionStatusRepository resolve and reopen produce a task change event.
  • Integration test covers one HTTP path and one internal path (incident resolve).
  • Integration test: a bulk operation over 2 or more tasks produces one change_event row per task, and a subscription on task fires once per affected task (carried over from Bulk task endpoint emits no per-task change events (subsumed by #29038) #29041, which this issue subsumes).

Metadata

Metadata

Assignees

Type

Projects

Status
No status
Status
Release Backlog 🚧

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions