Uploaded image for project: 'camunda BPM'
  1. camunda BPM
  2. CAM-14699

Updates to entities related to a task fire historic task update events

    • Icon: Bug Report Bug Report
    • Resolution: Fixed
    • Icon: L3 - Default L3 - Default
    • 7.18.0, 7.18.0-alpha5
    • 7.18.0, 7.18.0-alpha2
    • None
    • None

      Environment (Required on creation):

      7.18.0-alpha2

      Description (Required on creation; please attach any relevant screenshots, stacktraces, log files, etc. to the ticket):

      In 7.18.0-alpha2 when modifiying entities related to a task that do not modify the task entity (e.g., add candidate user), the engine fires a historic task update event.

      Additionally, the engine produces a task listener event.

      Steps to reproduce (Required on creation):

      Run org.camunda.bpm.spring.boot.starter.CamundaEventingIT.shouldEventHistoryTaskAssignmentChanges() or org.camunda.bpm.spring.boot.starter.CamundaEventingIT.shouldEventHistoryTaskMultipleAssignmentChanges().
      The test creates and deletes several identity link log events and asserts the order and some properties of the events.
      The list also contains a historic task update event for each created/deleted identy link log.

      Observed Behavior (Required on creation):

      The test fails. The list of inspected events does not only contain historic identity link log events but also historic task update events.

      Expected behavior (Required on creation):

      The test succeeds without modification. That means no historic task update events are fired for changes to entities related to a task that don't modify the task entity itself.

      Root Cause (Required on prioritization):

      With CAM-14303, we introduced a date property to the task entity called lastUpdated which is set whenever an update to the task entity or associated entities (like variables, identity links, comments, ...) happens.
      This means, that for actions that did not modify the task entity, now the task entity is modified. This is done via the triggerUpdateEvent method which also triggers the merge of the entity into the DB causing a MERGED state.

      On command context close the engine checks if the entity is dirty (which is fulfilled by the MERGED state) and fires the historic task update event.

      Solution Ideas (Optional):

      1. Introduce lastUpdated to the history. This would be relatively easy to add. In that case the historic events would be expected.
      2. Prevent the historic task update event for persisted changes. The event is produced on command context close. One possible solution would be to inspect the persistent state and don't fire the event if only lastUpdated was changed.
      3. Additionally to 2. also prevent the task listener event triggered within the task event lifecycle if only the lastUpdated property was changed.

      Hints (optional):

        This is the controller panel for Smart Panels app

            [CAM-14699] Updates to entities related to a task fire historic task update events

            Looking at the code, why do we need to explicitly call TaskEntity#update in https://github.com/camunda/camunda-bpm-platform/blob/171c14bbc5fa015211c33d18f445c3da65d2d8dc/engine/src/main/java/org/camunda/bpm/engine/impl/persistence/entity/TaskEntity.java#L1197? Not sure this is directly related to the problem here, but I was wondering about this when I read the code.

            Thorben Lindhauer added a comment - Looking at the code, why do we need to explicitly call TaskEntity#update in https://github.com/camunda/camunda-bpm-platform/blob/171c14bbc5fa015211c33d18f445c3da65d2d8dc/engine/src/main/java/org/camunda/bpm/engine/impl/persistence/entity/TaskEntity.java#L1197? Not sure this is directly related to the problem here, but I was wondering about this when I read the code.

            I think we can also argue that the additional history events are expected behavior. Because the runtime task does change and the history event handler may decide to reflect that in the history (it's just that the built-in database-backed handler does not and therefore it should not make an empty UPDATE SQL statement).

            Thorben Lindhauer added a comment - I think we can also argue that the additional history events are expected behavior. Because the runtime task does change and the history event handler may decide to reflect that in the history (it's just that the built-in database-backed handler does not and therefore it should not make an empty UPDATE SQL statement).

            Miklas Boskamp added a comment - - edited

            I see four options:

            1. Introduce lastUpdated to history
            Pro:

            • Low effort
            • History events would be expected

            Con:

            • Would not add too much value for users
            • Sorting in history would require an additional index which we try to avoid (larger tables)

            2. Prevent the historic event when only lastUpdated changed
            Pro:

            • No change in expected behavior
            • We can use getPersistentState to check what changed. Finding out what changed in an entity is the main purpose of the persistent state and it is also already used through TaskEntity.

            Con:

            • More effort than 1

            3. In addition to 2. also prevent the event fired in the event lifecycle if only lastUpdated changed
            Pro:

            • No event = no history event, no change in expected behavior

            Con:

            • More effort than 1 and 2

            4. Additional history events are expected
            Pro:

            • Low effort.
            • The default history event handler needs to ignore any event that was caused by a task that had only changed the lastUpdated property. Otherwise, an UPDATE statement for the historic table will be fired without any change in history.
            • The event should give users access to the changed property (lastUpdated) so they can decide to use it in a custom history event handler.
            • We need to adjust the tests and document the decision

            Con:

            • We change the expected behavior which might impact users.

            Miklas Boskamp added a comment - - edited I see four options: 1. Introduce lastUpdated to history Pro: Low effort History events would be expected Con: Would not add too much value for users Sorting in history would require an additional index which we try to avoid (larger tables) 2. Prevent the historic event when only lastUpdated changed Pro: No change in expected behavior We can use getPersistentState to check what changed. Finding out what changed in an entity is the main purpose of the persistent state and it is also already used through TaskEntity . Con: More effort than 1 3. In addition to 2. also prevent the event fired in the event lifecycle if only lastUpdated changed Pro: No event = no history event, no change in expected behavior Con: More effort than 1 and 2 4. Additional history events are expected Pro: Low effort. The default history event handler needs to ignore any event that was caused by a task that had only changed the lastUpdated property. Otherwise, an UPDATE statement for the historic table will be fired without any change in history. The event should give users access to the changed property ( lastUpdated ) so they can decide to use it in a custom history event handler. We need to adjust the tests and document the decision Con: We change the expected behavior which might impact users.

            Decision: We will prevent historic task update events when only lastUpdated has changed (i.e. a related entity like identity link for example changed). This can be achieved by removing the explicit update() call. This call also registers a listener which produces the history event.

            Miklas Boskamp added a comment - Decision: We will prevent historic task update events when only lastUpdated has changed (i.e. a related entity like identity link for example changed). This can be achieved by removing the explicit update() call . This call also registers a listener which produces the history event.

              miklas.boskamp Miklas Boskamp
              miklas.boskamp Miklas Boskamp
              Tassilo Weidner Tassilo Weidner
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

                Created:
                Updated:
                Resolved: