feat: add computation quotas check#1013
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (24)
✅ Files skipped from review due to trivial changes (2)
🚧 Files skipped from review as they are similar to previous changes (21)
📝 WalkthroughWalkthroughThis PR adds operation-based quotas for study computations, including a new quota enum, REST quota management calls, quota enforcement in study flows, quota release in consumers, a feature flag, and matching test updates. ChangesOperation quota tracking
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ast-grep (0.44.1)src/main/java/org/gridsuite/study/server/controller/StudyController.javaast-grep timed out on this file src/main/java/org/gridsuite/study/server/service/StudyService.javaast-grep retry budget exhausted before isolating this batch src/main/java/org/gridsuite/study/server/service/UserAdminService.javaast-grep retry budget exhausted before isolating this batch
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
03724ef to
05ec476
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
src/test/java/org/gridsuite/study/server/utils/TestUtils.java (2)
239-264: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDuplicated
removeServeEventsMatchingpair across the two teardown helpers.Consider extracting a small private helper (e.g.
removeQuotaServeEvents(WireMockServer)) to avoid repeating the same two lines inassertWiremockServerRequestsEmptyThenShutdownandassertWiremockServerRequestsEmptyThenClear.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/test/java/org/gridsuite/study/server/utils/TestUtils.java` around lines 239 - 264, The two teardown helpers, assertWiremockServerRequestsEmptyThenShutdown and assertWiremockServerRequestsEmptyThenClear, repeat the same removeServeEventsMatching calls for the quota start/end URLs. Extract that duplicated logic into a small private helper such as removeQuotaServeEvents(WireMockServer) and call it from both methods so the quota-event cleanup is centralized and easier to maintain.
112-140: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winNarrow the quota-skip regex to avoid masking legitimate GET
/quota/maxverification.
"/v1/users/.*/quota/.*"also matches a GET.../quota/maxrequest, not just the start/end tracking calls it's meant to filter out. This differs from the preciseUserAdminServerStubs.QUOTA_START_URL_PATTERN/QUOTA_END_URL_PATTERN(which require a/startor/endsuffix) already imported in this file. If a future MockWebServer-based test needs to verify the max-quota check call, this broader filter would silently skip it.♻️ Suggested fix reusing the precise patterns
do { recordedRequest = Objects.requireNonNull(server.takeRequest(TIMEOUT, TimeUnit.MILLISECONDS)); // skip quota start/end requests that are auto-handled and not part of test assertions - } while (recordedRequest.getPath() != null && recordedRequest.getPath().matches("/v1/users/.*/quota/.*")); + } while (recordedRequest.getPath() != null + && (recordedRequest.getPath().matches(UserAdminServerStubs.QUOTA_START_URL_PATTERN) + || recordedRequest.getPath().matches(UserAdminServerStubs.QUOTA_END_URL_PATTERN)));Apply the same change in
getRequestsDone.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/test/java/org/gridsuite/study/server/utils/TestUtils.java` around lines 112 - 140, The quota-request filtering in TestUtils.assertRequestMatches and getRequestsDone is too broad and can accidentally skip legitimate GET /quota/max calls. Replace the generic "/v1/users/.*/quota/.*" match with the precise quota start/end patterns already available in this file via UserAdminServerStubs.QUOTA_START_URL_PATTERN and UserAdminServerStubs.QUOTA_END_URL_PATTERN, and apply the same narrowing in both helper methods.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/main/java/org/gridsuite/study/server/service/ConsumerService.java`:
- Around line 402-405: The quota release path in ConsumerService’s handler only
checks userId before calling userAdminService.endOperationWithQuota, so it can
pass a null resultUuid and build a malformed quota URL. Update the free-quota
block to require both userId and resultUuid before invoking
endOperationWithQuota, matching the guard already used in the stopped handler,
and keep the call to OperationType.mapFromComputationType(computationType)
unchanged.
---
Nitpick comments:
In `@src/test/java/org/gridsuite/study/server/utils/TestUtils.java`:
- Around line 239-264: The two teardown helpers,
assertWiremockServerRequestsEmptyThenShutdown and
assertWiremockServerRequestsEmptyThenClear, repeat the same
removeServeEventsMatching calls for the quota start/end URLs. Extract that
duplicated logic into a small private helper such as
removeQuotaServeEvents(WireMockServer) and call it from both methods so the
quota-event cleanup is centralized and easier to maintain.
- Around line 112-140: The quota-request filtering in
TestUtils.assertRequestMatches and getRequestsDone is too broad and can
accidentally skip legitimate GET /quota/max calls. Replace the generic
"/v1/users/.*/quota/.*" match with the precise quota start/end patterns already
available in this file via UserAdminServerStubs.QUOTA_START_URL_PATTERN and
UserAdminServerStubs.QUOTA_END_URL_PATTERN, and apply the same narrowing in both
helper methods.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: bd8f74b1-33af-4c41-a8f8-f55735d4b2f6
📒 Files selected for processing (24)
src/main/java/org/gridsuite/study/server/controller/StudyController.javasrc/main/java/org/gridsuite/study/server/dto/OperationType.javasrc/main/java/org/gridsuite/study/server/dto/UserProfileInfos.javasrc/main/java/org/gridsuite/study/server/error/StudyBusinessErrorCode.javasrc/main/java/org/gridsuite/study/server/service/ConsumerService.javasrc/main/java/org/gridsuite/study/server/service/StudyService.javasrc/main/java/org/gridsuite/study/server/service/UserAdminService.javasrc/main/resources/config/application.yamlsrc/test/java/org/gridsuite/study/server/NetworkModificationTest.javasrc/test/java/org/gridsuite/study/server/NodeSequenceTest.javasrc/test/java/org/gridsuite/study/server/ShortCircuitTest.javasrc/test/java/org/gridsuite/study/server/StateEstimationTest.javasrc/test/java/org/gridsuite/study/server/StudyControllerDynamicMarginCalculationTest.javasrc/test/java/org/gridsuite/study/server/StudyControllerDynamicSecurityAnalysisTest.javasrc/test/java/org/gridsuite/study/server/StudyControllerDynamicSimulationTest.javasrc/test/java/org/gridsuite/study/server/StudyServiceTest.javasrc/test/java/org/gridsuite/study/server/VoltageInitTest.javasrc/test/java/org/gridsuite/study/server/dto/OperationTypeTest.javasrc/test/java/org/gridsuite/study/server/rootnetworks/ModificationToExcludeTest.javasrc/test/java/org/gridsuite/study/server/service/StudyServiceDynamicSimulationTest.javasrc/test/java/org/gridsuite/study/server/service/UserAdminServiceTest.javasrc/test/java/org/gridsuite/study/server/utils/TestUtils.javasrc/test/java/org/gridsuite/study/server/utils/wiremock/UserAdminServerStubs.javasrc/test/resources/application-default.yml
e8a8de9 to
4de5dc8
Compare
feat: fix tests feat: add test
4de5dc8 to
b4accf1
Compare
|
etiennehomer
left a comment
There was a problem hiding this comment.
Not enough time to test and to review UT
But i'm ok with the global design
| import org.junit.jupiter.api.Test; | ||
|
|
||
| import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
|
| import static org.mockito.Mockito.times; | ||
| import static org.mockito.Mockito.verify; | ||
| import static org.mockito.Mockito.when; | ||
|
|
| private final ComputationParametersService computationParametersService; | ||
| private final UserAdminService userAdminService; | ||
|
|
||
| public ConsumerService(ObjectMapper objectMapper, |
There was a problem hiding this comment.
no indentation changes in the class plz
| notificationService.emitComputationDebugFileStatus(studyUuid, receiverObj.getNodeUuid(), receiverObj.getRootNetworkUuid(), computationType, userId, resultUuid, errorMessage); | ||
| })); | ||
| // free quota | ||
| if (userId != null) { |
There was a problem hiding this comment.
In debug mode, at the end of the computation, you'll receive 2 notifications :
- the classic one that says that the computation is done
- the one that said that the debug zip is ready for download.
So you should notendOperationWithQuota()in consumeCalculationDebug(). That would free twice
| private final StudyService self; | ||
|
|
||
| @Value("${study.enable-operation-quotas}") | ||
| private boolean shouldCheckOperationQuotas = true; |
There was a problem hiding this comment.
The default value in the application.yaml is enough ?
| new LoadFlowService.ParametersInfos(lfParametersUuid, withRatioTapChangers, isSecurityNode), lfReportUuid, userId); | ||
| rootNetworkNodeInfoService.updateLoadflowResultUuid(nodeUuid, rootNetworkUuid, result, withRatioTapChangers); | ||
|
|
||
| userAdminService.startOperationWithQuota(userId, OperationType.mapFromComputationType(LOAD_FLOW), result); |
There was a problem hiding this comment.
we keep the startOperationWithQuota() in StudyService and not LoadflowService.runLoadflow() ?
This would allow to write some code that call runLoadflow() and do not call startOperationWithQuota()
But maybe StudyService is fine
| notificationService.emitRootNetworksUpdated(studyUuid); | ||
| } | ||
|
|
||
| public void assertOnQuotasAvailability(ComputationType computationType, String userId) { |
There was a problem hiding this comment.
This method could be just a call to a user-admin-server endpoint that returns true/false (computation allowed or not)
But you did this in anticipation of the coming front giving the quota information to the users ? Makes sense in that case
| DYNAMIC_SECURITY, | ||
| DYNAMIC_MARGIN; | ||
|
|
||
| public static OperationType mapFromComputationType(ComputationType computationType) { |
There was a problem hiding this comment.
keep same enum labels between ComputationType and OperationType
| /** | ||
| * @author Ghiles Abdellah {@literal <ghiles.abdellah at rte-france.com>} | ||
| */ | ||
| public enum OperationType { |
There was a problem hiding this comment.
QuotaType ? Another name ?
Because cases and builds are not operation. They static stuff staying in the system
There was a problem hiding this comment.
And is it ok to use the same enum for elements that have quotas but different nature (number of LF at the same time VS number of cases stored in the system)



PR Summary