Xinyu Wang created NIFI-16440:
---------------------------------

             Summary: Provided Parameters stay empty after restart once a 
failed Parameter Provider fetch has dropped their value from flow.json
                 Key: NIFI-16440
                 URL: https://issues.apache.org/jira/browse/NIFI-16440
             Project: Apache NiFi
          Issue Type: Bug
          Components: Core Framework
    Affects Versions: 2.12.0, 2.0.0
            Reporter: Xinyu Wang


h3. Problem
NIFI-13560 (first released in 2.0.0) stopped persisting values fetched from a 
Parameter Provider. The flow configuration only keeps a reference 
({{provided:parameter}}) and NiFi fetches the values again when it starts. If 
the Parameter Provider cannot be reached during that startup fetch, the 
reference is lost and the Parameters cannot recover on later restarts, even 
after the provider is healthy again.

h3. Steps to reproduce
# Configure a Parameter Provider and apply its Parameter Group so that a 
Parameter Context is bound to it. All Parameters have values.
# Make the provider unreachable and restart NiFi. The startup fetch fails, 
{{Fetched Parameters [0]}} is logged, and every provided Parameter is empty. 
This part is expected.
# Make the provider reachable again.
# Restart NiFi, as many times as you like.

h3. Actual behavior
On every restart in step 4 the provider returns all Parameters ({{Fetched 
Parameters [4]}}), but every Parameter stays empty. The only way back is *Fetch 
Parameters* followed by *Apply Changes*.

In flow.json the provided Parameters were serialized as
{code}{"name":"key1","sensitive":false,"provided":true,"value":"provided:parameter"}{code}
before step 2, and after step 2 they have *no {{value}} field at all*:
{code}{"name":"key1","sensitive":false,"provided":true}{code}

h3. Expected behavior
Once the provider is reachable again, the next restart fetches the values and 
the Parameters are populated. A failed fetch should not remove the reference to 
the provider from the flow configuration.

h3. Root cause
Two null checks run before the provided check:
# {{StandardParameterValueMapper.getMapped}} evaluates {{value == null}} before 
{{parameter.isProvided()}} (added in NIFI-13577 to avoid an NPE in the 
sensitive value encryptor). After a failed fetch the Parameter value is null, 
so the mapper returns null and the {{value}} field is omitted when flow.json is 
written.
# {{VersionedFlowSynchronizer}} (the method that builds the Parameter map from 
the serialized Parameter Context) evaluates {{rawValue == null}} before the 
provided check. A provided Parameter without a stored value is set to null 
without looking at the values fetched from the provider.

The failed fetch itself is only logged ({{Fetching Parameters for Group [...] 
from Provider [...] failed}}), then each provided Parameter logs {{Provided 
Parameter [x] not found}} and gets a null value. This happens for any provider 
whose {{fetchParameters}} throws, for example when the external service is 
unavailable during startup.

h3. Proposed fix
Evaluate {{isProvided()}} first in both places:
* {{StandardParameterValueMapper.getMapped}}: return {{provided:parameter}} for 
provided Parameters even when the value is null.
* {{VersionedFlowSynchronizer}}: for provided Parameters always use the value 
from the provider, regardless of the stored value.

With this change the flow configuration keeps {{provided:parameter}} through a 
failed fetch, and the Parameters recover on the next restart after the provider 
is back (verified on 2.12.0, see below). Non-provided Parameters are not 
affected.

h3. Verification
Tested on stock {{apache/nifi}} images, standalone, with a Parameter Provider 
that throws {{IOException}} when its backend is down. The "without fix" column 
was reproduced on both 2.0.0 and 2.12.0 with identical results; the "with fix" 
column was tested on 2.12.0:
|| Scenario || Without fix || With fix ||
| provider down, restart | Parameters empty, {{value}} dropped from flow.json | 
Parameters empty, {{provided:parameter}} kept in flow.json |
| provider up again, restart (repeat 3 times) | Parameters stay empty every 
time | Parameters populated after one restart |
| flow.json already missing {{value}} | stays empty | populated after one 
restart |

h3. Notes
* Existing unit test {{TestStandardParameterValueMapper}} covers a null value 
for a non-provided Parameter only; a provided Parameter with a null value is 
not covered.
* Related: NIFI-13560 (design), NIFI-13577 (null handling in the mapper), 
NIFI-13688 (startup ordering of provider validation).



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

Reply via email to