From 9c51ac3f8de2a4a38503fcee7eb4e20bd051d1b2 Mon Sep 17 00:00:00 2001 From: Trisha Anand Date: Tue, 28 Jul 2020 20:06:12 +0530 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A5=20&=20forget=20asynchronous=20emai?= =?UTF-8?q?l=20sending=20(#187)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Email sending is now an asynchronous function. It follows a 🔥 & forget strategy to make it run asynchronously. --- .../server/notifications/EmailSender.java | 23 ++++++++++++------- .../server/services/UserServiceImpl.java | 2 +- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/notifications/EmailSender.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/notifications/EmailSender.java index 5bac64dab0..a76503497e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/notifications/EmailSender.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/notifications/EmailSender.java @@ -9,9 +9,9 @@ import org.springframework.mail.MailException; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; import reactor.core.Exceptions; import reactor.core.publisher.Mono; +import reactor.core.scheduler.Schedulers; import javax.mail.MessagingException; import javax.mail.internet.InternetAddress; @@ -51,7 +51,7 @@ public class EmailSender { return matcher.find(); } - public Mono sendMail(String to, String subject, String text, Map params) { + public Mono sendMail(String to, String subject, String text, Map params) { return Mono .fromSupplier(() -> { try { @@ -60,15 +60,22 @@ public class EmailSender { throw Exceptions.propagate(e); } }) - .flatMap(emailBody -> sendMail(to, subject, emailBody)); - } - - public Mono sendMail(String to, String subject, String text) { - return Mono.fromRunnable(() -> sendMailSync(to, subject, text)); + // Sending email is a high cost I/O operation. Schedule the same on non-netty threads + // to implement a fire-and-forget strategy. + // CAUTION : We may run into scenarios where too many tasks have been created and queued and the master tasks have already exited with success. + .doOnNext(emailBody -> + Mono.fromRunnable(() -> { + sendMailSync(to, subject, emailBody); + }) + // Scheduling using boundedElastic because the number of active tasks are capped + // and hence not allowing the background threads to grow indefinitely + .subscribeOn(Schedulers.boundedElastic()) + .subscribe() + ); } /** - * This function sends an HTML email to the user from the default email address + * [Synchronous]This function sends an HTML email to the user from the default email address * * @param to Single valid string email address to send to. Multiple addresses doesn't work. * @param subject Subject string. diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserServiceImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserServiceImpl.java index 58ab45e1e6..c30a7de09c 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserServiceImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/services/UserServiceImpl.java @@ -641,7 +641,7 @@ public class UserServiceImpl extends BaseService i } params.put("inviter_org_name", updatedOrg.getName()); - Mono emailMono; + Mono emailMono; if (userExisted.get()) { // If the user already existed, just send an email informing that the user has been added // to a new organization