[
https://issues.apache.org/jira/browse/NIP-38?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Mark Payne reassigned NIP-38:
-----------------------------
Assignee: Mark Payne
> Pluggable Flow Persistence and Audit Storage
> --------------------------------------------
>
> Key: NIP-38
> URL: https://issues.apache.org/jira/browse/NIP-38
> Project: NiFi Improvement Proposal
> Issue Type: Improvement
> Reporter: Mark Payne
> Assignee: Mark Payne
> Priority: Major
>
> h2. Motivation
> Two parts of the NiFi framework are hardcoded to read and write local files,
> with no way to redirect that storage elsewhere.
> The first is the dataflow itself, which is always persisted to a local file
> as GZIP-compressed JSON ({{{}flow.json.gz{}}}). Some deployments would
> benefit from the ability to store the flow somewhere other than a local file,
> and there is currently no extension point that lets the mechanism for loading
> and saving the flow be replaced. This coupling also appears in components
> that only need to read a small part of the flow. For example,
> {{FileAccessPolicyProvider}} parses {{flow.json.gz}} directly to obtain the
> root process group identifier when seeding initial access policies.
> The second is the flow-change history (the audit trail of who changed what in
> the flow), which is written to an embedded database under
> {{{}nifi.database.directory{}}}. This history is stored by the
> {{{}AuditService{}}}. An {{AuditService}} interface already exists, but the
> framework constructs the {{EntityStoreAuditService}} implementation directly,
> so there is no way to store this history anywhere other than the local
> embedded database.
> This NIP makes both storage mechanisms pluggable, using the same extension
> pattern for each.
> h2. Proposed Solution
> h3. Flow Persistence Provider
> Introduce a {{FlowPersistenceProvider}} extension point in
> {{{}nifi-framework-api{}}}. A single provider is selected per instance and is
> responsible for loading and saving the dataflow. The provider should operate
> on {{{}VersionedDataflow{}}}; the encoding of the flow and the mechanism used
> to store it are entirely the provider's concern.
> {code:java}
> /**
> * Persists and restores the dataflow for a NiFi instance. A single provider
> is selected per
> * instance and is responsible for durably storing the flow so that it can be
> recovered when
> * NiFi restarts. The encoding of the flow and the mechanism used to store it
> are entirely the
> * provider's concern.
> */
> public interface FlowPersistenceProvider {
> /**
> * Called once after instantiation to provide the provider with its
> configuration.
> */
> void initialize(FlowPersistenceProviderInitializationContext
> initializationContext) throws IOException;
> /**
> * Loads the currently persisted flow, or an empty Optional when no flow
> has been persisted.
> */
> Optional<VersionedDataflow> loadFlow() throws IOException;
> /**
> * Persists the flow described by the given context, replacing any
> previously persisted flow.
> */
> void saveFlow(FlowPersistenceContext context) throws IOException;
> }
> {code}
> {{saveFlow}} accepts a {{FlowPersistenceContext}} rather than a bare
> {{VersionedDataflow}} so that additional detail about the save — for example
> a human-readable description of what changed — can be added later without
> breaking existing providers.
> {{VersionedDataflow}} and {{VersionedFlowEncodingVersion}} move from
> {{nifi-framework-core-api}} into {{nifi-framework-api}} so the extension
> point can expose a typed API.
> A default {{StandardFlowPersistenceProvider}} in {{nifi-framework-core}}
> persists the flow as GZIP-compressed JSON to the configured flow
> configuration file.
> h3. Audit Service
> Make the {{AuditService}} a selectable extension point. The interface moves
> from {{nifi-administration}} into {{nifi-framework-api}} so that
> implementations can be delivered in NARs, and it gains a default
> {{initialize}} method that receives the implementation's configuration.
> {code:java}
> /**
> * Called once after instantiation to provide the Audit Service with its
> configuration. The
> * default implementation does nothing so that existing implementations
> continue to work
> * unchanged.
> */
> default void initialize(AuditServiceInitializationContext
> initializationContext) throws IOException {
> }
> {code}
> The implementation to use is selected in {{nifi.properties}} and defaults to
> {{{}EntityStoreAuditService{}}}, which stores the flow-change history in the
> existing embedded database. The directory the default implementation uses is
> supplied through its initialization context, so the storage location is
> configuration rather than a hardcoded file reference.
> h2. Framework Changes
> * New {{FlowPersistenceProvider}} extension point and supporting context
> types in {{{}nifi-framework-api{}}}.
> * {{VersionedDataflow}} and {{VersionedFlowEncodingVersion}} move from
> {{nifi-framework-core-api}} to {{{}nifi-framework-api{}}}.
> * Default {{StandardFlowPersistenceProvider}} plus its extension-discovery
> and dependency-injection wiring in {{{}nifi-framework-core{}}}.
> * Every point at which the framework saves the flow, and every point at
> which it restores the flow, goes through the provider.
> * {{FileAccessPolicyProvider}} obtains the root process group identifier
> from the provider rather than reading {{flow.json.gz}} directly.
> * The previous {{FlowConfigurationDAO}} / {{StandardFlowConfigurationDAO}} /
> {{FlowParser}} / {{FlowInfo}} code path is removed.
> * {{AuditService}} (and its supporting types {{{}History{}}},
> {{{}HistoryQuery{}}}, {{{}PreviousValue{}}}) move from
> {{nifi-administration}} to {{{}nifi-framework-api{}}}, and the interface
> gains a default {{initialize}} method plus an
> {{{}AuditServiceInitializationContext{}}}.
> * The {{AuditService}} implementation is created through extension-discovery
> and dependency-injection wiring in {{nifi-framework-core}} instead of being
> constructed directly.
> * {{EntityStoreAuditService}} reads its storage directory from its
> initialization context rather than from a hardcoded location.
> h2. nifi.properties Configuration
> * {{nifi.flow.persistence.provider.implementation}} — fully qualified class
> name of the {{FlowPersistenceProvider}} to use. Default:
> {{{}org.apache.nifi.controller.flow.StandardFlowPersistenceProvider{}}}.
> * {{nifi.flow.persistence.provider.properties.<name>}} — provider-specific
> configuration, passed to the provider through its initialization context.
> * {{nifi.audit.service.implementation}} — fully qualified class name of the
> {{AuditService}} to use. Default:
> {{{}org.apache.nifi.admin.service.EntityStoreAuditService{}}}.
> * {{nifi.audit.service.properties.<name>}} — implementation-specific
> configuration, passed to the Audit Service through its initialization context.
> The existing {{{}nifi.flow.configuration.file{}}},
> {{{}nifi.flow.configuration.archive.*{}}}, and {{nifi.database.directory}}
> properties are honored as fallbacks.
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)