[ 
https://issues.apache.org/jira/browse/NIP-50?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Mark Payne resolved NIP-50.
---------------------------
    Resolution: Fixed

Given the lazy consensus vote 
([https://lists.apache.org/thread/pcxgkbjg498m1sfwj6onl7hkpj80tj19)] this NIP 
has been approved.

> Partial Component State Updates
> -------------------------------
>
>                 Key: NIP-50
>                 URL: https://issues.apache.org/jira/browse/NIP-50
>             Project: NiFi Improvement Proposal
>          Issue Type: Improvement
>            Reporter: Mark Payne
>            Assignee: Mark Payne
>            Priority: Major
>
> h2. Motivation
> {{setState}} and {{replace}} replace the entire state map. To change one key, 
> a component must get the map, copy it, change the key, and write the whole 
> map back. That is more code than the change needs, and two writers doing it 
> at the same time can drop each other's keys.
> Many components store independent keys in one map (one per table, partition, 
> or cursor) and often change only a few of them. A method that accepts just 
> those keys is simpler to use. It also lets a state store persist only what 
> changed, which can be cheaper when the map is large.
> h2. Proposed Solution
> Add one method to both {{ProcessSession}} and {{StateManager}}:
> {code:java}
> void patchState(Map<String, String> updatedState, Scope scope) throws 
> IOException;
> {code}
> The map is a patch, not a full replacement:
> * Present keys with a non-null value are created or overwritten.
> * Present keys with a {{null}} value are removed. Removing a key that is not 
> there is a no-op. An empty string is stored; it does not remove the key.
> * Keys that are not in the map are left as they are.
> If no state is stored yet ({{StateMap}} version {{-1}}), the call matches 
> {{setState}} after {{null}} values are dropped.
> A {{null}} map is not allowed. An empty map is a no-op: no write and no 
> version change.
> {{ProcessSession.patchState}} follows the same commit rules as {{setState}}: 
> the patch is cached on the session, {{getState}} in that session sees it, and 
> it is published on commit only if it is still the latest remote state. 
> Rollback discards it. A second {{patchState}} in the same session applies on 
> top of the first cached result.
> A default implementation is provided on both interfaces. Existing 
> {{StateManager}} and {{ProcessSession}} implementations stay 
> source-compatible. The default gets the current state, copies it into a new 
> {{HashMap}}, applies the patch, and calls {{replace}} until that succeeds:
> {code}
> StateMap current;
> do {
>     current = getState(scope);
>     Map<String, String> updated = new HashMap<>(current.toMap());
>     for (each key/value in updatedState) {
>         if (value is null) {
>             updated.remove(key);
>         } else {
>             updated.put(key, value);
>         }
>     }
> } while (!replace(current, updated, scope));
> {code}
> On {{ProcessSession}}, {{replace}} is {{replaceState}}. {{getState}} and 
> {{replaceState}} already see session-cached state, so the same loop honors 
> commit and rollback.
> h2. NiFi API Changes
> New default methods on {{org.apache.nifi.processor.ProcessSession}} and 
> {{org.apache.nifi.components.state.StateManager}}, using the loop above.
> {{StateTooLargeException}} still applies to the map after the patch is 
> applied.
> Backward compatible: additive default methods only.
> h2. Voting Period
> This NIP is proposed with a 24-hour lazy consensus voting period.



--
This message was sent by Atlassian Jira
(v10.3.26#10030026)

Reply via email to