Skip to content

New notification on study creation#981

Merged
antoinebhs merged 5 commits intomainfrom
new-notif-study-creation
Apr 29, 2026
Merged

New notification on study creation#981
antoinebhs merged 5 commits intomainfrom
new-notif-study-creation

Conversation

@antoinebhs
Copy link
Copy Markdown
Contributor

@antoinebhs antoinebhs commented Apr 27, 2026

PR Summary

Introduce a distinct notification on study creation to avoid race condition in directory server.
In the current code:

  • directory server emits a notif on study creation
  • study server emits a notif on study creation (resent by directory server if the study element is created in directory DB)
  • study server emits a notif on study creation done (resent by directory server)
    Sometimes we have 3 notifications (if the creation notif from study server arrives after the element is created in directory DB), sometimes 2 if not already created.

Instead of this system that leads to notification race conditions, I only rely on the notification of directory server and study creation finished. The study creation started notif is not consumed by directory server.
Relates to gridsuite/directory-server#244

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 27, 2026

📝 Walkthrough

Walkthrough

The notification message contract for study-creation events is refactored from a single generic update type to two distinct lifecycle types: studyCreationStarted and studyCreationFinished. The methods emitStudiesChanged and constant UPDATE_TYPE_STUDIES are removed and replaced with explicit lifecycle notification methods and constants across the service and test layers.

Changes

Cohort / File(s) Summary
Notification Service Core
src/main/java/org/gridsuite/study/server/notification/NotificationService.java
Replaced generic UPDATE_TYPE_STUDIES constant and emitStudiesChanged() method with two lifecycle-specific constants (UPDATE_TYPE_STUDY_CREATION_STARTED, UPDATE_TYPE_STUDY_CREATION_FINISHED) and corresponding notification methods. Updated emitStudyCreationError() to emit UPDATE_TYPE_STUDY_CREATION_FINISHED instead of the removed generic type.
Service Integration
src/main/java/org/gridsuite/study/server/service/StudyService.java
Updated study creation flow to emit emitStudyCreationStarted() on request insertion and emitStudyCreationFinished() on completion (both direct and asynchronous duplication paths), replacing the previous emitStudiesChanged() calls.
Test Suite Updates
src/test/java/org/gridsuite/study/server/rootnetworks/RootNetworkControllerTest.java, src/test/java/org/gridsuite/study/server/studycontroller/StudyControllerCreationTest.java, src/test/java/org/gridsuite/study/server/studycontroller/StudyTest.java, src/test/java/org/gridsuite/study/server/studycontroller/StudyTestBase.java
Updated test assertions to verify the new two-phase lifecycle notification sequence: expecting UPDATE_TYPE_STUDY_CREATION_STARTED for initial messages and UPDATE_TYPE_STUDY_CREATION_FINISHED for completion/error messages. Refactored assertion helpers to validate the specific update types.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: introducing distinct notifications for study creation lifecycle events to resolve race conditions.
Description check ✅ Passed The description is directly related to the changeset, explaining the motivation (race condition avoidance) and detailing how the notification flow changes from generic to lifecycle-specific events.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

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.42.1)
src/main/java/org/gridsuite/study/server/service/StudyService.java

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@antoinebhs antoinebhs force-pushed the new-notif-study-creation branch from 748b0ff to 7a8706f Compare April 28, 2026 07:05
@antoinebhs antoinebhs changed the title New notifications on study creation New notification on study creation Apr 28, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/test/java/org/gridsuite/study/server/studycontroller/StudyControllerCreationTest.java (1)

320-327: Optional: add a null guard before reading message payload/headers.

In async broker tests, a timeout currently fails with a less-informative NPE. An explicit null assertion improves diagnosis.

Proposed tweak
 private void assertStudyCreationMessageReceived(UUID studyUuid, String userId, String expectedUpdateType) {
     Message<byte[]> message = output.receive(TIMEOUT, studyUpdateDestination);
+    assertThat(message).as("Expected study.update message with updateType=%s", expectedUpdateType).isNotNull();
     assertEquals("", new String(message.getPayload()));
     MessageHeaders headers = message.getHeaders();
     assertEquals(userId, headers.get(HEADER_USER_ID));
     assertEquals(studyUuid, headers.get(NotificationService.HEADER_STUDY_UUID));
     assertEquals(expectedUpdateType, headers.get(HEADER_UPDATE_TYPE));
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/test/java/org/gridsuite/study/server/studycontroller/StudyControllerCreationTest.java`
around lines 320 - 327, The test helper assertStudyCreationMessageReceived
should guard against a timed-out receive returning null: after calling
output.receive(TIMEOUT, studyUpdateDestination) assert the returned Message is
not null (and fail with a clear message), then assert the payload is not null
before converting to String and assert that headers (MessageHeaders) are not
null before reading HEADER_USER_ID, NotificationService.HEADER_STUDY_UUID and
HEADER_UPDATE_TYPE; update the method (referencing output, TIMEOUT,
studyUpdateDestination, Message, MessageHeaders, HEADER_USER_ID,
NotificationService.HEADER_STUDY_UUID, HEADER_UPDATE_TYPE) to perform these null
checks and use assertNotNull with a helpful message so an NPE is avoided and
test failures are descriptive.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/java/org/gridsuite/study/server/service/StudyService.java`:
- Around line 799-803: Wrap the call to
notificationService.emitStudyCreationStarted(...) inside a try-catch in
insertStudyCreationRequest so a publishing failure cannot leave a persisted
orphan; after creating newStudy via insertStudyCreationRequestEntity(...),
attempt the emit in try and on any RuntimeException perform a compensated
cleanup (either call an existing deleteStudyCreationRequest(newStudy.getId()) or
studyCreationRequestRepository.deleteById(newStudy.getId()); if deletion API
doesn't exist, update the persisted entity to a FAILED/ROLLED_BACK status via
updateStudyCreationRequestStatus(newStudy.getId(), FAILED)) and log the error;
rethrow or return a clear failure as appropriate for caller behavior.

In `@src/test/java/org/gridsuite/study/server/studycontroller/StudyTest.java`:
- Around line 484-485: The test currently asserts only the studyCreationStarted
update; add a second assertion to consume the next message and verify the
terminal update equals the finished event used by the other failure-path tests:
fetch the next message (same way the test retrieved the first), extract headers,
and assertEquals(NotificationService.UPDATE_TYPE_STUDY_CREATION_FINISHED,
headers.get(HEADER_UPDATE_TYPE)) to mirror the behavior produced by
emitStudyCreationError(); place this immediately after the existing
started-event assertion in StudyTest so the lifecycle is fully validated like
testCreateStudyCreationFailedWithoutErrorMessage/testCreateStudyCreationFailedWithStudyCreationError.

---

Nitpick comments:
In
`@src/test/java/org/gridsuite/study/server/studycontroller/StudyControllerCreationTest.java`:
- Around line 320-327: The test helper assertStudyCreationMessageReceived should
guard against a timed-out receive returning null: after calling
output.receive(TIMEOUT, studyUpdateDestination) assert the returned Message is
not null (and fail with a clear message), then assert the payload is not null
before converting to String and assert that headers (MessageHeaders) are not
null before reading HEADER_USER_ID, NotificationService.HEADER_STUDY_UUID and
HEADER_UPDATE_TYPE; update the method (referencing output, TIMEOUT,
studyUpdateDestination, Message, MessageHeaders, HEADER_USER_ID,
NotificationService.HEADER_STUDY_UUID, HEADER_UPDATE_TYPE) to perform these null
checks and use assertNotNull with a helpful message so an NPE is avoided and
test failures are descriptive.
🪄 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: 89504180-b613-4dea-b8b4-97595fe622d8

📥 Commits

Reviewing files that changed from the base of the PR and between c314c1d and 3d4240c.

📒 Files selected for processing (6)
  • src/main/java/org/gridsuite/study/server/notification/NotificationService.java
  • src/main/java/org/gridsuite/study/server/service/StudyService.java
  • src/test/java/org/gridsuite/study/server/rootnetworks/RootNetworkControllerTest.java
  • src/test/java/org/gridsuite/study/server/studycontroller/StudyControllerCreationTest.java
  • src/test/java/org/gridsuite/study/server/studycontroller/StudyTest.java
  • src/test/java/org/gridsuite/study/server/studycontroller/StudyTestBase.java

Comment thread src/main/java/org/gridsuite/study/server/service/StudyService.java
Comment on lines +484 to 485
assertEquals(NotificationService.UPDATE_TYPE_STUDY_CREATION_STARTED, headers.get(HEADER_UPDATE_TYPE));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Inspect study-creation notification emissions in service code and this test class.
rg -n --type=java -C3 "STUDY_CREATION_STARTED|STUDY_CREATION_FINISHED|emit.*StudyCreation|studyCreation" src/main src/test
rg -n --type=java -C6 "testCreateStudyWithErrorDuringCaseImport|CASE_UUID_CAUSING_IMPORT_ERROR" src/test/java/org/gridsuite/study/server/studycontroller/StudyTest.java

Repository: gridsuite/study-server

Length of output: 41955


🏁 Script executed:

sed -n '466,498p' src/test/java/org/gridsuite/study/server/studycontroller/StudyTest.java

Repository: gridsuite/study-server

Length of output: 1936


Add assertion for terminal studyCreationFinished event to match other failure-path tests.

This test receives only the studyCreationStarted message and stops, while the other two failure-path tests (testCreateStudyCreationFailedWithoutErrorMessage and testCreateStudyCreationFailedWithStudyCreationError) both verify a subsequent studyCreationFinished event. The service emits this finished message via emitStudyCreationError() when case import fails, so add a second message assertion to complete the lifecycle validation.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/test/java/org/gridsuite/study/server/studycontroller/StudyTest.java`
around lines 484 - 485, The test currently asserts only the studyCreationStarted
update; add a second assertion to consume the next message and verify the
terminal update equals the finished event used by the other failure-path tests:
fetch the next message (same way the test retrieved the first), extract headers,
and assertEquals(NotificationService.UPDATE_TYPE_STUDY_CREATION_FINISHED,
headers.get(HEADER_UPDATE_TYPE)) to mirror the behavior produced by
emitStudyCreationError(); place this immediately after the existing
started-event assertion in StudyTest so the lifecycle is fully validated like
testCreateStudyCreationFailedWithoutErrorMessage/testCreateStudyCreationFailedWithStudyCreationError.

@antoinebhs antoinebhs requested a review from EtienneLt April 28, 2026 13:53
Copy link
Copy Markdown
Contributor

@EtienneLt EtienneLt left a comment

Choose a reason for hiding this comment

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

code OK test OK

@sonarqubecloud
Copy link
Copy Markdown

@antoinebhs antoinebhs merged commit 22e7f77 into main Apr 29, 2026
5 of 7 checks passed
@antoinebhs antoinebhs deleted the new-notif-study-creation branch April 29, 2026 15:30
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.

2 participants