Seow Alex created NIFI-16475:
--------------------------------

             Summary: ConnectionStatus.maxQueuedDuration is 0 on all but one 
node in a cluster
                 Key: NIFI-16475
                 URL: https://issues.apache.org/jira/browse/NIFI-16475
             Project: Apache NiFi
          Issue Type: Bug
          Components: Core Framework
    Affects Versions: 2.7.2, 1.28.1
            Reporter: Seow Alex


In a NiFi cluster, `ConnectionStatus.getMaxQueuedDuration()` returns 0 on every 
node except one, even when the connection has flowfiles queued on that node. 
The one node that reports correctly is the node whose name sorts last.

Anything that reads `maxQueuedDuration` from connection status, such as a 
reporting task or the connection status from the REST API, gets 0 on most 
nodes. `totalQueuedDuration` is not affected.

**Cause**

When the node is clustered, `FlowController.createConnection` creates a 
`SocketLoadBalancedFlowFileQueue` for every connection, including ones set to 
"Do not load balance". The queue keeps one partition per node. 
`setNodeIdentifiers` sorts the partitions by node name and port (`apiAddress + 
":" + apiPort`).

`SocketLoadBalancedFlowFileQueue.getMinLastQueueDate()` is effectively:

```java
long min = 0;
for (QueuePartition partition : queuePartitions) {
    min = (min == 0) ? partition.getMinLastQueueDate()
                     : Long.min(min, partition.getMinLastQueueDate());
}
return min;
```

An empty partition returns 0. Once `min` holds a real date, any later empty 
partition sets it back to `Long.min(min, 0) = 0`. On a connection that isn't 
load-balanced, only the local partition holds flowfiles. So the result is 
non-zero only if the local partition is the last one in the sorted array.

`AbstractEventAccess` then sets `maxQueuedDuration = 0` when 
`getMinLastQueueDate()` returns 0, and `now - minLastQueueDate` otherwise.

`SwappablePriorityQueue.getMinLastQueueDate()` has a similar flaw. It computes 
`Long.min(activeMin, getMinLastQueueDate(swapQueue, activeMin))`. If the active 
queue is empty, `activeMin` is 0 and the swap queue's dates are ignored. It 
falls back to the dates of swapped-out flowfiles only when `min == 0`.

**Steps to reproduce**

1. Start a 3-node cluster with nodes named `nifi-a`, `nifi-b` and `nifi-c`.
2. Create a flow with a connection whose load balance strategy is "Do not load 
balance". Stop the destination processor so flowfiles stay queued.
3. Generate flowfiles on each node.
4. Read `maxQueuedDuration` for the connection from each node's local status.

**Expected:** every node reports the age of the oldest flowfile queued on it.

**Actual:** `nifi-c` (last in sort order) reports a non-zero value. `nifi-a` 
and `nifi-b` report 0.

**Observed in production**

On three separate 3-node clusters running 1.28.1, and on 3-node clusters 
running 2.7.2, only the last node by name ever reported a non-zero 
`maxQueuedDuration` over several weeks of monitoring. The other nodes reported 
0 even with flowfiles queued for days.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to