Skip to content

APPENG-5698: add per-user concurrent request limiting to analysis queue - #286

Merged
zvigrinberg merged 4 commits into
RHEcosystemAppEng:mainfrom
gnetanel:APPENG-5698_limit_users_requests_squashed2
Jul 28, 2026
Merged

APPENG-5698: add per-user concurrent request limiting to analysis queue#286
zvigrinberg merged 4 commits into
RHEcosystemAppEng:mainfrom
gnetanel:APPENG-5698_limit_users_requests_squashed2

Conversation

@gnetanel

Copy link
Copy Markdown
Collaborator

A single authenticated user could submit enough large SBOM analysis
requests to fill every slot in the global active-request queue,
starving all other users for up to the queue timeout (T-011).
RequestQueueService now tracks active requests per user identity in
addition to the existing global count, and rejects a user's new
submission with a UserQueueExceededException (mapped to HTTP 429)
once they hit a configurable per-user limit
(exploit-iq.queue.max-active-per-user, default 5). Pending requests
retain their owning user so the limit is still enforced when they are
promoted from the pending queue to active.

RequestQueueService: add max-active-per-user config, per-user active
tracking (activeByUser/activeUserById), and PendingRequest record to
carry user identity through the pending queue
ReportService: pass resolved user identity into queue() for both
submit() and retry(), and surface UserQueueExceededException as a
distinct report error state
ReportEndpoint/ProductEndpoint: map UserQueueExceededException to
HTTP 429 with a dedicated message
ComponentProcessingService: distinguish per-user limit errors in
component submission failure messages
AppConfig/application.properties/docs: document the new
max-active-per-user setting
In addition - max-body-size has been reduced from 300M to 90M

@vbelouso

vbelouso commented Jul 27, 2026

Copy link
Copy Markdown
Collaborator

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues
Licenses 0 0 0 0 0 issues
Code Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@gnetanel
gnetanel force-pushed the APPENG-5698_limit_users_requests_squashed2 branch from 0e1346a to c503fdf Compare July 27, 2026 11:18
…is queue

A single authenticated user could submit enough large SBOM analysis
requests to fill every slot in the global active-request queue,
starving all other users for up to the queue timeout (T-011).
RequestQueueService now tracks active requests per user identity in
addition to the existing global count, and rejects a user's new
submission with a UserQueueExceededException (mapped to HTTP 429)
once they hit a configurable per-user limit
(exploit-iq.queue.max-active-per-user, default 5). Pending requests
retain their owning user so the limit is still enforced when they are
promoted from the pending queue to active.
- RequestQueueService: add max-active-per-user config, per-user active
  tracking (activeByUser/activeUserById), and PendingRequest record to
  carry user identity through the pending queue
- ReportService: pass resolved user identity into queue() for both
  submit() and retry(), and surface UserQueueExceededException as a
  distinct report error state
- ReportEndpoint/ProductEndpoint: map UserQueueExceededException to
  HTTP 429 with a dedicated message
- ComponentProcessingService: distinguish per-user limit errors in
  component submission failure messages
- AppConfig/application.properties/docs: document the new
  max-active-per-user setting

reduce quarkus.http.limits.max-body-size from 300M to 90M.

Maximum SPDX SBOM product in redhat is 87MB… ( openshift version 4.15 ).

Add unit-tests

Fix review note 2 - sync concerns

Code review fix: Update active, activeUserById, activeByUser ConcurrentHashMap during application startup

On applicatino crash/stopped - init the active, activeUserById, activeByUser ConcurrentHashMap with the current scan on the system.

Code review fix: Use @ServerExceptionMapper for queue exceptions in ReportEndpoint

Replace duplicated try/catch blocks for RequestQueueExceededException and
UserQueueExceededException in process(), newRpmReport(), and submit() with
class-level @ServerExceptionMapper methods, matching the pattern already
used in ProductEndpoint. Ensures all three endpoints return the same 429
status and error message instead of process()/newRpmReport() using a
hardcoded message while submit() returned e.getMessage().

Fix review note bug fix: Also calculate pending user request when checking user limits

Review fix: enhance syncrnoizaton using user logk and not generic logs

Fix code review: Remove reflection from unit-tests

rebase fixes

Code review fixes

fix unit-tests

Add debug logs
@gnetanel
gnetanel force-pushed the APPENG-5698_limit_users_requests_squashed2 branch from c503fdf to bb8256f Compare July 27, 2026 11:37

@zvigrinberg zvigrinberg left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gnetanel Very good job...
Only 2 minor issues left..

Please take a look..
Thanks.

public void deleted(String id) {
LOGGER.debugf("Removed deleted report %s. Removing from active queue.", id);
active.remove(id);
removeActive(id);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gnetanel You're assuming that only active reports can be deleted, like it was before.
Let's keep it that way, but add documentation so it will be known that we're not supporting pending reports removal.

} catch (Exception e) {
// Release the slot reserved above so a failing onAdmitted callback (e.g. a failed DB
// write) doesn't permanently consume queue capacity.
if (sendNow) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gnetanel I'm missing here a warning/error log message that explains what went wrong on the onAdmiited.run() callback invocation.. ( before it's removing the slots from the queues).

@zvigrinberg zvigrinberg left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gnetanel LGTM Approved.
Thanks for the great work!.

@zvigrinberg
zvigrinberg merged commit 5c23de6 into RHEcosystemAppEng:main Jul 28, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants