Merge changes Iad263b16,If74c346e,I5682bf9b
* changes:
CommentsUtil: Don't use the diff cache to look up the parent commit
Cover some more behaviors of ported comments with tests
Ignore comments on non-existing patchsets when porting
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 6b89d67..09741aa 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -182,20 +182,6 @@
+
By default 1.
-[[asyncPostUpdate]]
-=== Section asyncPostUpdate
-
-[[asyncPostUpdate.threadPoolSize]]asyncPostUpdate.threadPoolSize::
-+
-Maximum size of thread pool in which async post updates are sent out.
-+
-When set to 0, a direct executor is used.
-+
-When unset, use link:#sendemail[sendemail.threadPoolSize] threadPoolSize. When both
-are unset, use the default.
-+
-By default, 1.
-
[[auth]]
=== Section auth
@@ -884,8 +870,6 @@
The check if they are is cheap and always happens on the thread that
inquires for a cached value.
+
-When set to 0, a direct executor is used.
-+
Defaults to 2.
==== [[cache_names]]Standard Caches
@@ -4490,7 +4474,11 @@
an error occurs.
[[sendemail.threadPoolSize]]sendemail.threadPoolSize::
-Deprecated. Replaced with link:#asyncPostUpdate.threadPoolSize[asyncPostUpdate.threadPoolSize]
++
+Maximum size of thread pool in which the review comments
+notifications are sent out asynchronously.
++
+By default, 1.
[[sendemail.from]]sendemail.from::
+
diff --git a/java/com/google/gerrit/acceptance/AbstractNotificationTest.java b/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
index 32bc992..452df67 100644
--- a/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractNotificationTest.java
@@ -48,7 +48,6 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import org.eclipse.jgit.junit.TestRepository;
@@ -98,7 +97,7 @@
protected static class FakeEmailSenderSubject extends Subject {
private final FakeEmailSender fakeEmailSender;
- private Optional<Message> message;
+ private Message message;
private StagedUsers users;
private Map<RecipientType, List<String>> recipients = new HashMap<>();
private Set<String> accountedFor = new HashSet<>();
@@ -117,29 +116,35 @@
}
public FakeEmailSenderSubject sent(String messageType, StagedUsers users) {
- fakeEmailSender.readOneMessage();
- message =
- fakeEmailSender.getMessages().stream()
- .filter(
- m ->
- m.headers()
- .get("X-Gerrit-MessageType")
- .equals(new EmailHeader.String(messageType)))
- .findFirst();
- if (!message.isPresent()) {
- failWithoutActual(
- fact(String.format("expected message of type %s", messageType), "not sent"));
+ message = fakeEmailSender.nextMessage();
+ if (message == null) {
+ failWithoutActual(fact("expected message", "not sent"));
}
recipients = new HashMap<>();
- recipients.put(TO, parseAddresses(message.get(), "To"));
- recipients.put(CC, parseAddresses(message.get(), "Cc"));
+ recipients.put(TO, parseAddresses(message, "To"));
+ recipients.put(CC, parseAddresses(message, "Cc"));
recipients.put(
BCC,
- message.get().rcpt().stream()
+ message.rcpt().stream()
.map(Address::email)
.filter(e -> !recipients.get(TO).contains(e) && !recipients.get(CC).contains(e))
.collect(toList()));
this.users = users;
+ if (!message.headers().containsKey("X-Gerrit-MessageType")) {
+ failWithoutActual(
+ fact("expected to have message sent with", "X-Gerrit-MessageType header"));
+ }
+ EmailHeader header = message.headers().get("X-Gerrit-MessageType");
+ if (!header.equals(new EmailHeader.String(messageType))) {
+ failWithoutActual(
+ fact("expected message of type", messageType),
+ fact(
+ "actual",
+ header instanceof EmailHeader.String
+ ? ((EmailHeader.String) header).getString()
+ : header));
+ }
+
return this;
}
diff --git a/java/com/google/gerrit/server/PublishCommentsOp.java b/java/com/google/gerrit/server/PublishCommentsOp.java
index e03c244..358ce92 100644
--- a/java/com/google/gerrit/server/PublishCommentsOp.java
+++ b/java/com/google/gerrit/server/PublishCommentsOp.java
@@ -28,7 +28,6 @@
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.patch.PatchListNotAvailableException;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.CommentsRejectedException;
@@ -47,7 +46,7 @@
* <p>This class uses the {@link PublishCommentUtil} to publish draft comments and fires the
* necessary event for this.
*/
-public class PublishCommentsOp implements BatchUpdateOp, AsyncPostUpdateOp {
+public class PublishCommentsOp implements BatchUpdateOp {
private final PatchSetUtil psUtil;
private final ChangeNotes.Factory changeNotesFactory;
private final ChangeMessagesUtil cmUtil;
@@ -62,8 +61,6 @@
private List<HumanComment> comments = new ArrayList<>();
private ChangeMessage message;
private IdentifiedUser user;
- private ChangeNotes changeNotes;
- private PatchSet patchset;
public interface Factory {
PublishCommentsOp create(PatchSet.Id psId, Project.NameKey projectNameKey);
@@ -112,24 +109,11 @@
@Override
public void postUpdate(Context ctx) {
- changeNotes = changeNotesFactory.createChecked(projectNameKey, psId.changeId());
- patchset = psUtil.get(changeNotes, psId);
-
- commentAdded.fire(
- changeNotes.getChange(),
- patchset,
- ctx.getAccount(),
- message.getMessage(),
- ImmutableMap.of(),
- ImmutableMap.of(),
- ctx.getWhen());
- }
-
- @Override
- public void asyncPostUpdate(Context ctx) {
if (message == null || comments.isEmpty()) {
return;
}
+ ChangeNotes changeNotes = changeNotesFactory.createChecked(projectNameKey, psId.changeId());
+ PatchSet ps = psUtil.get(changeNotes, psId);
NotifyResolver.Result notify = ctx.getNotify(changeNotes.getChangeId());
if (notify.shouldNotify()) {
RepoView repoView;
@@ -140,10 +124,17 @@
String.format("Repository %s not found", ctx.getProject().get()), ex);
}
email
- .create(
- notify, changeNotes, patchset, user, message, comments, null, labelDelta, repoView)
- .send();
+ .create(notify, changeNotes, ps, user, message, comments, null, labelDelta, repoView)
+ .sendAsync();
}
+ commentAdded.fire(
+ changeNotes.getChange(),
+ ps,
+ ctx.getAccount(),
+ message.getMessage(),
+ ImmutableMap.of(),
+ ImmutableMap.of(),
+ ctx.getWhen());
}
private boolean insertMessage(ChangeContext ctx, ChangeUpdate changeUpdate) {
diff --git a/java/com/google/gerrit/server/change/AbandonOp.java b/java/com/google/gerrit/server/change/AbandonOp.java
index e0e489b..6c39ed0 100644
--- a/java/com/google/gerrit/server/change/AbandonOp.java
+++ b/java/com/google/gerrit/server/change/AbandonOp.java
@@ -30,14 +30,13 @@
import com.google.gerrit.server.mail.send.MessageIdGenerator;
import com.google.gerrit.server.mail.send.ReplyToChangeSender;
import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
-public class AbandonOp implements BatchUpdateOp, AsyncPostUpdateOp {
+public class AbandonOp implements BatchUpdateOp {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final AbandonedSender.Factory abandonedSenderFactory;
@@ -52,7 +51,6 @@
private Change change;
private PatchSet patchSet;
private ChangeMessage message;
- private NotifyResolver.Result notify;
public interface Factory {
AbandonOp create(
@@ -98,7 +96,6 @@
update.setStatus(change.getStatus());
message = newMessage(ctx);
cmUtil.addChangeMessage(update, message);
- notify = ctx.getNotify(change.getId());
return true;
}
@@ -115,11 +112,7 @@
@Override
public void postUpdate(Context ctx) {
- changeAbandoned.fire(change, patchSet, accountState, msgTxt, ctx.getWhen(), notify.handling());
- }
-
- @Override
- public void asyncPostUpdate(Context ctx) {
+ NotifyResolver.Result notify = ctx.getNotify(change.getId());
try {
ReplyToChangeSender emailSender =
abandonedSenderFactory.create(ctx.getProject(), change.getId());
@@ -134,5 +127,6 @@
} catch (Exception e) {
logger.atSevere().withCause(e).log("Cannot email update for change %s", change.getId());
}
+ changeAbandoned.fire(change, patchSet, accountState, msgTxt, ctx.getWhen(), notify.handling());
}
}
diff --git a/java/com/google/gerrit/server/change/AddReviewersEmail.java b/java/com/google/gerrit/server/change/AddReviewersEmail.java
index 5e48353..4a3f638 100644
--- a/java/com/google/gerrit/server/change/AddReviewersEmail.java
+++ b/java/com/google/gerrit/server/change/AddReviewersEmail.java
@@ -23,27 +23,34 @@
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.mail.send.AddReviewerSender;
import com.google.gerrit.server.mail.send.MessageIdGenerator;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.Collection;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
@Singleton
public class AddReviewersEmail {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final AddReviewerSender.Factory addReviewerSenderFactory;
+ private final ExecutorService sendEmailsExecutor;
private final MessageIdGenerator messageIdGenerator;
@Inject
AddReviewersEmail(
- AddReviewerSender.Factory addReviewerSenderFactory, MessageIdGenerator messageIdGenerator) {
+ AddReviewerSender.Factory addReviewerSenderFactory,
+ @SendEmailExecutor ExecutorService sendEmailsExecutor,
+ MessageIdGenerator messageIdGenerator) {
this.addReviewerSenderFactory = addReviewerSenderFactory;
+ this.sendEmailsExecutor = sendEmailsExecutor;
this.messageIdGenerator = messageIdGenerator;
}
- public void emailReviewers(
+ public void emailReviewersAsync(
IdentifiedUser user,
Change change,
Collection<Account.Id> added,
@@ -71,20 +78,27 @@
ImmutableList<Address> immutableAddedByEmail = ImmutableList.copyOf(addedByEmail);
ImmutableList<Address> immutableCopiedByEmail = ImmutableList.copyOf(copiedByEmail);
- try {
- AddReviewerSender emailSender = addReviewerSenderFactory.create(projectNameKey, cId);
- emailSender.setNotify(notify);
- emailSender.setFrom(userId);
- emailSender.addReviewers(immutableToMail);
- emailSender.addReviewersByEmail(immutableAddedByEmail);
- emailSender.addExtraCC(immutableToCopy);
- emailSender.addExtraCCByEmail(immutableCopiedByEmail);
- emailSender.setMessageId(
- messageIdGenerator.fromChangeUpdate(change.getProject(), change.currentPatchSetId()));
- emailSender.send();
- } catch (Exception err) {
- logger.atSevere().withCause(err).log(
- "Cannot send email to new reviewers of change %s", change.getId());
- }
+ @SuppressWarnings("unused")
+ Future<?> possiblyIgnoredError =
+ sendEmailsExecutor.submit(
+ () -> {
+ try {
+ AddReviewerSender emailSender =
+ addReviewerSenderFactory.create(projectNameKey, cId);
+ emailSender.setNotify(notify);
+ emailSender.setFrom(userId);
+ emailSender.addReviewers(immutableToMail);
+ emailSender.addReviewersByEmail(immutableAddedByEmail);
+ emailSender.addExtraCC(immutableToCopy);
+ emailSender.addExtraCCByEmail(immutableCopiedByEmail);
+ emailSender.setMessageId(
+ messageIdGenerator.fromChangeUpdate(
+ change.getProject(), change.currentPatchSetId()));
+ emailSender.send();
+ } catch (Exception err) {
+ logger.atSevere().withCause(err).log(
+ "Cannot send email to new reviewers of change %s", change.getId());
+ }
+ });
}
}
diff --git a/java/com/google/gerrit/server/change/AddReviewersOp.java b/java/com/google/gerrit/server/change/AddReviewersOp.java
index fd57722..ff8e5c6 100644
--- a/java/com/google/gerrit/server/change/AddReviewersOp.java
+++ b/java/com/google/gerrit/server/change/AddReviewersOp.java
@@ -42,7 +42,6 @@
import com.google.gerrit.server.extensions.events.ReviewerAdded;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
import com.google.gerrit.server.project.ProjectCache;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
@@ -53,7 +52,7 @@
import java.util.List;
import java.util.Set;
-public class AddReviewersOp implements BatchUpdateOp, AsyncPostUpdateOp {
+public class AddReviewersOp implements BatchUpdateOp {
public interface Factory {
/**
@@ -239,7 +238,7 @@
}
@Override
- public void postUpdate(Context ctx) {
+ public void postUpdate(Context ctx) throws Exception {
opResult =
Result.builder()
.setAddedReviewers(addedReviewers)
@@ -247,20 +246,8 @@
.setAddedCCs(addedCCs)
.setAddedCCsByEmail(addedCCsByEmail)
.build();
- if (!addedReviewers.isEmpty()) {
- List<AccountState> reviewers =
- addedReviewers.stream()
- .map(r -> accountCache.get(r.accountId()))
- .flatMap(Streams::stream)
- .collect(toList());
- reviewerAdded.fire(change, patchSet, reviewers, ctx.getAccount(), ctx.getWhen());
- }
- }
-
- @Override
- public void asyncPostUpdate(Context ctx) {
if (sendEmail) {
- addReviewersEmail.emailReviewers(
+ addReviewersEmail.emailReviewersAsync(
ctx.getUser().asIdentifiedUser(),
change,
Lists.transform(addedReviewers, PatchSetApproval::accountId),
@@ -269,6 +256,14 @@
addedCCsByEmail,
ctx.getNotify(change.getId()));
}
+ if (!addedReviewers.isEmpty()) {
+ List<AccountState> reviewers =
+ addedReviewers.stream()
+ .map(r -> accountCache.get(r.accountId()))
+ .flatMap(Streams::stream)
+ .collect(toList());
+ reviewerAdded.fire(change, patchSet, reviewers, ctx.getAccount(), ctx.getWhen());
+ }
}
public Result getResult() {
diff --git a/java/com/google/gerrit/server/change/AddToAttentionSetOp.java b/java/com/google/gerrit/server/change/AddToAttentionSetOp.java
index 31147fc..8053b30 100644
--- a/java/com/google/gerrit/server/change/AddToAttentionSetOp.java
+++ b/java/com/google/gerrit/server/change/AddToAttentionSetOp.java
@@ -25,7 +25,6 @@
import com.google.gerrit.server.mail.send.MessageIdGenerator;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
@@ -35,7 +34,7 @@
import java.io.IOException;
/** Add a specified user to the attention set. */
-public class AddToAttentionSetOp implements BatchUpdateOp, AsyncPostUpdateOp {
+public class AddToAttentionSetOp implements BatchUpdateOp {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public interface Factory {
@@ -102,7 +101,7 @@
}
@Override
- public void asyncPostUpdate(Context ctx) {
+ public void postUpdate(Context ctx) {
if (!notify) {
return;
}
@@ -115,7 +114,7 @@
reason,
messageIdGenerator.fromChangeUpdate(ctx.getRepoView(), change.currentPatchSetId()),
attentionUserId)
- .send();
+ .sendAsync();
} catch (IOException e) {
logger.atSevere().withCause(e).log(e.getMessage(), change.getId());
}
diff --git a/java/com/google/gerrit/server/change/ChangeInserter.java b/java/com/google/gerrit/server/change/ChangeInserter.java
index 2f95a5c..a086cb1 100644
--- a/java/com/google/gerrit/server/change/ChangeInserter.java
+++ b/java/com/google/gerrit/server/change/ChangeInserter.java
@@ -52,6 +52,7 @@
import com.google.gerrit.server.change.ReviewerAdder.InternalAddReviewerInput;
import com.google.gerrit.server.change.ReviewerAdder.ReviewerAddition;
import com.google.gerrit.server.change.ReviewerAdder.ReviewerAdditionList;
+import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.config.UrlFormatter;
import com.google.gerrit.server.events.CommitReceivedEvent;
import com.google.gerrit.server.extensions.events.CommentAdded;
@@ -68,12 +69,12 @@
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.ssh.NoSshInfo;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
import com.google.gerrit.server.update.InsertChangeOp;
import com.google.gerrit.server.update.RepoContext;
import com.google.gerrit.server.util.CommitMessageUtil;
+import com.google.gerrit.server.util.RequestScopePropagator;
import com.google.gerrit.server.validators.ValidationException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
@@ -83,13 +84,15 @@
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;
-public class ChangeInserter implements InsertChangeOp, AsyncPostUpdateOp {
+public class ChangeInserter implements InsertChangeOp {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public interface Factory {
@@ -103,6 +106,7 @@
private final ApprovalsUtil approvalsUtil;
private final ChangeMessagesUtil cmUtil;
private final CreateChangeSender.Factory createChangeSenderFactory;
+ private final ExecutorService sendEmailExecutor;
private final CommitValidators.Factory commitValidatorsFactory;
private final RevisionCreated revisionCreated;
private final CommentAdded commentAdded;
@@ -126,6 +130,7 @@
private List<String> groups = Collections.emptyList();
private boolean validate = true;
private Map<String, Short> approvals;
+ private RequestScopePropagator requestScopePropagator;
private boolean fireRevisionCreated;
private boolean sendMail;
private boolean updateRef;
@@ -141,7 +146,6 @@
private String pushCert;
private ProjectState projectState;
private ReviewerAdditionList reviewerAdditions;
- private NotifyResolver.Result notify;
@Inject
ChangeInserter(
@@ -152,6 +156,7 @@
ApprovalsUtil approvalsUtil,
ChangeMessagesUtil cmUtil,
CreateChangeSender.Factory createChangeSenderFactory,
+ @SendEmailExecutor ExecutorService sendEmailExecutor,
CommitValidators.Factory commitValidatorsFactory,
CommentAdded commentAdded,
RevisionCreated revisionCreated,
@@ -168,6 +173,7 @@
this.approvalsUtil = approvalsUtil;
this.cmUtil = cmUtil;
this.createChangeSenderFactory = createChangeSenderFactory;
+ this.sendEmailExecutor = sendEmailExecutor;
this.commitValidatorsFactory = commitValidatorsFactory;
this.revisionCreated = revisionCreated;
this.commentAdded = commentAdded;
@@ -309,6 +315,11 @@
return this;
}
+ public ChangeInserter setRequestScopePropagator(RequestScopePropagator r) {
+ this.requestScopePropagator = r;
+ return this;
+ }
+
public ChangeInserter setRevertOf(Change.Id revertOf) {
this.revertOf = revertOf;
return this;
@@ -446,13 +457,57 @@
ChangeMessagesUtil.uploadedPatchSetTag(workInProgress));
cmUtil.addChangeMessage(update, changeMessage);
}
- notify = ctx.getNotify(change.getId());
return true;
}
@Override
- public void postUpdate(Context ctx) {
+ public void postUpdate(Context ctx) throws Exception {
reviewerAdditions.postUpdate(ctx);
+ NotifyResolver.Result notify = ctx.getNotify(change.getId());
+ if (sendMail && notify.shouldNotify()) {
+ Runnable sender =
+ new Runnable() {
+ @Override
+ public void run() {
+ try {
+ CreateChangeSender emailSender =
+ createChangeSenderFactory.create(change.getProject(), change.getId());
+ emailSender.setFrom(change.getOwner());
+ emailSender.setPatchSet(patchSet, patchSetInfo);
+ emailSender.setNotify(notify);
+ emailSender.addReviewers(
+ reviewerAdditions.flattenResults(AddReviewersOp.Result::addedReviewers).stream()
+ .map(PatchSetApproval::accountId)
+ .collect(toImmutableSet()));
+ emailSender.addReviewersByEmail(
+ reviewerAdditions.flattenResults(AddReviewersOp.Result::addedReviewersByEmail));
+ emailSender.addExtraCC(
+ reviewerAdditions.flattenResults(AddReviewersOp.Result::addedCCs));
+ emailSender.addExtraCCByEmail(
+ reviewerAdditions.flattenResults(AddReviewersOp.Result::addedCCsByEmail));
+ emailSender.setMessageId(
+ messageIdGenerator.fromChangeUpdate(ctx.getRepoView(), patchSet.id()));
+ emailSender.send();
+ } catch (Exception e) {
+ logger.atSevere().withCause(e).log(
+ "Cannot send email for new change %s", change.getId());
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "send-email newchange";
+ }
+ };
+ if (requestScopePropagator != null) {
+ @SuppressWarnings("unused")
+ Future<?> possiblyIgnoredError =
+ sendEmailExecutor.submit(requestScopePropagator.wrap(sender));
+ } else {
+ sender.run();
+ }
+ }
+
/* For labels that are not set in this operation, show the "current" value
* of 0, and no oldValue as the value was not modified by this operation.
* For labels that are set in this operation, the value was modified, so
@@ -480,34 +535,6 @@
}
}
- @Override
- public void asyncPostUpdate(Context ctx) {
- reviewerAdditions.asyncPostUpdate(ctx);
- if (sendMail && notify.shouldNotify()) {
- try {
- CreateChangeSender emailSender =
- createChangeSenderFactory.create(change.getProject(), change.getId());
- emailSender.setFrom(change.getOwner());
- emailSender.setPatchSet(patchSet, patchSetInfo);
- emailSender.setNotify(notify);
- emailSender.addReviewers(
- reviewerAdditions.flattenResults(AddReviewersOp.Result::addedReviewers).stream()
- .map(PatchSetApproval::accountId)
- .collect(toImmutableSet()));
- emailSender.addReviewersByEmail(
- reviewerAdditions.flattenResults(AddReviewersOp.Result::addedReviewersByEmail));
- emailSender.addExtraCC(reviewerAdditions.flattenResults(AddReviewersOp.Result::addedCCs));
- emailSender.addExtraCCByEmail(
- reviewerAdditions.flattenResults(AddReviewersOp.Result::addedCCsByEmail));
- emailSender.setMessageId(
- messageIdGenerator.fromChangeUpdate(ctx.getRepoView(), patchSet.id()));
- emailSender.send();
- } catch (Exception e) {
- logger.atSevere().withCause(e).log("Cannot send email for new change %s", change.getId());
- }
- }
- }
-
private void validate(RepoContext ctx) throws IOException, ResourceConflictException {
if (!validate) {
return;
diff --git a/java/com/google/gerrit/server/change/DeleteReviewerByEmailOp.java b/java/com/google/gerrit/server/change/DeleteReviewerByEmailOp.java
index d9ede58..255e13a 100644
--- a/java/com/google/gerrit/server/change/DeleteReviewerByEmailOp.java
+++ b/java/com/google/gerrit/server/change/DeleteReviewerByEmailOp.java
@@ -22,7 +22,6 @@
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.mail.send.DeleteReviewerSender;
import com.google.gerrit.server.mail.send.MessageIdGenerator;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
@@ -30,7 +29,7 @@
import com.google.inject.assistedinject.Assisted;
import java.util.Collections;
-public class DeleteReviewerByEmailOp implements BatchUpdateOp, AsyncPostUpdateOp {
+public class DeleteReviewerByEmailOp implements BatchUpdateOp {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public interface Factory {
@@ -74,7 +73,7 @@
}
@Override
- public void asyncPostUpdate(Context ctx) {
+ public void postUpdate(Context ctx) {
try {
NotifyResolver.Result notify = ctx.getNotify(change.getId());
if (!notify.shouldNotify()) {
diff --git a/java/com/google/gerrit/server/change/DeleteReviewerOp.java b/java/com/google/gerrit/server/change/DeleteReviewerOp.java
index de11e07..07cb04f 100644
--- a/java/com/google/gerrit/server/change/DeleteReviewerOp.java
+++ b/java/com/google/gerrit/server/change/DeleteReviewerOp.java
@@ -43,7 +43,6 @@
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.RemoveReviewerControl;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
@@ -56,7 +55,7 @@
import java.util.HashMap;
import java.util.Map;
-public class DeleteReviewerOp implements BatchUpdateOp, AsyncPostUpdateOp {
+public class DeleteReviewerOp implements BatchUpdateOp {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public interface Factory {
@@ -77,12 +76,11 @@
private final AccountState reviewer;
private final DeleteReviewerInput input;
- private ChangeMessage changeMessage;
- private Change currChange;
- private PatchSet currPs;
- private Map<String, Short> newApprovals = new HashMap<>();
- private Map<String, Short> oldApprovals = new HashMap<>();
- private NotifyResolver.Result notify;
+ ChangeMessage changeMessage;
+ Change currChange;
+ PatchSet currPs;
+ Map<String, Short> newApprovals = new HashMap<>();
+ Map<String, Short> oldApprovals = new HashMap<>();
@Inject
DeleteReviewerOp(
@@ -167,27 +165,13 @@
changeMessage =
ChangeMessagesUtil.newMessage(ctx, msg.toString(), ChangeMessagesUtil.TAG_DELETE_REVIEWER);
cmUtil.addChangeMessage(update, changeMessage);
- notify = ctx.getNotify(currChange.getId());
return true;
}
@Override
public void postUpdate(Context ctx) {
- reviewerDeleted.fire(
- currChange,
- currPs,
- reviewer,
- ctx.getAccount(),
- changeMessage.getMessage(),
- newApprovals,
- oldApprovals,
- notify.handling(),
- ctx.getWhen());
- }
-
- @Override
- public void asyncPostUpdate(Context ctx) {
+ NotifyResolver.Result notify = ctx.getNotify(currChange.getId());
if (input.notify == null
&& currChange.isWorkInProgress()
&& !oldApprovals.isEmpty()
@@ -203,6 +187,16 @@
} catch (Exception err) {
logger.atSevere().withCause(err).log("Cannot email update for change %s", currChange.getId());
}
+ reviewerDeleted.fire(
+ currChange,
+ currPs,
+ reviewer,
+ ctx.getAccount(),
+ changeMessage.getMessage(),
+ newApprovals,
+ oldApprovals,
+ notify.handling(),
+ ctx.getWhen());
}
private Iterable<PatchSetApproval> approvals(ChangeContext ctx, Account.Id accountId) {
diff --git a/java/com/google/gerrit/server/change/EmailReviewComments.java b/java/com/google/gerrit/server/change/EmailReviewComments.java
index 309b041..cacfbe7 100644
--- a/java/com/google/gerrit/server/change/EmailReviewComments.java
+++ b/java/com/google/gerrit/server/change/EmailReviewComments.java
@@ -21,18 +21,24 @@
import com.google.gerrit.entities.ChangeMessage;
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.PatchSet;
+import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.mail.send.CommentSender;
import com.google.gerrit.server.mail.send.MessageIdGenerator;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
import com.google.gerrit.server.update.RepoView;
import com.google.gerrit.server.util.LabelVote;
+import com.google.gerrit.server.util.RequestContext;
+import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
-public class EmailReviewComments {
+public class EmailReviewComments implements Runnable, RequestContext {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public interface Factory {
@@ -65,8 +71,10 @@
RepoView repoView);
}
+ private final ExecutorService sendEmailsExecutor;
private final PatchSetInfoFactory patchSetInfoFactory;
private final CommentSender.Factory commentSenderFactory;
+ private final ThreadLocalRequestContext requestContext;
private final MessageIdGenerator messageIdGenerator;
private final NotifyResolver.Result notify;
@@ -81,8 +89,10 @@
@Inject
EmailReviewComments(
+ @SendEmailExecutor ExecutorService executor,
PatchSetInfoFactory patchSetInfoFactory,
CommentSender.Factory commentSenderFactory,
+ ThreadLocalRequestContext requestContext,
MessageIdGenerator messageIdGenerator,
@Assisted NotifyResolver.Result notify,
@Assisted ChangeNotes notes,
@@ -93,8 +103,10 @@
@Nullable @Assisted String patchSetComment,
@Assisted List<LabelVote> labels,
@Assisted RepoView repoView) {
+ this.sendEmailsExecutor = executor;
this.patchSetInfoFactory = patchSetInfoFactory;
this.commentSenderFactory = commentSenderFactory;
+ this.requestContext = requestContext;
this.messageIdGenerator = messageIdGenerator;
this.notify = notify;
this.notes = notes;
@@ -107,7 +119,14 @@
this.repoView = repoView;
}
- public void send() {
+ public void sendAsync() {
+ @SuppressWarnings("unused")
+ Future<?> possiblyIgnoredError = sendEmailsExecutor.submit(this);
+ }
+
+ @Override
+ public void run() {
+ RequestContext old = requestContext.setContext(this);
try {
CommentSender emailSender =
commentSenderFactory.create(notes.getProjectName(), notes.getChangeId());
@@ -124,6 +143,18 @@
emailSender.send();
} catch (Exception e) {
logger.atSevere().withCause(e).log("Cannot email comments for %s", patchSet.id());
+ } finally {
+ requestContext.setContext(old);
}
}
+
+ @Override
+ public String toString() {
+ return "send-email comments";
+ }
+
+ @Override
+ public CurrentUser getUser() {
+ return user.getRealUser();
+ }
}
diff --git a/java/com/google/gerrit/server/change/PatchSetInserter.java b/java/com/google/gerrit/server/change/PatchSetInserter.java
index 4502408..882352d 100644
--- a/java/com/google/gerrit/server/change/PatchSetInserter.java
+++ b/java/com/google/gerrit/server/change/PatchSetInserter.java
@@ -49,7 +49,6 @@
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.ssh.NoSshInfo;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
@@ -63,7 +62,7 @@
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.transport.ReceiveCommand;
-public class PatchSetInserter implements BatchUpdateOp, AsyncPostUpdateOp {
+public class PatchSetInserter implements BatchUpdateOp {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public interface Factory {
@@ -110,7 +109,6 @@
private ChangeMessage changeMessage;
private ReviewerSet oldReviewers;
private boolean oldWorkInProgressState;
- private NotifyResolver.Result notify;
@Inject
public PatchSetInserter(
@@ -281,12 +279,12 @@
throw new BadRequestException(ex.getMessage());
}
}
- notify = ctx.getNotify(change.getId());
return true;
}
@Override
- public void asyncPostUpdate(Context ctx) {
+ public void postUpdate(Context ctx) {
+ NotifyResolver.Result notify = ctx.getNotify(change.getId());
if (notify.shouldNotify() && sendEmail) {
requireNonNull(changeMessage);
try {
@@ -306,10 +304,7 @@
"Cannot send email for new patch set on change %s", change.getId());
}
}
- }
- @Override
- public void postUpdate(Context ctx) {
if (fireRevisionCreated) {
revisionCreated.fire(change, patchSet, ctx.getAccount(), ctx.getWhen(), notify);
}
diff --git a/java/com/google/gerrit/server/change/RebaseChangeOp.java b/java/com/google/gerrit/server/change/RebaseChangeOp.java
index a8cc75a..231359b 100644
--- a/java/com/google/gerrit/server/change/RebaseChangeOp.java
+++ b/java/com/google/gerrit/server/change/RebaseChangeOp.java
@@ -34,7 +34,6 @@
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
@@ -49,7 +48,7 @@
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
-public class RebaseChangeOp implements BatchUpdateOp, AsyncPostUpdateOp {
+public class RebaseChangeOp implements BatchUpdateOp {
public interface Factory {
RebaseChangeOp create(ChangeNotes notes, PatchSet originalPatchSet, ObjectId baseCommitId);
}
@@ -222,11 +221,6 @@
patchSetInserter.postUpdate(ctx);
}
- @Override
- public void asyncPostUpdate(Context ctx) {
- patchSetInserter.asyncPostUpdate(ctx);
- }
-
public RevCommit getRebasedCommit() {
checkState(rebasedCommit != null, "getRebasedCommit() only valid after updateRepo");
return rebasedCommit;
diff --git a/java/com/google/gerrit/server/change/RemoveFromAttentionSetOp.java b/java/com/google/gerrit/server/change/RemoveFromAttentionSetOp.java
index 7f4e0e3..e532409 100644
--- a/java/com/google/gerrit/server/change/RemoveFromAttentionSetOp.java
+++ b/java/com/google/gerrit/server/change/RemoveFromAttentionSetOp.java
@@ -26,7 +26,6 @@
import com.google.gerrit.server.mail.send.RemoveFromAttentionSetSender;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
@@ -37,7 +36,7 @@
import java.util.Optional;
/** Remove a specified user from the attention set. */
-public class RemoveFromAttentionSetOp implements BatchUpdateOp, AsyncPostUpdateOp {
+public class RemoveFromAttentionSetOp implements BatchUpdateOp {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public interface Factory {
@@ -102,7 +101,7 @@
}
@Override
- public void asyncPostUpdate(Context ctx) {
+ public void postUpdate(Context ctx) {
if (!notify) {
return;
}
@@ -115,7 +114,7 @@
reason,
messageIdGenerator.fromChangeUpdate(ctx.getRepoView(), change.currentPatchSetId()),
attentionUserId)
- .send();
+ .sendAsync();
} catch (IOException e) {
logger.atSevere().withCause(e).log(e.getMessage(), change.getId());
}
diff --git a/java/com/google/gerrit/server/change/ReviewerAdder.java b/java/com/google/gerrit/server/change/ReviewerAdder.java
index 3638bf2..3d986d2 100644
--- a/java/com/google/gerrit/server/change/ReviewerAdder.java
+++ b/java/com/google/gerrit/server/change/ReviewerAdder.java
@@ -587,7 +587,7 @@
}
}
- public void postUpdate(Context ctx) {
+ public void postUpdate(Context ctx) throws Exception {
for (ReviewerAddition addition : additions()) {
if (addition.op != null) {
addition.op.postUpdate(ctx);
@@ -595,14 +595,6 @@
}
}
- public void asyncPostUpdate(Context ctx) {
- for (ReviewerAddition addition : additions()) {
- if (addition.op != null) {
- addition.op.asyncPostUpdate(ctx);
- }
- }
- }
-
public <T> ImmutableSet<T> flattenResults(
Function<AddReviewersOp.Result, ? extends Collection<T>> func) {
additions()
diff --git a/java/com/google/gerrit/server/change/SetAssigneeOp.java b/java/com/google/gerrit/server/change/SetAssigneeOp.java
index c2e36f5..411c9b6 100644
--- a/java/com/google/gerrit/server/change/SetAssigneeOp.java
+++ b/java/com/google/gerrit/server/change/SetAssigneeOp.java
@@ -28,7 +28,6 @@
import com.google.gerrit.server.mail.send.SetAssigneeSender;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.plugincontext.PluginSetContext;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
@@ -38,7 +37,7 @@
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
-public class SetAssigneeOp implements BatchUpdateOp, AsyncPostUpdateOp {
+public class SetAssigneeOp implements BatchUpdateOp {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public interface Factory {
@@ -121,7 +120,7 @@
}
@Override
- public void asyncPostUpdate(Context ctx) {
+ public void postUpdate(Context ctx) {
try {
SetAssigneeSender emailSender =
setAssigneeSenderFactory.create(
@@ -134,10 +133,6 @@
logger.atSevere().withCause(err).log(
"Cannot send email to new assignee of change %s", change.getId());
}
- }
-
- @Override
- public void postUpdate(Context ctx) {
assigneeChanged.fire(
change, ctx.getAccount(), oldAssignee != null ? oldAssignee.state() : null, ctx.getWhen());
}
diff --git a/java/com/google/gerrit/server/change/WorkInProgressOp.java b/java/com/google/gerrit/server/change/WorkInProgressOp.java
index 99f7adb..f0ebb80 100644
--- a/java/com/google/gerrit/server/change/WorkInProgressOp.java
+++ b/java/com/google/gerrit/server/change/WorkInProgressOp.java
@@ -28,7 +28,6 @@
import com.google.gerrit.server.extensions.events.WorkInProgressStateChanged;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
@@ -38,7 +37,7 @@
import java.io.IOException;
/* Set work in progress or ready for review state on a change */
-public class WorkInProgressOp implements BatchUpdateOp, AsyncPostUpdateOp {
+public class WorkInProgressOp implements BatchUpdateOp {
public static class Input extends InputWithMessage {
@Nullable public NotifyHandling notify;
@@ -127,7 +126,8 @@
}
@Override
- public void asyncPostUpdate(Context ctx) {
+ public void postUpdate(Context ctx) {
+ stateChanged.fire(change, ps, ctx.getAccount(), ctx.getWhen());
NotifyResolver.Result notify = ctx.getNotify(change.getId());
if (workInProgress
|| notify.handling().compareTo(NotifyHandling.OWNER_REVIEWERS) < 0
@@ -152,11 +152,6 @@
cmsg.getMessage(),
ImmutableList.of(),
repoView)
- .send();
- }
-
- @Override
- public void postUpdate(Context ctx) {
- stateChanged.fire(change, ps, ctx.getAccount(), ctx.getWhen());
+ .sendAsync();
}
}
diff --git a/java/com/google/gerrit/server/config/AsyncPostUpdateExecutor.java b/java/com/google/gerrit/server/config/SendEmailExecutor.java
similarity index 90%
rename from java/com/google/gerrit/server/config/AsyncPostUpdateExecutor.java
rename to java/com/google/gerrit/server/config/SendEmailExecutor.java
index 7951b8c..cf90cbf 100644
--- a/java/com/google/gerrit/server/config/AsyncPostUpdateExecutor.java
+++ b/java/com/google/gerrit/server/config/SendEmailExecutor.java
@@ -1,4 +1,4 @@
-// Copyright (C) 2020 The Android Open Source Project
+// Copyright (C) 2014 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -23,4 +23,4 @@
/** Marker on the global {@link ScheduledThreadPoolExecutor} used to send email. */
@Retention(RUNTIME)
@BindingAnnotation
-public @interface AsyncPostUpdateExecutor {}
+public @interface SendEmailExecutor {}
diff --git a/java/com/google/gerrit/server/config/SysExecutorModule.java b/java/com/google/gerrit/server/config/SysExecutorModule.java
index 5caf6fe..ea45b12 100644
--- a/java/com/google/gerrit/server/config/SysExecutorModule.java
+++ b/java/com/google/gerrit/server/config/SysExecutorModule.java
@@ -51,20 +51,14 @@
@Provides
@Singleton
- @AsyncPostUpdateExecutor
+ @SendEmailExecutor
public ExecutorService provideSendEmailExecutor(
@GerritServerConfig Config config, WorkQueue queues) {
- // sendemail.threadPoolSize is deprecated and overridden by asyncPostUpdate.threadPoolSize.
- int poolSize =
- config.getInt(
- "asyncPostUpdate",
- null,
- "threadPoolSize",
- config.getInt("sendemail", null, "threadPoolSize", 1));
+ int poolSize = config.getInt("sendemail", null, "threadPoolSize", 1);
if (poolSize == 0) {
return newDirectExecutorService();
}
- return queues.createQueue(poolSize, "AsyncPostUpdate", true);
+ return queues.createQueue(poolSize, "SendEmail", true);
}
@Provides
diff --git a/java/com/google/gerrit/server/git/CommitUtil.java b/java/com/google/gerrit/server/git/CommitUtil.java
index 67c7f01..47cbd60 100644
--- a/java/com/google/gerrit/server/git/CommitUtil.java
+++ b/java/com/google/gerrit/server/git/CommitUtil.java
@@ -45,7 +45,6 @@
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
import com.google.gerrit.server.notedb.Sequences;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
@@ -301,7 +300,7 @@
return changeId;
}
- private class NotifyOp implements BatchUpdateOp, AsyncPostUpdateOp {
+ private class NotifyOp implements BatchUpdateOp {
private final Change change;
private final ChangeInserter ins;
@@ -311,12 +310,8 @@
}
@Override
- public void postUpdate(Context ctx) {
+ public void postUpdate(Context ctx) throws Exception {
changeReverted.fire(change, ins.getChange(), ctx.getWhen());
- }
-
- @Override
- public void asyncPostUpdate(Context ctx) {
try {
RevertedSender emailSender = revertedSenderFactory.create(ctx.getProject(), change.getId());
emailSender.setFrom(ctx.getAccountId());
diff --git a/java/com/google/gerrit/server/git/MergedByPushOp.java b/java/com/google/gerrit/server/git/MergedByPushOp.java
index 13625bc..40e2730 100644
--- a/java/com/google/gerrit/server/git/MergedByPushOp.java
+++ b/java/com/google/gerrit/server/git/MergedByPushOp.java
@@ -25,19 +25,22 @@
import com.google.gerrit.entities.SubmissionId;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.PatchSetUtil;
+import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.extensions.events.ChangeMerged;
import com.google.gerrit.server.mail.send.MergedSender;
import com.google.gerrit.server.mail.send.MessageIdGenerator;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.patch.PatchSetInfoFactory;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
+import com.google.gerrit.server.util.RequestScopePropagator;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -49,21 +52,24 @@
* <p>When we find a change corresponding to a commit that is pushed to a branch directly, we close
* the change. This class marks the change as merged, and sends out the email notification.
*/
-public class MergedByPushOp implements BatchUpdateOp, AsyncPostUpdateOp {
+public class MergedByPushOp implements BatchUpdateOp {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public interface Factory {
MergedByPushOp create(
+ RequestScopePropagator requestScopePropagator,
PatchSet.Id psId,
@Assisted SubmissionId submissionId,
@Assisted("refName") String refName,
@Assisted("mergeResultRevId") String mergeResultRevId);
}
+ private final RequestScopePropagator requestScopePropagator;
private final PatchSetInfoFactory patchSetInfoFactory;
private final ChangeMessagesUtil cmUtil;
private final MergedSender.Factory mergedSenderFactory;
private final PatchSetUtil psUtil;
+ private final ExecutorService sendEmailExecutor;
private final ChangeMerged changeMerged;
private final MessageIdGenerator messageIdGenerator;
@@ -84,8 +90,10 @@
ChangeMessagesUtil cmUtil,
MergedSender.Factory mergedSenderFactory,
PatchSetUtil psUtil,
+ @SendEmailExecutor ExecutorService sendEmailExecutor,
ChangeMerged changeMerged,
MessageIdGenerator messageIdGenerator,
+ @Assisted RequestScopePropagator requestScopePropagator,
@Assisted PatchSet.Id psId,
@Assisted SubmissionId submissionId,
@Assisted("refName") String refName,
@@ -94,8 +102,10 @@
this.cmUtil = cmUtil;
this.mergedSenderFactory = mergedSenderFactory;
this.psUtil = psUtil;
+ this.sendEmailExecutor = sendEmailExecutor;
this.changeMerged = changeMerged;
this.messageIdGenerator = messageIdGenerator;
+ this.requestScopePropagator = requestScopePropagator;
this.submissionId = submissionId;
this.psId = psId;
this.refName = refName;
@@ -171,27 +181,36 @@
if (!correctBranch) {
return;
}
+ @SuppressWarnings("unused") // Runnable already handles errors
+ Future<?> possiblyIgnoredError =
+ sendEmailExecutor.submit(
+ requestScopePropagator.wrap(
+ new Runnable() {
+ @Override
+ public void run() {
+ try {
+ MergedSender emailSender =
+ mergedSenderFactory.create(ctx.getProject(), psId.changeId());
+ emailSender.setFrom(ctx.getAccountId());
+ emailSender.setPatchSet(patchSet, info);
+ emailSender.setMessageId(
+ messageIdGenerator.fromChangeUpdate(ctx.getRepoView(), patchSet.id()));
+ emailSender.send();
+ } catch (Exception e) {
+ logger.atSevere().withCause(e).log(
+ "Cannot send email for submitted patch set %s", psId);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "send-email merged";
+ }
+ }));
+
changeMerged.fire(change, patchSet, ctx.getAccount(), mergeResultRevId, ctx.getWhen());
}
- @Override
- public void asyncPostUpdate(Context ctx) {
- if (!correctBranch) {
- return;
- }
-
- try {
- MergedSender emailSender = mergedSenderFactory.create(ctx.getProject(), psId.changeId());
- emailSender.setFrom(ctx.getAccountId());
- emailSender.setPatchSet(patchSet, info);
- emailSender.setMessageId(
- messageIdGenerator.fromChangeUpdate(ctx.getRepoView(), patchSet.id()));
- emailSender.send();
- } catch (Exception e) {
- logger.atSevere().withCause(e).log("Cannot send email for submitted patch set %s", psId);
- }
- }
-
private PatchSetInfo getPatchSetInfo(ChangeContext ctx) throws IOException {
RevWalk rw = ctx.getRevWalk();
RevCommit commit = rw.parseCommit(requireNonNull(patchSet).commitId());
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
index e44f422..015ed0b 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -175,6 +175,7 @@
import com.google.gerrit.server.update.UpdateException;
import com.google.gerrit.server.util.LabelVote;
import com.google.gerrit.server.util.MagicBranch;
+import com.google.gerrit.server.util.RequestScopePropagator;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.gerrit.server.validators.ValidationException;
import com.google.gerrit.util.cli.CmdLineParser;
@@ -338,6 +339,7 @@
private final PluginSetContext<RequestListener> requestListeners;
private final PublishCommentsOp.Factory publishCommentsOp;
private final RetryHelper retryHelper;
+ private final RequestScopePropagator requestScopePropagator;
private final Sequences seq;
private final SetHashtagsOp.Factory hashtagsFactory;
private final SubmoduleOp.Factory subOpFactory;
@@ -419,6 +421,7 @@
ReplaceOp.Factory replaceOpFactory,
PluginSetContext<RequestListener> requestListeners,
RetryHelper retryHelper,
+ RequestScopePropagator requestScopePropagator,
Sequences seq,
SetHashtagsOp.Factory hashtagsFactory,
SubmoduleOp.Factory subOpFactory,
@@ -467,6 +470,7 @@
this.replaceOpFactory = replaceOpFactory;
this.requestListeners = requestListeners;
this.retryHelper = retryHelper;
+ this.requestScopePropagator = requestScopePropagator;
this.seq = seq;
this.subOpFactory = subOpFactory;
this.tagCache = tagCache;
@@ -2582,6 +2586,7 @@
magicBranch.getCombinedCcs(fromFooters))
.setApprovals(approvals)
.setMessage(msg.toString())
+ .setRequestScopePropagator(requestScopePropagator)
.setSendMail(true)
.setPatchSetDescription(magicBranch.message));
if (!magicBranch.hashtags.isEmpty()) {
@@ -3008,20 +3013,22 @@
RevCommit priorCommit = revisions.inverse().get(priorPatchSet);
replaceOp =
- replaceOpFactory.create(
- projectState,
- notes.getChange().getDest(),
- checkMergedInto,
- checkMergedInto ? inputCommand.getNewId().name() : null,
- priorPatchSet,
- priorCommit,
- psId,
- newCommit,
- info,
- groups,
- magicBranch,
- receivePack.getPushCertificate(),
- notes.getChange());
+ replaceOpFactory
+ .create(
+ projectState,
+ notes.getChange().getDest(),
+ checkMergedInto,
+ checkMergedInto ? inputCommand.getNewId().name() : null,
+ priorPatchSet,
+ priorCommit,
+ psId,
+ newCommit,
+ info,
+ groups,
+ magicBranch,
+ receivePack.getPushCertificate(),
+ notes.getChange())
+ .setRequestScopePropagator(requestScopePropagator);
bu.addOp(notes.getChangeId(), replaceOp);
if (progress != null) {
bu.addOp(notes.getChangeId(), new ChangeProgressOp(progress));
@@ -3302,7 +3309,11 @@
bu.addOp(
psId.changeId(),
mergedByPushOpFactory.create(
- psId, submissionId, refName, newTip.getId().getName()));
+ requestScopePropagator,
+ psId,
+ submissionId,
+ refName,
+ newTip.getId().getName()));
continue COMMIT;
}
}
@@ -3346,7 +3357,12 @@
bu.addOp(
id,
mergedByPushOpFactory
- .create(req.psId, submissionId, refName, newTip.getId().getName())
+ .create(
+ requestScopePropagator,
+ req.psId,
+ submissionId,
+ refName,
+ newTip.getId().getName())
.setPatchSetProvider(req.replaceOp::getPatchSet));
bu.addOp(id, new ChangeProgressOp(progress));
ids.add(id);
diff --git a/java/com/google/gerrit/server/git/receive/ReplaceOp.java b/java/com/google/gerrit/server/git/receive/ReplaceOp.java
index 87266f3..ce62d7a 100644
--- a/java/com/google/gerrit/server/git/receive/ReplaceOp.java
+++ b/java/com/google/gerrit/server/git/receive/ReplaceOp.java
@@ -56,6 +56,7 @@
import com.google.gerrit.server.change.ReviewerAdder.InternalAddReviewerInput;
import com.google.gerrit.server.change.ReviewerAdder.ReviewerAddition;
import com.google.gerrit.server.change.ReviewerAdder.ReviewerAdditionList;
+import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.config.UrlFormatter;
import com.google.gerrit.server.extensions.events.CommentAdded;
import com.google.gerrit.server.extensions.events.RevisionCreated;
@@ -70,11 +71,11 @@
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
import com.google.gerrit.server.update.RepoContext;
+import com.google.gerrit.server.util.RequestScopePropagator;
import com.google.gerrit.server.validators.ValidationException;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
@@ -85,6 +86,8 @@
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ObjectId;
@@ -93,7 +96,7 @@
import org.eclipse.jgit.transport.PushCertificate;
import org.eclipse.jgit.transport.ReceiveCommand;
-public class ReplaceOp implements BatchUpdateOp, AsyncPostUpdateOp {
+public class ReplaceOp implements BatchUpdateOp {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public interface Factory {
@@ -120,6 +123,7 @@
private final ChangeData.Factory changeDataFactory;
private final ChangeKindCache changeKindCache;
private final ChangeMessagesUtil cmUtil;
+ private final ExecutorService sendEmailExecutor;
private final RevisionCreated revisionCreated;
private final CommentAdded commentAdded;
private final MergedByPushOp.Factory mergedByPushOpFactory;
@@ -153,6 +157,7 @@
private ChangeMessage msg;
private String rejectMessage;
private MergedByPushOp mergedByPushOp;
+ private RequestScopePropagator requestScopePropagator;
private ReviewerAdditionList reviewerAdditions;
private MailRecipients oldRecipients;
@@ -169,6 +174,7 @@
PatchSetUtil psUtil,
ReplacePatchSetSender.Factory replacePatchSetFactory,
ProjectCache projectCache,
+ @SendEmailExecutor ExecutorService sendEmailExecutor,
ReviewerAdder reviewerAdder,
Change change,
MessageIdGenerator messageIdGenerator,
@@ -196,6 +202,7 @@
this.psUtil = psUtil;
this.replacePatchSetFactory = replacePatchSetFactory;
this.projectCache = projectCache;
+ this.sendEmailExecutor = sendEmailExecutor;
this.reviewerAdder = reviewerAdder;
this.change = change;
this.messageIdGenerator = messageIdGenerator;
@@ -232,7 +239,11 @@
if (mergedInto != null) {
mergedByPushOp =
mergedByPushOpFactory.create(
- patchSetId, new SubmissionId(change), mergedInto, mergeResultRevId);
+ requestScopePropagator,
+ patchSetId,
+ new SubmissionId(change),
+ mergedInto,
+ mergeResultRevId);
}
}
@@ -482,8 +493,18 @@
}
@Override
- public void postUpdate(Context ctx) {
+ public void postUpdate(Context ctx) throws Exception {
reviewerAdditions.postUpdate(ctx);
+ if (changeKind != ChangeKind.TRIVIAL_REBASE) {
+ // TODO(dborowitz): Merge email templates so we only have to send one.
+ Runnable e = new ReplaceEmailTask(ctx);
+ if (requestScopePropagator != null) {
+ @SuppressWarnings("unused")
+ Future<?> possiblyIgnoredError = sendEmailExecutor.submit(requestScopePropagator.wrap(e));
+ } else {
+ e.run();
+ }
+ }
NotifyResolver.Result notify = ctx.getNotify(notes.getChangeId());
revisionCreated.fire(notes.getChange(), newPatchSet, ctx.getAccount(), ctx.getWhen(), notify);
try {
@@ -496,11 +517,15 @@
}
}
- @Override
- public void asyncPostUpdate(Context ctx) {
- reviewerAdditions.asyncPostUpdate(ctx);
- if (changeKind != ChangeKind.TRIVIAL_REBASE) {
- // TODO(dborowitz): Merge email templates so we only have to send one.
+ private class ReplaceEmailTask implements Runnable {
+ private final Context ctx;
+
+ private ReplaceEmailTask(Context ctx) {
+ this.ctx = ctx;
+ }
+
+ @Override
+ public void run() {
try {
ReplacePatchSetSender emailSender =
replacePatchSetFactory.create(projectState.getNameKey(), notes.getChangeId());
@@ -528,8 +553,10 @@
"Cannot send email for new patch set %s", newPatchSet.id());
}
}
- if (mergedByPushOp != null) {
- mergedByPushOp.asyncPostUpdate(ctx);
+
+ @Override
+ public String toString() {
+ return "send-email newpatchset";
}
}
@@ -586,6 +613,11 @@
return cmd;
}
+ public ReplaceOp setRequestScopePropagator(RequestScopePropagator requestScopePropagator) {
+ this.requestScopePropagator = requestScopePropagator;
+ return this;
+ }
+
private static String findMergedInto(Context ctx, String first, RevCommit commit) {
try {
RevWalk rw = ctx.getRevWalk();
diff --git a/java/com/google/gerrit/server/mail/receive/MailProcessor.java b/java/com/google/gerrit/server/mail/receive/MailProcessor.java
index c983c09..df38118 100644
--- a/java/com/google/gerrit/server/mail/receive/MailProcessor.java
+++ b/java/com/google/gerrit/server/mail/receive/MailProcessor.java
@@ -62,7 +62,6 @@
import com.google.gerrit.server.plugincontext.PluginSetContext;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
@@ -310,7 +309,7 @@
}
}
- private class Op implements BatchUpdateOp, AsyncPostUpdateOp {
+ private class Op implements BatchUpdateOp {
private final PatchSet.Id psId;
private final List<MailComment> parsedComments;
private final String tag;
@@ -354,26 +353,6 @@
@Override
public void postUpdate(Context ctx) throws Exception {
- // Get previous approvals from this user
- Map<String, Short> approvals = new HashMap<>();
- approvalsUtil
- .byPatchSetUser(
- notes, psId, ctx.getAccountId(), ctx.getRevWalk(), ctx.getRepoView().getConfig())
- .forEach(a -> approvals.put(a.label(), a.value()));
- // Fire Gerrit event. Note that approvals can't be granted via email, so old and new approvals
- // are always the same here.
- commentAdded.fire(
- notes.getChange(),
- patchSet,
- ctx.getAccount(),
- changeMessage.getMessage(),
- approvals,
- approvals,
- ctx.getWhen());
- }
-
- @Override
- public void asyncPostUpdate(Context ctx) throws Exception {
String patchSetComment = null;
if (parsedComments.get(0).getType() == MailComment.CommentType.CHANGE_MESSAGE) {
patchSetComment = parsedComments.get(0).getMessage();
@@ -390,7 +369,23 @@
patchSetComment,
ImmutableList.of(),
ctx.getRepoView())
- .send();
+ .sendAsync();
+ // Get previous approvals from this user
+ Map<String, Short> approvals = new HashMap<>();
+ approvalsUtil
+ .byPatchSetUser(
+ notes, psId, ctx.getAccountId(), ctx.getRevWalk(), ctx.getRepoView().getConfig())
+ .forEach(a -> approvals.put(a.label(), a.value()));
+ // Fire Gerrit event. Note that approvals can't be granted via email, so old and new approvals
+ // are always the same here.
+ commentAdded.fire(
+ notes.getChange(),
+ patchSet,
+ ctx.getAccount(),
+ changeMessage.getMessage(),
+ approvals,
+ approvals,
+ ctx.getWhen());
}
private ChangeMessage generateChangeMessage(ChangeContext ctx) {
diff --git a/java/com/google/gerrit/server/restapi/change/DeleteVote.java b/java/com/google/gerrit/server/restapi/change/DeleteVote.java
index 22c3567..4b813df 100644
--- a/java/com/google/gerrit/server/restapi/change/DeleteVote.java
+++ b/java/com/google/gerrit/server/restapi/change/DeleteVote.java
@@ -50,7 +50,6 @@
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.project.RemoveReviewerControl;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
@@ -147,7 +146,7 @@
return Response.none();
}
- private class Op implements BatchUpdateOp, AsyncPostUpdateOp {
+ private class Op implements BatchUpdateOp {
private final ProjectState projectState;
private final AccountState accountState;
private final String label;
@@ -222,30 +221,17 @@
@Override
public void postUpdate(Context ctx) {
- voteDeleted.fire(
- change,
- ps,
- accountState,
- newApprovals,
- oldApprovals,
- input.notify,
- changeMessage.getMessage(),
- ctx.getIdentifiedUser().state(),
- ctx.getWhen());
- }
-
- @Override
- public void asyncPostUpdate(Context ctx) {
if (changeMessage == null) {
return;
}
+ IdentifiedUser user = ctx.getIdentifiedUser();
try {
NotifyResolver.Result notify = ctx.getNotify(change.getId());
if (notify.shouldNotify()) {
ReplyToChangeSender emailSender =
deleteVoteSenderFactory.create(ctx.getProject(), change.getId());
- emailSender.setFrom(ctx.getIdentifiedUser().getAccountId());
+ emailSender.setFrom(user.getAccountId());
emailSender.setChangeMessage(changeMessage.getMessage(), ctx.getWhen());
emailSender.setNotify(notify);
emailSender.setMessageId(
@@ -255,6 +241,17 @@
} catch (Exception e) {
logger.atSevere().withCause(e).log("Cannot email update for change %s", change.getId());
}
+
+ voteDeleted.fire(
+ change,
+ ps,
+ accountState,
+ newApprovals,
+ oldApprovals,
+ input.notify,
+ changeMessage.getMessage(),
+ user.state(),
+ ctx.getWhen());
}
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/PostReview.java b/java/com/google/gerrit/server/restapi/change/PostReview.java
index 843bfd2..3367ca6 100644
--- a/java/com/google/gerrit/server/restapi/change/PostReview.java
+++ b/java/com/google/gerrit/server/restapi/change/PostReview.java
@@ -119,7 +119,6 @@
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
@@ -448,7 +447,7 @@
ccByEmail.addAll(addition.reviewersByEmail);
}
}
- addReviewersEmail.emailReviewers(
+ addReviewersEmail.emailReviewersAsync(
user.asIdentifiedUser(), change, to, cc, toByEmail, ccByEmail, notify);
}
}
@@ -870,7 +869,7 @@
abstract Comment.Range range();
}
- private class Op implements BatchUpdateOp, AsyncPostUpdateOp {
+ private class Op implements BatchUpdateOp {
private final ProjectState projectState;
private final PatchSet.Id psId;
private final ReviewInput in;
@@ -916,7 +915,7 @@
}
@Override
- public void asyncPostUpdate(Context ctx) {
+ public void postUpdate(Context ctx) {
if (message == null) {
return;
}
@@ -934,20 +933,12 @@
in.message,
labelDelta,
ctx.getRepoView())
- .send();
+ .sendAsync();
} catch (IOException ex) {
throw new StorageException(
String.format("Repository %s not found", ctx.getProject().get()), ex);
}
}
- }
-
- @Override
- public void postUpdate(Context ctx) {
- if (message == null) {
- return;
- }
-
commentAdded.fire(
notes.getChange(),
ps,
diff --git a/java/com/google/gerrit/server/restapi/change/Restore.java b/java/com/google/gerrit/server/restapi/change/Restore.java
index 26b9d4c..7faf8e0 100644
--- a/java/com/google/gerrit/server/restapi/change/Restore.java
+++ b/java/com/google/gerrit/server/restapi/change/Restore.java
@@ -44,7 +44,6 @@
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
@@ -109,7 +108,7 @@
return Response.ok(json.noOptions().format(op.change));
}
- private class Op implements BatchUpdateOp, AsyncPostUpdateOp {
+ private class Op implements BatchUpdateOp {
private final RestoreInput input;
private Change change;
@@ -150,12 +149,6 @@
@Override
public void postUpdate(Context ctx) {
- changeRestored.fire(
- change, patchSet, ctx.getAccount(), Strings.emptyToNull(input.message), ctx.getWhen());
- }
-
- @Override
- public void asyncPostUpdate(Context ctx) {
try {
ReplyToChangeSender emailSender =
restoredSenderFactory.create(ctx.getProject(), change.getId());
@@ -167,6 +160,8 @@
} catch (Exception e) {
logger.atSevere().withCause(e).log("Cannot email update for change %s", change.getId());
}
+ changeRestored.fire(
+ change, patchSet, ctx.getAccount(), Strings.emptyToNull(input.message), ctx.getWhen());
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/RevertSubmission.java b/java/com/google/gerrit/server/restapi/change/RevertSubmission.java
index d128186..ca39a57 100644
--- a/java/com/google/gerrit/server/restapi/change/RevertSubmission.java
+++ b/java/com/google/gerrit/server/restapi/change/RevertSubmission.java
@@ -72,7 +72,6 @@
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.restapi.change.CherryPickChange.Result;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
@@ -601,7 +600,7 @@
}
}
- private class NotifyOp implements BatchUpdateOp, AsyncPostUpdateOp {
+ private class NotifyOp implements BatchUpdateOp {
private final Change change;
private final Change.Id revertChangeId;
@@ -611,13 +610,9 @@
}
@Override
- public void postUpdate(Context ctx) {
+ public void postUpdate(Context ctx) throws Exception {
changeReverted.fire(
change, changeNotesFactory.createChecked(revertChangeId).getChange(), ctx.getWhen());
- }
-
- @Override
- public void asyncPostUpdate(Context ctx) {
try {
RevertedSender emailSender = revertedSenderFactory.create(ctx.getProject(), change.getId());
emailSender.setFrom(ctx.getAccountId());
diff --git a/java/com/google/gerrit/server/submit/EmailMerge.java b/java/com/google/gerrit/server/submit/EmailMerge.java
index c7671b0..4efa4c8 100644
--- a/java/com/google/gerrit/server/submit/EmailMerge.java
+++ b/java/com/google/gerrit/server/submit/EmailMerge.java
@@ -19,14 +19,22 @@
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.Project;
+import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.change.NotifyResolver;
+import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.mail.send.MergedSender;
import com.google.gerrit.server.mail.send.MessageIdGenerator;
import com.google.gerrit.server.update.RepoView;
+import com.google.gerrit.server.util.RequestContext;
+import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.inject.Inject;
+import com.google.inject.OutOfScopeException;
import com.google.inject.assistedinject.Assisted;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
-class EmailMerge {
+class EmailMerge implements Runnable, RequestContext {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
interface Factory {
@@ -38,7 +46,10 @@
RepoView repoView);
}
+ private final ExecutorService sendEmailsExecutor;
private final MergedSender.Factory mergedSenderFactory;
+ private final ThreadLocalRequestContext requestContext;
+ private final IdentifiedUser.GenericFactory identifiedUserFactory;
private final MessageIdGenerator messageIdGenerator;
private final Project.NameKey project;
@@ -49,14 +60,20 @@
@Inject
EmailMerge(
+ @SendEmailExecutor ExecutorService executor,
MergedSender.Factory mergedSenderFactory,
+ ThreadLocalRequestContext requestContext,
+ IdentifiedUser.GenericFactory identifiedUserFactory,
MessageIdGenerator messageIdGenerator,
@Assisted Project.NameKey project,
@Assisted Change change,
@Assisted @Nullable Account.Id submitter,
@Assisted NotifyResolver.Result notify,
@Assisted RepoView repoView) {
+ this.sendEmailsExecutor = executor;
this.mergedSenderFactory = mergedSenderFactory;
+ this.requestContext = requestContext;
+ this.identifiedUserFactory = identifiedUserFactory;
this.messageIdGenerator = messageIdGenerator;
this.project = project;
this.change = change;
@@ -65,7 +82,14 @@
this.repoView = repoView;
}
- public void send() {
+ void sendAsync() {
+ @SuppressWarnings("unused")
+ Future<?> possiblyIgnoredError = sendEmailsExecutor.submit(this);
+ }
+
+ @Override
+ public void run() {
+ RequestContext old = requestContext.setContext(this);
try {
MergedSender emailSender = mergedSenderFactory.create(project, change.getId());
if (submitter != null) {
@@ -77,6 +101,21 @@
emailSender.send();
} catch (Exception e) {
logger.atSevere().withCause(e).log("Cannot email merged notification for %s", change.getId());
+ } finally {
+ requestContext.setContext(old);
}
}
+
+ @Override
+ public String toString() {
+ return "send-email merged";
+ }
+
+ @Override
+ public CurrentUser getUser() {
+ if (submitter != null) {
+ return identifiedUserFactory.create(submitter).getRealUser();
+ }
+ throw new OutOfScopeException("No user on email thread");
+ }
}
diff --git a/java/com/google/gerrit/server/submit/RebaseSubmitStrategy.java b/java/com/google/gerrit/server/submit/RebaseSubmitStrategy.java
index 3629640..edc3725 100644
--- a/java/com/google/gerrit/server/submit/RebaseSubmitStrategy.java
+++ b/java/com/google/gerrit/server/submit/RebaseSubmitStrategy.java
@@ -275,13 +275,6 @@
rebaseOp.postUpdate(ctx);
}
}
-
- @Override
- public void asyncPostUpdateImpl(Context ctx) {
- if (rebaseOp != null) {
- rebaseOp.asyncPostUpdate(ctx);
- }
- }
}
private class MergeIfNecessaryOp extends SubmitStrategyOp {
diff --git a/java/com/google/gerrit/server/submit/SubmitStrategyOp.java b/java/com/google/gerrit/server/submit/SubmitStrategyOp.java
index 201eba8..3cc566b 100644
--- a/java/com/google/gerrit/server/submit/SubmitStrategyOp.java
+++ b/java/com/google/gerrit/server/submit/SubmitStrategyOp.java
@@ -43,7 +43,6 @@
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.ProjectState;
-import com.google.gerrit.server.update.AsyncPostUpdateOp;
import com.google.gerrit.server.update.BatchUpdateOp;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.Context;
@@ -61,7 +60,7 @@
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.ReceiveCommand;
-abstract class SubmitStrategyOp implements BatchUpdateOp, AsyncPostUpdateOp {
+abstract class SubmitStrategyOp implements BatchUpdateOp {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
protected final SubmitStrategy.Arguments args;
@@ -484,22 +483,8 @@
}
}
- if (mergeResultRev != null && !args.dryrun) {
- args.changeMerged.fire(
- updatedChange,
- mergedPatchSet,
- args.accountCache.get(submitter.accountId()).orElse(null),
- args.mergeTip.getCurrentTip().name(),
- ctx.getWhen());
- }
- }
-
- /**
- * Assume the change must have been merged at this point, otherwise we would have failed in one of
- * the other steps in postUpdate (which is done prior to this method).
- */
- @Override
- public final void asyncPostUpdate(Context ctx) {
+ // Assume the change must have been merged at this point, otherwise we would
+ // have failed fast in one of the other steps.
try {
args.mergedSenderFactory
.create(
@@ -508,11 +493,18 @@
submitter.accountId(),
ctx.getNotify(getId()),
ctx.getRepoView())
- .send();
+ .sendAsync();
} catch (Exception e) {
logger.atSevere().withCause(e).log("Cannot email merged notification for %s", getId());
}
- asyncPostUpdateImpl(ctx);
+ if (mergeResultRev != null && !args.dryrun) {
+ args.changeMerged.fire(
+ updatedChange,
+ mergedPatchSet,
+ args.accountCache.get(submitter.accountId()).orElse(null),
+ args.mergeTip.getCurrentTip().name(),
+ ctx.getWhen());
+ }
}
/**
@@ -537,12 +529,6 @@
protected void postUpdateImpl(Context ctx) throws Exception {}
/**
- * @see #asyncPostUpdate(Context)
- * @param ctx
- */
- protected void asyncPostUpdateImpl(Context ctx) {}
-
- /**
* Amend the commit with gitlink update
*
* @param commit
diff --git a/java/com/google/gerrit/server/update/AsyncPostUpdateOp.java b/java/com/google/gerrit/server/update/AsyncPostUpdateOp.java
deleted file mode 100644
index 9a989b7..0000000
--- a/java/com/google/gerrit/server/update/AsyncPostUpdateOp.java
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.update;
-
-import com.google.gerrit.server.config.SysExecutorModule;
-
-/** Base interface for operations performed asynchronously as part of a {@link BatchUpdate}. */
-public interface AsyncPostUpdateOp {
-
- /**
- * Override this method to do something after the update e.g. send emails. This method will be
- * invoked asynchronously, and when invoked, the invoking method will not wait for the async
- * updates to finish. This method will be called after {@link BatchUpdateOp} operations and {@link
- * RepoOnlyOp} are finished.
- *
- * <p>The maximum amount of threads in the thread pool is decided by
- * asyncPostUpdate.threadPoolSize. When asyncPostUpdate.threadPoolSize is not specified, the
- * deprecated sendemail.threadPoolSize is used (see {@link
- * SysExecutorModule#provideSendEmailExecutor}). This is the case for legacy reasons, since in the
- * past only some emails were sent async (and sendemail.threadPoolSize) was used, and now all
- * emails (and possibly others) are done async, so asyncPostUpdate.threadPoolSize is used.
- *
- * @param ctx context
- */
- default void asyncPostUpdate(Context ctx) throws Exception {}
-}
diff --git a/java/com/google/gerrit/server/update/BatchUpdate.java b/java/com/google/gerrit/server/update/BatchUpdate.java
index 2fdc124..166e88d 100644
--- a/java/com/google/gerrit/server/update/BatchUpdate.java
+++ b/java/com/google/gerrit/server/update/BatchUpdate.java
@@ -47,7 +47,6 @@
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.account.AccountState;
import com.google.gerrit.server.change.NotifyResolver;
-import com.google.gerrit.server.config.AsyncPostUpdateExecutor;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.validators.OnSubmitValidators;
@@ -63,7 +62,6 @@
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.NoSuchProjectException;
import com.google.gerrit.server.project.NoSuchRefException;
-import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.assistedinject.Assisted;
@@ -77,7 +75,6 @@
import java.util.Optional;
import java.util.TimeZone;
import java.util.TreeMap;
-import java.util.concurrent.ExecutorService;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
@@ -335,8 +332,6 @@
private final NoteDbUpdateManager.Factory updateManagerFactory;
private final ChangeIndexer indexer;
private final GitReferenceUpdated gitRefUpdated;
- private final ThreadLocalRequestContext requestContext;
- private final ExecutorService executorService;
private final Project.NameKey project;
private final CurrentUser user;
@@ -365,8 +360,6 @@
NoteDbUpdateManager.Factory updateManagerFactory,
ChangeIndexer indexer,
GitReferenceUpdated gitRefUpdated,
- ThreadLocalRequestContext requestContext,
- @AsyncPostUpdateExecutor ExecutorService executorService,
@Assisted Project.NameKey project,
@Assisted CurrentUser user,
@Assisted Timestamp when) {
@@ -376,8 +369,6 @@
this.updateManagerFactory = updateManagerFactory;
this.indexer = indexer;
this.gitRefUpdated = gitRefUpdated;
- this.requestContext = requestContext;
- this.executorService = executorService;
this.project = project;
this.user = user;
this.when = when;
@@ -646,40 +637,23 @@
return new ChangeContextImpl(notes);
}
- private void executePostOps() {
+ private void executePostOps() throws Exception {
ContextImpl ctx = new ContextImpl();
for (BatchUpdateOp op : ops.values()) {
- postUpdate(ctx, op);
- if (op instanceof AsyncPostUpdateOp) {
- asyncPostUpdate(ctx, ((AsyncPostUpdateOp) op));
+ try (TraceContext.TraceTimer ignored =
+ TraceContext.newTimer(op.getClass().getSimpleName() + "#postUpdate", Metadata.empty())) {
+ op.postUpdate(ctx);
}
}
for (RepoOnlyOp op : repoOnlyOps) {
- postUpdate(ctx, op);
- if (op instanceof AsyncPostUpdateOp) {
- asyncPostUpdate(ctx, ((AsyncPostUpdateOp) op));
+ try (TraceContext.TraceTimer ignored =
+ TraceContext.newTimer(op.getClass().getSimpleName() + "#postUpdate", Metadata.empty())) {
+ op.postUpdate(ctx);
}
}
}
- /** Invoke the postUpdate methods synchronously. */
- private void postUpdate(ContextImpl ctx, RepoOnlyOp op) {
- try (TraceContext.TraceTimer ignored =
- TraceContext.newTimer(op.getClass().getSimpleName() + "#postUpdate", Metadata.empty())) {
- op.postUpdate(ctx);
- } catch (Exception ex) {
- logDebug(
- String.format(
- "postUpdate for project %s failed for user %s", ctx.getProject(), ctx.getUser()));
- }
- }
-
- /** Invoke the asyncPostUpdate methods asynchronously. */
- private void asyncPostUpdate(ContextImpl ctx, AsyncPostUpdateOp op) {
- executorService.execute(new ExecuteAsyncPostUpdate(op, ctx, user, requestContext));
- }
-
private static void logDebug(String msg) {
// Only log if there is a requestId assigned, since those are the
// expensive/complicated requests like MergeOp. Doing it every time would be
diff --git a/java/com/google/gerrit/server/update/ExecuteAsyncPostUpdate.java b/java/com/google/gerrit/server/update/ExecuteAsyncPostUpdate.java
deleted file mode 100644
index e640ab1..0000000
--- a/java/com/google/gerrit/server/update/ExecuteAsyncPostUpdate.java
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright (C) 2020 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.update;
-
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.util.RequestContext;
-import com.google.gerrit.server.util.ThreadLocalRequestContext;
-
-/** Executes {@link AsyncPostUpdateOp#asyncPostUpdate(Context)} on a specific op, asynchronously. */
-public class ExecuteAsyncPostUpdate implements Runnable, RequestContext {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- private final AsyncPostUpdateOp op;
- private final Context ctx;
- private final CurrentUser user;
- private final ThreadLocalRequestContext threadLocalRequestContext;
-
- ExecuteAsyncPostUpdate(
- AsyncPostUpdateOp op,
- Context ctx,
- CurrentUser user,
- ThreadLocalRequestContext threadLocalRequestContext) {
- this.op = op;
- this.ctx = ctx;
- this.user = user;
- this.threadLocalRequestContext = threadLocalRequestContext;
- }
-
- @Override
- public void run() {
- RequestContext old = threadLocalRequestContext.setContext(this);
- try {
- op.asyncPostUpdate(ctx);
- } catch (Exception e) {
- logger.atSevere().withCause(e).log(
- "Cannot perform async post update for repo %s and user %s",
- ctx.getProject(), ctx.getAccount().account().getName());
- } finally {
- threadLocalRequestContext.setContext(old);
- }
- }
-
- @Override
- public String toString() {
- return "async-post-update";
- }
-
- @Override
- public CurrentUser getUser() {
- return user;
- }
-}
diff --git a/java/com/google/gerrit/server/update/RepoOnlyOp.java b/java/com/google/gerrit/server/update/RepoOnlyOp.java
index f9b41c4..7e9c47e 100644
--- a/java/com/google/gerrit/server/update/RepoOnlyOp.java
+++ b/java/com/google/gerrit/server/update/RepoOnlyOp.java
@@ -30,11 +30,10 @@
default void updateRepo(RepoContext ctx) throws Exception {}
/**
- * Override this method to do something after the update e.g. run hooks. This method will
- * <strong>NOT</strong> be invoked asynchronously. This method will be finished before {@link
- * AsyncPostUpdateOp#asyncPostUpdate} is called.
+ * Override this method to do something after the update e.g. send email or run hooks
*
* @param ctx context
*/
+ // TODO(dborowitz): Support async operations?
default void postUpdate(Context ctx) throws Exception {}
}
diff --git a/java/com/google/gerrit/server/util/AttentionSetEmail.java b/java/com/google/gerrit/server/util/AttentionSetEmail.java
index 2b09c49..56b1dda 100644
--- a/java/com/google/gerrit/server/util/AttentionSetEmail.java
+++ b/java/com/google/gerrit/server/util/AttentionSetEmail.java
@@ -17,7 +17,9 @@
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
+import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.account.AccountState;
+import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.mail.send.AddToAttentionSetSender;
import com.google.gerrit.server.mail.send.AttentionSetSender;
import com.google.gerrit.server.mail.send.MessageIdGenerator;
@@ -25,8 +27,10 @@
import com.google.gerrit.server.update.Context;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
-public class AttentionSetEmail {
+public class AttentionSetEmail implements Runnable, RequestContext {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public interface Factory {
@@ -51,6 +55,7 @@
Account.Id attentionUserId);
}
+ private ExecutorService sendEmailsExecutor;
private AttentionSetSender sender;
private Context ctx;
private Change change;
@@ -61,12 +66,14 @@
@Inject
AttentionSetEmail(
+ @SendEmailExecutor ExecutorService executor,
@Assisted AttentionSetSender sender,
@Assisted Context ctx,
@Assisted Change change,
@Assisted String reason,
@Assisted MessageIdGenerator.MessageId messageId,
@Assisted Account.Id attentionUserId) {
+ this.sendEmailsExecutor = executor;
this.sender = sender;
this.ctx = ctx;
this.change = change;
@@ -75,7 +82,13 @@
this.attentionUserId = attentionUserId;
}
- public void send() {
+ public void sendAsync() {
+ @SuppressWarnings("unused")
+ Future<?> possiblyIgnoredError = sendEmailsExecutor.submit(this);
+ }
+
+ @Override
+ public void run() {
try {
AccountState accountState =
ctx.getUser().isIdentifiedUser() ? ctx.getUser().asIdentifiedUser().state() : null;
@@ -91,4 +104,14 @@
logger.atSevere().withCause(e).log("Cannot email update for change %s", change.getId());
}
}
+
+ @Override
+ public String toString() {
+ return "send-email comments";
+ }
+
+ @Override
+ public CurrentUser getUser() {
+ return ctx.getUser();
+ }
}
diff --git a/java/com/google/gerrit/testing/FakeEmailSender.java b/java/com/google/gerrit/testing/FakeEmailSender.java
index f73020a..fec9b27 100644
--- a/java/com/google/gerrit/testing/FakeEmailSender.java
+++ b/java/com/google/gerrit/testing/FakeEmailSender.java
@@ -128,7 +128,6 @@
}
public synchronized @Nullable Message peekMessage() {
- waitForEmails();
if (messagesRead >= messages.size()) {
return null;
}
@@ -136,14 +135,9 @@
}
public synchronized @Nullable Message nextMessage() {
- waitForEmails();
Message msg = peekMessage();
- readOneMessage();
- return msg;
- }
-
- public synchronized void readOneMessage() {
messagesRead++;
+ return msg;
}
public ImmutableList<Message> getMessages() {
@@ -166,7 +160,7 @@
// a single thread in tests (tricky because most callers just use the
// default executor).
for (WorkQueue.Task<?> task : workQueue.getTasks()) {
- if (task.toString().contains("async-post-update")) {
+ if (task.toString().contains("send-email")) {
try {
task.get();
} catch (ExecutionException | InterruptedException e) {
diff --git a/java/com/google/gerrit/testing/InMemoryModule.java b/java/com/google/gerrit/testing/InMemoryModule.java
index 693fd90..6c9fbed 100644
--- a/java/com/google/gerrit/testing/InMemoryModule.java
+++ b/java/com/google/gerrit/testing/InMemoryModule.java
@@ -47,7 +47,6 @@
import com.google.gerrit.server.config.AllUsersNameProvider;
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.config.AnonymousCowardNameProvider;
-import com.google.gerrit.server.config.AsyncPostUpdateExecutor;
import com.google.gerrit.server.config.CanonicalWebUrlModule;
import com.google.gerrit.server.config.CanonicalWebUrlProvider;
import com.google.gerrit.server.config.DefaultUrlFormatter;
@@ -59,6 +58,7 @@
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.GerritServerId;
import com.google.gerrit.server.config.GerritServerIdProvider;
+import com.google.gerrit.server.config.SendEmailExecutor;
import com.google.gerrit.server.config.SitePath;
import com.google.gerrit.server.config.TrackingFooters;
import com.google.gerrit.server.config.TrackingFootersProvider;
@@ -279,7 +279,7 @@
@Provides
@Singleton
- @AsyncPostUpdateExecutor
+ @SendEmailExecutor
public ExecutorService createSendEmailExecutor() {
return newDirectExecutorService();
}
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
index 0bfd525..d4affb7 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -284,11 +284,6 @@
String fileName = "a_new_file.txt";
String fileContent = "First line\nSecond line\n";
PushOneCommit.Result result = createChange("Add a file", fileName, fileContent);
-
- // Emails are sent here async which triggers cache hits, so we must wait until those email are
- // actually sent.
- sender.clear();
-
String triplet = project.get() + "~master~" + result.getChangeId();
CacheStats startPatch = cloneStats(fileCache.stats());
CacheStats startIntra = cloneStats(intraCache.stats());
diff --git a/javatests/com/google/gerrit/acceptance/git/AbstractSubmitOnPush.java b/javatests/com/google/gerrit/acceptance/git/AbstractSubmitOnPush.java
index aafe9b9..23bcdec 100644
--- a/javatests/com/google/gerrit/acceptance/git/AbstractSubmitOnPush.java
+++ b/javatests/com/google/gerrit/acceptance/git/AbstractSubmitOnPush.java
@@ -412,17 +412,17 @@
sender.clear();
result = pushTo(pushSpec + ",submit,notify=" + NotifyHandling.OWNER_REVIEWERS);
result.assertOkStatus();
- assertThatEmailsForChangeCreationAndSubmitWereSent(result.getChangeId(), user, null);
+ assertThatEmailsForChangeCreationAndSubmitWereSent(user, null);
sender.clear();
result = pushTo(pushSpec + ",submit,notify=" + NotifyHandling.ALL);
result.assertOkStatus();
- assertThatEmailsForChangeCreationAndSubmitWereSent(result.getChangeId(), user, null);
+ assertThatEmailsForChangeCreationAndSubmitWereSent(user, null);
sender.clear();
result = pushTo(pushSpec + ",submit"); // default is notify = ALL
result.assertOkStatus();
- assertThatEmailsForChangeCreationAndSubmitWereSent(result.getChangeId(), user, null);
+ assertThatEmailsForChangeCreationAndSubmitWereSent(user, null);
}
@Test
@@ -442,22 +442,19 @@
PushOneCommit.Result result =
pushTo(pushSpec + ",submit,notify=" + NotifyHandling.NONE + ",notify-to=" + user2.email());
result.assertOkStatus();
- assertThatEmailsForChangeCreationAndSubmitWereSent(
- result.getChangeId(), user2, RecipientType.TO);
+ assertThatEmailsForChangeCreationAndSubmitWereSent(user2, RecipientType.TO);
sender.clear();
result =
pushTo(pushSpec + ",submit,notify=" + NotifyHandling.NONE + ",notify-cc=" + user2.email());
result.assertOkStatus();
- assertThatEmailsForChangeCreationAndSubmitWereSent(
- result.getChangeId(), user2, RecipientType.CC);
+ assertThatEmailsForChangeCreationAndSubmitWereSent(user2, RecipientType.CC);
sender.clear();
result =
pushTo(pushSpec + ",submit,notify=" + NotifyHandling.NONE + ",notify-bcc=" + user2.email());
result.assertOkStatus();
- assertThatEmailsForChangeCreationAndSubmitWereSent(
- result.getChangeId(), user2, RecipientType.BCC);
+ assertThatEmailsForChangeCreationAndSubmitWereSent(user2, RecipientType.BCC);
}
private PatchSetApproval getSubmitter(PatchSet.Id patchSetId) throws Exception {
@@ -518,15 +515,15 @@
* sent as "To" and sometimes can be sent as "Cc".
*/
private void assertThatEmailsForChangeCreationAndSubmitWereSent(
- String changeId, TestAccount expected, @Nullable RecipientType expectedRecipientType) {
+ TestAccount expected, @Nullable RecipientType expectedRecipientType) {
String expectedEmail = expected.email();
String expectedFullName = expected.fullName();
Address expectedAddress = Address.create(expectedFullName, expectedEmail);
assertThat(sender.getMessages()).hasSize(2);
- Message message = Iterables.getOnlyElement(sender.getMessages(changeId, "newchange"));
+ Message message = sender.getMessages().get(0);
assertThat(message.body().contains("review")).isTrue();
assertAddress(message, expectedAddress, expectedRecipientType);
- message = Iterables.getOnlyElement(sender.getMessages(changeId, "merged"));
+ message = sender.getMessages().get(1);
assertThat(message.rcpt()).containsExactly(expectedAddress);
assertAddress(message, expectedAddress, expectedRecipientType);
assertThat(message.body().contains("submitted")).isTrue();
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
index e040860..a6bd5eb 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
@@ -28,7 +28,6 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.RestResponse;
@@ -399,13 +398,13 @@
List<Message> messages = sender.getMessages();
assertThat(messages).hasSize(2);
- Message m = Iterables.getOnlyElement(sender.getMessages(r.getChangeId(), "comment"));
+ Message m = messages.get(0);
assertThat(m.rcpt()).containsExactly(user.getNameEmail(), observer.getNameEmail());
assertThat(m.body()).contains(admin.fullName() + " has posted comments on this change.");
assertThat(m.body()).contains("Change subject: " + PushOneCommit.SUBJECT + "\n");
assertThat(m.body()).contains("Patch Set 1: Code-Review+2");
- m = Iterables.getOnlyElement(sender.getMessages(r.getChangeId(), "newchange"));
+ m = messages.get(1);
assertThat(m.rcpt()).containsExactly(user.getNameEmail(), observer.getNameEmail());
assertThat(m.body()).contains("Hello " + user.fullName() + ",\n");
assertThat(m.body()).contains("I'd like you to do a code review.");
diff --git a/javatests/com/google/gerrit/acceptance/server/git/receive/ReceiveCommitsCommentValidationIT.java b/javatests/com/google/gerrit/acceptance/server/git/receive/ReceiveCommitsCommentValidationIT.java
index 7570ce9..1a01184 100644
--- a/javatests/com/google/gerrit/acceptance/server/git/receive/ReceiveCommitsCommentValidationIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/git/receive/ReceiveCommitsCommentValidationIT.java
@@ -124,14 +124,12 @@
List<FakeEmailSender.Message> messages = sender.getMessages();
assertThat(messages).hasSize(2);
- FakeEmailSender.Message newPatchsetMessage =
- Iterables.getOnlyElement(sender.getMessages(changeId, "newpatchset"));
+ FakeEmailSender.Message newPatchsetMessage = messages.get(0);
assertThat(newPatchsetMessage.body()).contains("new patch set");
assertThat(newPatchsetMessage.headers().get("Message-ID").toString())
.doesNotContain("EmailReviewComments");
- FakeEmailSender.Message newCommentsMessage =
- Iterables.getOnlyElement(sender.getMessages(changeId, "comment"));
+ FakeEmailSender.Message newCommentsMessage = messages.get(1);
assertThat(newCommentsMessage.body()).contains("has posted comments on this change");
assertThat(newCommentsMessage.headers().get("Message-ID").toString())
.contains("EmailReviewComments");
diff --git a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts
index 7bcd833..b75c26d 100644
--- a/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts
+++ b/polygerrit-ui/app/elements/edit/gr-editor-view/gr-editor-view.ts
@@ -127,9 +127,9 @@
/** @override */
created() {
super.created();
- this.addEventListener('content-change', e =>
- this._handleContentChange(e as CustomEvent<{value: string}>)
- );
+ this.addEventListener('content-change', e => {
+ this._handleContentChange(e as CustomEvent<{value: string}>);
+ });
}
/** @override */
diff --git a/polygerrit-ui/app/styles/shared-styles.ts b/polygerrit-ui/app/styles/shared-styles.ts
index 3b738a4..fbc62e2 100644
--- a/polygerrit-ui/app/styles/shared-styles.ts
+++ b/polygerrit-ui/app/styles/shared-styles.ts
@@ -135,7 +135,7 @@
/* Stopgap solution until we remove hidden$ attributes. */
- :host[hidden],
+ :host([hidden]),
[hidden] {
display: none !important;
}