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

Jannik Rebmann updated NIFI-16359:
----------------------------------
    Summary: Git Flow Registry Clients: Cache commit listing per (path, branch) 
to remove per-process-group API load  (was: Port GitHubFlowRegistryClient 
API-call optimizations (NIFI-14837) to GitLabFlowRegistryClient)

> Git Flow Registry Clients: Cache commit listing per (path, branch) to remove 
> per-process-group API load
> -------------------------------------------------------------------------------------------------------
>
>                 Key: NIFI-16359
>                 URL: https://issues.apache.org/jira/browse/NIFI-16359
>             Project: Apache NiFi
>          Issue Type: Improvement
>          Components: Flow Versioning
>    Affects Versions: 2.12.0
>            Reporter: Jannik Rebmann
>            Priority: Major
>
> h2. Summary
> GitLabFlowRegistryClient against a self-hosted GitLab instance generates high 
> load on the
> GitLab server as the number of versioned process groups grows. The load does 
> not come from
> one expensive operation but from a per-process-group multiplier on the 
> version-check path,
> compounded by a GitLab-specific full-history listing. This ticket proposes 
> removing that
> multiplier at the shared base-class level so all Git-based registry clients 
> benefit.
> h2. Environment / Observation
> Self-hosted GitLab, many versioned process groups. Our infrastructure team 
> flagged a high
> volume of GitLab REST API calls (repository/commits, repository/tree, 
> repository/files)
> originating from NiFi. The volume scales with the number of versioned process 
> groups, even
> when most of them are bound to the *same* flow at the *same* version.
> h2. Root cause
> The dominant driver is a per-process-group multiplier, not the cost of a 
> single listing:
> 1. The periodic "up to date" check and version listing run {*}per process 
> group{*}. In
> AbstractGitFlowRegistryClient, getLatestVersion(...), getFlowVersions(...) 
> and the
> latest-version comparison in getFlowContents(...) all call
> repositoryClient.getCommits(filePath, branch). With N process groups bound to 
> the same
> flow (identical filePath+branch), each cycle issues N identical 
> repository/commits
> requests. There is no deduplication across process groups.
> 2. repositoryClient is a singleton: getRepositoryClient(context) builds the 
> client once
> (guarded by clientInitialized) and reuses the volatile instance. A cache 
> placed on the
> base class is therefore shared across every process group using the component 
> - i.e. the
> multiplier can be removed with a shared, in-memory cache.
> 3. GitLab-specific amplification: GitLabRepositoryClient.getCommits(path, 
> branch) uses the
> gitlab4j List overload that delegates to Pager.all(), which pages the 
> *entire* commit
> history for the path (the client sets per_page=100). Each of the N calls 
> above is thus
> itself several page requests.
> 4. Content resolution (repository/tree, repository/files) is likewise 
> performed per process
> group when materializing a version.
> h2. Relationship to NIFI-14837 / PR #10186
> NIFI-14837 (fixed in 2.6.0, PR #10186) improved the GitHub client by (a) 
> limiting the commit
> listing to the first page and (b) adding an in-memory SHA->commit-detail 
> cache. Two points:
>  * Those changes were applied only to GitHubRepositoryClient. GitLab has 
> neither, and
> additionally pages the full history (point 3 above).
>  * PR #10186 reduced GitHub load from O(processGroups x commits) to 
> O(processGroups): it
> removed the full-history paging and the per-commit N+1 detail fetch. It did 
> NOT remove the
> per-process-group multiplier - GitHubRepositoryClient.getCommits(path, 
> branch) still issues
> a live getRef + first-page listing on every call, with no (path, branch) 
> cache and no TTL.
> This simply was not visible at a small number of process groups. So GitHub 
> scales linearly
> with process-group count as well.
>  * The SHA->commit-detail cache is not the load-bearing part for GitLab. 
> gitlab4j's commit
> listing returns fully-populated Commit objects (author, message, 
> committed_date inline),
> so there is no per-commit detail call to eliminate. Porting that cache 1:1 to 
> GitLab would
> add a dependency and complexity without reducing API calls.
> h2. Proposed solution
> 1. Primary, general fix - cache the commit listing at the base class. Add a 
> short-TTL,
> size-bounded in-memory cache keyed by (filePath, branch) in 
> AbstractGitFlowRegistryClient,
> wrapping the getCommits calls in getLatestVersion / getFlowVersions / 
> getFlowContents.
> This collapses the per-process-group calls to one remote call per (flow, 
> branch) per TTL
> window and benefits all Git clients (GitHub, GitLab, Bitbucket, Azure 
> DevOps). TTL bounds
> the staleness for detecting a *remote* new version; invalidate eagerly on 
> local writes
> (createContent, deleteContent) and on client (re)initialization so locally 
> committed
> versions are visible immediately. TTL and size hard-coded initially; can be 
> promoted to
> properties in a follow-up.
> 2. GitLab-specific - bound the commit listing to the first page (a small 
> COMMIT_PAGE_SIZE)
> instead of Pager.all(), to stop full-history paging and cap payload size, 
> mirroring the
> listing limit from PR #10186.
> 3. Optional follow-up - immutable content cache. For the repository/tree and
> repository/files load, add a cache keyed by (commitSha, path). Content at a 
> fixed SHA is
> immutable, so this can be cached without a TTL.
> h2. Scope question for reviewers
> The primary fix lives in the shared base class and benefits all four Git 
> clients, so this
> ticket's scope effectively broadens beyond GitLab. Should NIFI-16359 own the 
> base-class
> caching (with GitLab as the motivating case), or should the base-class change 
> be split into a
> dedicated framework ticket that per-client tickets reference? Input welcome 
> before
> implementation.
> h2. References
> NIFI-14837, PR [https://github.com/apache/nifi/pull/10186]



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

Reply via email to