Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.broadinstitute.consent.http.authentication.OAuthAuthenticator;
import org.broadinstitute.consent.http.authentication.OAuthCustomAuthFilter;
import org.broadinstitute.consent.http.configurations.ConsentConfiguration;
import org.broadinstitute.consent.http.filters.EmailSendIdFilter;
import org.broadinstitute.consent.http.filters.RateLimitFilter;
import org.broadinstitute.consent.http.filters.RequestHeaderCacheFilter;
import org.broadinstitute.consent.http.filters.ResponseServerFilter;
Expand Down Expand Up @@ -250,6 +251,7 @@ public void run(ConsentConfiguration config, Environment env) {
env.jersey().register(injector.getInstance(RateLimitFilter.class));
env.jersey().register(RolesAllowedDynamicFeature.class);
env.jersey().register(TemplateSizeLimitFilter.class);
env.jersey().register(EmailSendIdFilter.class);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ public interface MailMessageDAO extends Transactional<MailMessageDAO> {
"""
WITH insterted_row AS (
INSERT INTO email_entity
(entity_reference_id, vote_id, user_id, email_type, date_sent, email_text, sendgrid_response, sendgrid_status, create_date)
(entity_reference_id, vote_id, user_id, email_type, date_sent, email_text, sendgrid_response, sendgrid_status, create_date, send_id)
VALUES
(:entityReferenceId, :voteId, :userId, :emailType, :dateSent, :emailText, :sendgridResponse, :sendgridStatus, NOW())
(:entityReferenceId, :voteId, :userId, :emailType, :dateSent, :emailText, :sendgridResponse, :sendgridStatus, NOW(), CAST(:sendId AS uuid))
RETURNING *)
SELECT * FROM insterted_row
""")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.broadinstitute.consent.http.filters;

import jakarta.annotation.Priority;
import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.container.ContainerRequestContext;
import jakarta.ws.rs.container.ContainerRequestFilter;
import jakarta.ws.rs.container.ContainerResponseContext;
import jakarta.ws.rs.container.ContainerResponseFilter;
import jakarta.ws.rs.ext.Provider;
import org.broadinstitute.consent.http.mail.EmailSendId;

@Provider
@Priority(Priorities.USER)
public class EmailSendIdFilter implements ContainerRequestFilter, ContainerResponseFilter {

@Override
public void filter(ContainerRequestContext requestContext) {
EmailSendId.start();
}

@Override
public void filter(
ContainerRequestContext requestContext, ContainerResponseContext responseContext) {
EmailSendId.clear();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.broadinstitute.consent.http.mail;

import java.util.UUID;

/** The send id shared by the emails written during the current request. */
public final class EmailSendId {

private static final ThreadLocal<UUID> CURRENT = new ThreadLocal<>();

private EmailSendId() {}

public static void start() {
CURRENT.set(UUID.randomUUID());
}

/** Runs a job off the request thread, such as a scheduled batch, under a send id of its own. */
public static void run(Runnable job) {
UUID previous = CURRENT.get();
CURRENT.set(UUID.randomUUID());
try {
job.run();
} finally {
CURRENT.set(previous);
}
}

/** Null outside a request or job, where each email is grouped by the older rules. */
public static UUID current() {
return CURRENT.get();
}

public static void clear() {
CURRENT.remove();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.broadinstitute.consent.http.models.mail;

import java.util.Date;
import java.util.UUID;

public record MailMessageInsert(
String entityReferenceId,
Expand All @@ -10,4 +11,5 @@ public record MailMessageInsert(
Date dateSent,
String emailText,
String sendgridResponse,
Integer sendgridStatus) {}
Integer sendgridStatus,
UUID sendId) {}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.core.Response;
import java.util.concurrent.ExecutorService;
import org.broadinstitute.consent.http.mail.EmailSendId;
import org.broadinstitute.consent.http.models.DuosUser;
import org.broadinstitute.consent.http.service.DataAccessRequestService;
import org.broadinstitute.consent.http.service.EmailService;
Expand Down Expand Up @@ -47,9 +48,9 @@ public Response sendReminderMessage(@Auth DuosUser duosUser, @PathParam("voteId"
@Path("/dailyMessages")
@RolesAllowed({SERVICE_ACCOUNT})
public Response sendDailyMessages(@Auth DuosUser duosUser) {
executor.submit(this::processExpirationNotices);
executor.submit(this::processVoteDigestMessages);
executor.submit(this::processNewDatasetInDUOSNotifications);
executor.submit(() -> EmailSendId.run(this::processExpirationNotices));
executor.submit(() -> EmailSendId.run(this::processVoteDigestMessages));
executor.submit(() -> EmailSendId.run(this::processNewDatasetInDUOSNotifications));
return Response.ok().build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.broadinstitute.consent.http.db.UserDAO;
import org.broadinstitute.consent.http.enumeration.EmailType;
import org.broadinstitute.consent.http.exceptions.EmailNotRecordedException;
import org.broadinstitute.consent.http.mail.EmailSendId;
import org.broadinstitute.consent.http.mail.EmailSendOutcome;
import org.broadinstitute.consent.http.mail.SendGridAPI;
import org.broadinstitute.consent.http.mail.freemarker.FreeMarkerTemplateHelper;
Expand Down Expand Up @@ -115,7 +116,8 @@ public EmailSendOutcome sendMessage(MailMessage mailMessage, Integer userId)
dateSent,
content,
sendgridResponse,
sendgridStatus);
sendgridStatus,
EmailSendId.current());
try {
emailDAO.insert(mailMessageInsert);
} catch (RuntimeException e) {
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/changelog-master.xml
Original file line number Diff line number Diff line change
Expand Up @@ -271,4 +271,5 @@
<include file="changesets/changelog-consent-2026-09-19-drop-match-consent.xml" relativeToChangelogFile="true" />
<include file="changesets/changelog-consent-2026-10-06-metrics-date-indexes.xml" relativeToChangelogFile="true" />
<include file="changesets/changelog-consent-2026-10-06-ontology-index-normalized-ids.xml" relativeToChangelogFile="true" />
<include file="changesets/changelog-consent-2026-10-09-email-entity-send-id.xml" relativeToChangelogFile="true" />
</databaseChangeLog>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<!-- Rows written during one request share a send_id, so one send is that id plus type and reference. -->
<changeSet id="changelog-consent-2026-10-09-email-entity-send-id" author="kmarete">
<addColumn tableName="email_entity">
<column name="send_id" type="uuid"/>
</addColumn>
</changeSet>
</databaseChangeLog>
Original file line number Diff line number Diff line change
Expand Up @@ -2520,7 +2520,8 @@ void testFindAgedDARsByEmailTypeOlderThanIntervalExpiringEntriesDoesNotRepeatIfE
Date.from(Instant.now()),
"hello world!",
"success",
200));
200,
null));
List<DataAccessRequest> dars =
dataAccessRequestDAO.findAgedDARsByEmailTypeOlderThanInterval(
EmailType.DAR_EXPIRATION_REMINDER.getTypeInt(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -722,6 +722,7 @@ void testFindVotesThatNeedReminders_AlreadyEmailed() {
FIXED_DATE,
"Extra, Extra!",
null,
null,
null));

List<UserVoteReminder> userVoteReminders =
Expand Down
Loading
Loading