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

Mark Payne updated NIP-40:
--------------------------
    Description: 
h2. Motivation

Several small, related gaps in the Content Repository and FlowFile Repository
API (nifi-framework-api) make it harder than necessary to implement t he 
repository interfaces and to reason about repository behavior. This NIP
groups a few backward-compatible cleanups to that API.
 # *No component or Connector context on writes.* When a ProcessSession creates 
content or commits FlowFile changes, it calls {{{}ContentRepository.create(...) 
and FlowFileRepository.updateRepository(...){}}}. Neither call tells the 
repository which component the session is acting on behalf of, nor which 
Connector (managed flow) that component belongs to, so the repository cannot 
attribute an operation to a component or organize data by Connector. There have 
been several instances when I wanted to know which component a Content Claim 
was for; e.g., if we know that it's for a Processor that statistically will 
create large FlowFiles we may not want to append its content to an existing 
Resource Claim but instead create a new Resource Claim. This would help avoid 
scenarios where Content Repository holds onto a large file just because one 
small FlowFile shares the same Resource Claim.
 # *The session depends on framework-internal stream classes.*
{{StandardProcessSession}} reads content through 
{{{}ContentClaimInputStream{}}}, and the write cache reuses claims through 
{{{}ContentClaimOutputStream.newContentClaim(){}}}. These abstractions are good 
and make sense, but both classes live in framework internals 
(nifi-framework-components), not in the more public {{{}nifi-framework-api{}}}, 
so a repository that wants to provide its own read stream or claim-reuse 
behavior has no public abstraction to implement and must bind to framework 
internals.
 # *Content Repository should own the maximum appendable claim size.* The claim 
rollover size is read from the {{nifi.content.claim.max.appendable.size}} 
property and threaded to the write cache, while a repository that has its own 
notion of where a storage unit ends has no way to declare it. The two values 
must be kept consistent by hand. While participation from Process Session is 
necessary for the max appendable size to work properly, it should be the 
responsibility of the pluggable {{ContentRepository}} to dictate what max size 
should be used.

h2. Proposed Solution

Three backward-compatible additions to the repository SPI:
 * *Component/Connector context.* Pass a small, immutable context object on 
each create/update describing the component and Connector the session is acting 
for. It is populated by the framework and passed straight through; stock 
repositories ignore it.
 * *Public stream abstractions.* Expose the content-claim input-stream 
abstraction and the output-stream claim-reuse contract in nifi-framework-api, 
and have {{StandardProcessSession}} and the write cache depend on those public 
types rather than the framework-internal classes.
 * *Repository-owned appendable size.* Let {{ContentRepository}} report its 
maximum appendable claim size, and have the framework source the rollover size 
from the repository. The existing property remains the default the stock 
repository reports. All additions are default methods or newly exposed types; 
no existing type or method is removed, changed, or deprecated. The stock 
FileSystemRepository and WriteAheadFlowFileRepository behave exactly as they do 
today.
h2. Framework API Changes (nifi-framework-api)

*Component/Connector context*
 * New {{LossTolerance}} enum ({{{}LOSS_TOLERANT{}}}, {{{}LOSS_INTOLERANT{}}}). 
While we could keep with the existing {{boolean lossTolerant}} the general 
pattern that NiFi has tended toward is to drop booleans in interfaces/APIs in 
favor of more descriptive enums.
 * New {{ContentClaimCreationContext}} (component id, Connector id, loss 
tolerance) and {{FlowFileUpdateContext}} (component id, Connector id).
 * New {{default}} {{ContentRepository.create(ContentClaimCreationContext)}} 
and {{{}FlowFileRepository.updateRepository(Collection<RepositoryRecord>, 
FlowFileUpdateContext){}}}, each delegating to the existing method.{*}{{*}}

 

*Public stream abstractions*
 * Relocate {{ContentClaimInputStream}} and {{ContentClaimOutputStream}} from 
{{nifi-framework-components}} to {{nifi-framework-api}}

*Repository-owned appendable size*
 * New {{default}} {{ContentRepository.getMaxAppendableClaimBytes()}} returning 
the configured default (so stock behavior is unchanged); the framework sources 
the rollover size from the repository. The value must be a cheap in-memory read,
since it is consulted on the write hot path. The existing 
{{{}create(boolean){}}}, {{{}updateRepository(Collection){}}}, and the 
{{nifi.content.claim.max.appendable.size}} property are all retained and not 
deprecated.

  was:
h2. Motivation

Several small, related gaps in the Content Repository and FlowFile Repository
API (nifi-framework-api) make it harder than necessary to implement t he 
repository interfaces and to reason about repository behavior. This NIP
groups a few backward-compatible cleanups to that API.
 # *No component or Connector context on writes.* When a ProcessSession creates 
content or commits FlowFile changes, it calls {{ContentRepository.create(...) 
}}and {{{}FlowFileRepository.updateRepository(...){}}}. Neither call tells the 
repository which component the session is acting on behalf of, nor which 
Connector (managed flow) that component belongs to, so the repository cannot 
attribute an operation to a component or organize data by Connector. There have 
been several instances when I wanted to know which component a Content Claim 
was for; e.g., if we know that it's for a Processor that statistically will 
create large FlowFiles we may not want to append its content to an existing 
Resource Claim but instead create a new Resource Claim. This would help avoid 
scenarios where Content Repository holds onto a large file just because one 
small FlowFile shares the same Resource Claim.
 # *The session depends on framework-internal stream classes.*
{{StandardProcessSession}} reads content through 
{{{}ContentClaimInputStream{}}}, and the write cache reuses claims through 
{{{}ContentClaimOutputStream.newContentClaim(){}}}. These abstractions are good 
and make sense, but both classes live in framework internals 
(nifi-framework-components), not in the more public {{{}nifi-framework-api{}}}, 
so a repository that wants to provide its own read stream or claim-reuse 
behavior has no public abstraction to implement and must bind to framework 
internals.
 # *Content Repository should own the maximum appendable claim size.* The claim 
rollover size is read from the {{nifi.content.claim.max.appendable.size}} 
property and threaded to the write cache, while a repository that has its own 
notion of where a storage unit ends has no way to declare it. The two values 
must be kept consistent by hand. While participation from Process Session is 
necessary for the max appendable size to work properly, it should be the 
responsibility of the pluggable {{ContentRepository}} to dictate what max size 
should be used.

h2. Proposed Solution

Three backward-compatible additions to the repository SPI:
 * *Component/Connector context.* Pass a small, immutable context object on 
each create/update describing the component and Connector the session is acting 
for. It is populated by the framework and passed straight through; stock 
repositories ignore it.
 * *Public stream abstractions.* Expose the content-claim input-stream 
abstraction and the output-stream claim-reuse contract in nifi-framework-api, 
and have {{StandardProcessSession}} and the write cache depend on those public 
types rather than the framework-internal classes.
 * *Repository-owned appendable size.* Let {{ContentRepository}} report its 
maximum appendable claim size, and have the framework source the rollover size 
from the repository. The existing property remains the default the stock 
repository reports. All additions are default methods or newly exposed types; 
no existing type or method is removed, changed, or deprecated. The stock 
FileSystemRepository and WriteAheadFlowFileRepository behave exactly as they do 
today.
h2. Framework API Changes (nifi-framework-api)

*Component/Connector context*
 * New {{LossTolerance}} enum ({{{}LOSS_TOLERANT{}}}, {{{}LOSS_INTOLERANT{}}}). 
While we could keep with the existing {{boolean lossTolerant}} the general 
pattern that NiFi has tended toward is to drop booleans in interfaces/APIs in 
favor of more descriptive enums.
 * New {{ContentClaimCreationContext}} (component id, Connector id, loss 
tolerance) and {{FlowFileUpdateContext}} (component id, Connector id).
 * New {{default}} {{ContentRepository.create(ContentClaimCreationContext)}} 
and {{{}FlowFileRepository.updateRepository(Collection<RepositoryRecord>, 
FlowFileUpdateContext){}}}, each delegating to the existing method.{*}{{*}}

 

*Public stream abstractions*
 * Relocate {{ContentClaimInputStream}} and {{ContentClaimOutputStream}} from 
{{nifi-framework-components}} to {{nifi-framework-api}}

*Repository-owned appendable size*
 * New {{default}} {{ContentRepository.getMaxAppendableClaimBytes()}} returning 
the configured default (so stock behavior is unchanged); the framework sources 
the rollover size from the repository. The value must be a cheap in-memory read,
since it is consulted on the write hot path. The existing 
{{{}create(boolean){}}}, {{{}updateRepository(Collection){}}}, and the 
{{nifi.content.claim.max.appendable.size}} property are all retained and not 
deprecated.


> Content and FlowFile Repository API Cleanup
> -------------------------------------------
>
>                 Key: NIP-40
>                 URL: https://issues.apache.org/jira/browse/NIP-40
>             Project: NiFi Improvement Proposal
>          Issue Type: Improvement
>            Reporter: Mark Payne
>            Assignee: Mark Payne
>            Priority: Major
>
> h2. Motivation
> Several small, related gaps in the Content Repository and FlowFile Repository
> API (nifi-framework-api) make it harder than necessary to implement t he 
> repository interfaces and to reason about repository behavior. This NIP
> groups a few backward-compatible cleanups to that API.
>  # *No component or Connector context on writes.* When a ProcessSession 
> creates content or commits FlowFile changes, it calls 
> {{{}ContentRepository.create(...) and 
> FlowFileRepository.updateRepository(...){}}}. Neither call tells the 
> repository which component the session is acting on behalf of, nor which 
> Connector (managed flow) that component belongs to, so the repository cannot 
> attribute an operation to a component or organize data by Connector. There 
> have been several instances when I wanted to know which component a Content 
> Claim was for; e.g., if we know that it's for a Processor that statistically 
> will create large FlowFiles we may not want to append its content to an 
> existing Resource Claim but instead create a new Resource Claim. This would 
> help avoid scenarios where Content Repository holds onto a large file just 
> because one small FlowFile shares the same Resource Claim.
>  # *The session depends on framework-internal stream classes.*
> {{StandardProcessSession}} reads content through 
> {{{}ContentClaimInputStream{}}}, and the write cache reuses claims through 
> {{{}ContentClaimOutputStream.newContentClaim(){}}}. These abstractions are 
> good and make sense, but both classes live in framework internals 
> (nifi-framework-components), not in the more public 
> {{{}nifi-framework-api{}}}, so a repository that wants to provide its own 
> read stream or claim-reuse behavior has no public abstraction to implement 
> and must bind to framework internals.
>  # *Content Repository should own the maximum appendable claim size.* The 
> claim rollover size is read from the 
> {{nifi.content.claim.max.appendable.size}} property and threaded to the write 
> cache, while a repository that has its own notion of where a storage unit 
> ends has no way to declare it. The two values must be kept consistent by 
> hand. While participation from Process Session is necessary for the max 
> appendable size to work properly, it should be the responsibility of the 
> pluggable {{ContentRepository}} to dictate what max size should be used.
> h2. Proposed Solution
> Three backward-compatible additions to the repository SPI:
>  * *Component/Connector context.* Pass a small, immutable context object on 
> each create/update describing the component and Connector the session is 
> acting for. It is populated by the framework and passed straight through; 
> stock repositories ignore it.
>  * *Public stream abstractions.* Expose the content-claim input-stream 
> abstraction and the output-stream claim-reuse contract in nifi-framework-api, 
> and have {{StandardProcessSession}} and the write cache depend on those 
> public types rather than the framework-internal classes.
>  * *Repository-owned appendable size.* Let {{ContentRepository}} report its 
> maximum appendable claim size, and have the framework source the rollover 
> size from the repository. The existing property remains the default the stock 
> repository reports. All additions are default methods or newly exposed types; 
> no existing type or method is removed, changed, or deprecated. The stock 
> FileSystemRepository and WriteAheadFlowFileRepository behave exactly as they 
> do today.
> h2. Framework API Changes (nifi-framework-api)
> *Component/Connector context*
>  * New {{LossTolerance}} enum ({{{}LOSS_TOLERANT{}}}, 
> {{{}LOSS_INTOLERANT{}}}). While we could keep with the existing {{boolean 
> lossTolerant}} the general pattern that NiFi has tended toward is to drop 
> booleans in interfaces/APIs in favor of more descriptive enums.
>  * New {{ContentClaimCreationContext}} (component id, Connector id, loss 
> tolerance) and {{FlowFileUpdateContext}} (component id, Connector id).
>  * New {{default}} {{ContentRepository.create(ContentClaimCreationContext)}} 
> and {{{}FlowFileRepository.updateRepository(Collection<RepositoryRecord>, 
> FlowFileUpdateContext){}}}, each delegating to the existing method.{*}{{*}}
>  
> *Public stream abstractions*
>  * Relocate {{ContentClaimInputStream}} and {{ContentClaimOutputStream}} from 
> {{nifi-framework-components}} to {{nifi-framework-api}}
> *Repository-owned appendable size*
>  * New {{default}} {{ContentRepository.getMaxAppendableClaimBytes()}} 
> returning the configured default (so stock behavior is unchanged); the 
> framework sources the rollover size from the repository. The value must be a 
> cheap in-memory read,
> since it is consulted on the write hot path. The existing 
> {{{}create(boolean){}}}, {{{}updateRepository(Collection){}}}, and the 
> {{nifi.content.claim.max.appendable.size}} property are all retained and not 
> deprecated.



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

Reply via email to