-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[#11571] Cascade user updates/deletes to deadline maps #11688
[#11571] Cascade user updates/deletes to deadline maps #11688
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the FeedbackSessionLogic
- Let's group the delete methods and update methods together.
- I don't think we need so many methods for a simple update. The current implementation seems unnecessarily complex for this purpose.
I think something like this will be more suitable. I've tried to write it in your style.
public void deleteFeedbackSessionsDeadlinesForUser(String courseId, String email, boolean isInstructor) {
Consumer<Map<String, Instant>> deadlineUpdater = deadlines -> deadlines.remove(email);
updateFeedbackSessionDeadlinesForUser(courseId, email, isInstructor, deadlineUpdater);
}
public void updateFeedbackSessionDeadlinesWithNewEmail(String courseId, String oldEmail, String newEmail, boolean isInstructor) {
if (oldEmail.equals(newEmail)) {
return;
}
Consumer<Map<String, Instant>> deadlineUpdater = deadlines -> deadlines.put(newEmail, deadlines.remove(oldEmail));
updateFeedbackSessionDeadlinesForUser(courseId, oldEmail, isInstructor, deadlineUpdater);
}
private void updateFeedbackSessionDeadlinesForUser(String courseId, String email,
boolean isInstructor, Consumer<Map<String, Instant>> deadlineUpdater) {
List<FeedbackSessionAttributes> feedbackSessions = fsDb.getFeedbackSessionsForCourse(courseId);
for (var session : feedbackSessions) {
Map<String, Instant> studentDeadlines = session.getStudentDeadlines();
Map<String, Instant> instructorDeadlines = session.getInstructorDeadlines();
if (isInstructor && instructorDeadlines.containsKey(email)) {
deadlineUpdater.accept(instructorDeadlines);
} else if (!isInstructor && studentDeadlines.containsKey(email)) {
deadlineUpdater.accept(studentDeadlines);
} else {
// No deadline found in session
continue;
}
try {
fsDb.updateFeedbackSession(FeedbackSessionAttributes
.updateOptionsBuilder(session.getFeedbackSessionName(), courseId)
.withStudentDeadlines(studentDeadlines)
.withInstructorDeadlines(instructorDeadlines)
.build());
} catch (InvalidParametersException | EntityDoesNotExistException e) {
// Both Exceptions should not be thrown
log.severe("Unexpected error", e);
}
}
}
"instructorDeadlines": { | ||
"[email protected]": "2027-04-30T23:00:00Z" | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the test json files, let's add the corresponding DeadlineExtensions as well.
@samuelfangjw I initially did it similarly to how you suggested, also to mirror your implementation for cascading for the deadline extension entity since it seemed pretty good. However, I felt that for your case, the reason why cascading to the entity can be implemented that way is because Regardless, I think for right now, I will change Edit: Also the |
If you can do it in a way that doesn't sacrifice readability I don't see any issues. My personal thoughts are that we should have a pragmatic approach to refactoring and make sure any "rules" we apply actually makes sense in the context. |
Ok, I think if I cannot make it readable enough, I might consider putting your stuff as the underlying private methods instead. |
.reduce(new HashMap<>(), (counts, deadline) -> { | ||
int count = counts.getOrDefault(deadline, 0); | ||
counts.put(deadline, count + 1); | ||
return counts; | ||
}, (curr, next) -> { | ||
curr.putAll(next); | ||
return curr; | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps you are looking for Collectors.GroupingBy
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh yes that would be much better; I did not know it existed. Thanks.
@@ -700,6 +704,182 @@ public void testUpdateFeedbackSession_shouldAdjustEmailSendingStatusAccordingly( | |||
typicalSession.getFeedbackSessionName(), typicalSession.getCourseId()).isSentPublishedEmail()); | |||
} | |||
|
|||
@Test | |||
public void testUpdateFeedbackSessionsInstructorDeadlinesWithNewEmail() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe the test case name can describe the input and the output, say updateInstructorEmail_transferDeadlinesToNewEmail
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the test method name gets a bit too long if I add it to the end:
public void testUpdateFeedbackSessionsInstructorDeadlinesWithNewEmail_updateInstructorEmail_transferDeadlinesToNewEmail()
Or do you mean replacing it completely? Wouldn't this be unconventional?
public void testUpdateInstructorEmail_transferDeadlinesToNewEmail()
Or how about using something like ______TS("Update instructor email; transfers deadlines to new email.")
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think TS will do. Indeed it isn't too conventional to just replace as such.
} | ||
|
||
@Test | ||
public void testUpdateFeedbackSessionsStudentDeadlinesWithNewEmail() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto
.map(FeedbackSessionAttributes::getStudentDeadlines) | ||
.filter(studentDeadlines -> studentDeadlines.containsKey(oldEmailAddress)) | ||
.map(studentDeadlines -> studentDeadlines.get(oldEmailAddress)) | ||
.reduce(new HashMap<>(), (counts, deadline) -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto?
.filter(feedbackSessionAttributes -> feedbackSessionAttributes.getInstructorDeadlines() | ||
.containsKey(emailAddress)) | ||
.collect(Collectors.toSet()); | ||
assertEquals(2, oldSessionsWithInstructor1Deadlines.size()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can consider move to after line 819?
src/test/java/teammates/logic/core/FeedbackSessionsLogicTest.java
Outdated
Show resolved
Hide resolved
.map(FeedbackSessionAttributes::getInstructorDeadlines) | ||
.filter(instructorDeadlines -> instructorDeadlines.containsKey(oldEmailAddress)) | ||
.map(instructorDeadlines -> instructorDeadlines.get(oldEmailAddress)) | ||
.reduce(new HashMap<>(), (counts, deadline) -> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few more places like this are unclear. Can apply the same fix here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah sorry, I forgot I did it in other files too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! I'm ok with the rest of the changes!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good!
* Add methods for updating and deleting deadline maps for a user * Add tests for updating and deleting deadline maps for a user * Cascade instructor updates or deletes to deadline maps * Test cascade of instructor updates or deletes to deadline maps * Cascade student updates or deletes to deadline maps * Test cascade of student updates or deletes to deadline maps * Match deadline extension entities with deadline maps * Change deadlinesUpdater into a Consumer * Change unexpected error assertion into a severe log * Improve readability of feedback session deadline map update code * Clean code * Clean code further
* Add methods for updating and deleting deadline maps for a user * Add tests for updating and deleting deadline maps for a user * Cascade instructor updates or deletes to deadline maps * Test cascade of instructor updates or deletes to deadline maps * Cascade student updates or deletes to deadline maps * Test cascade of student updates or deletes to deadline maps * Match deadline extension entities with deadline maps * Change deadlinesUpdater into a Consumer * Change unexpected error assertion into a severe log * Improve readability of feedback session deadline map update code * Clean code * Clean code further
* Add methods for updating and deleting deadline maps for a user * Add tests for updating and deleting deadline maps for a user * Cascade instructor updates or deletes to deadline maps * Test cascade of instructor updates or deletes to deadline maps * Cascade student updates or deletes to deadline maps * Test cascade of student updates or deletes to deadline maps * Match deadline extension entities with deadline maps * Change deadlinesUpdater into a Consumer * Change unexpected error assertion into a severe log * Improve readability of feedback session deadline map update code * Clean code * Clean code further
Part of #11571
PR Checklist
Outline of Solution
Any user email address update or any user deletion is cascaded down to the deadline maps. This is implemented by finding all the feedback sessions in the course the user belongs to. For each feedback session, the email is updated or deleted accordingly in the respective deadline map if that map contains a selective deadline for that user.