Subversion Repositories SmartDukaan

Rev

Rev 36399 | Rev 37473 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 36399 Rev 37361
Line 7... Line 7...
7
import org.apache.logging.log4j.LogManager;
7
import org.apache.logging.log4j.LogManager;
8
import org.apache.logging.log4j.Logger;
8
import org.apache.logging.log4j.Logger;
9
import org.springframework.beans.factory.annotation.Autowired;
9
import org.springframework.beans.factory.annotation.Autowired;
10
import org.springframework.beans.factory.annotation.Qualifier;
10
import org.springframework.beans.factory.annotation.Qualifier;
11
import org.springframework.beans.factory.annotation.Value;
11
import org.springframework.beans.factory.annotation.Value;
-
 
12
import org.springframework.context.annotation.Lazy;
12
import org.springframework.core.io.ByteArrayResource;
13
import org.springframework.core.io.ByteArrayResource;
13
import org.springframework.core.io.InputStreamSource;
14
import org.springframework.core.io.InputStreamSource;
14
import org.springframework.mail.javamail.JavaMailSender;
15
import org.springframework.mail.javamail.JavaMailSender;
15
import org.springframework.mail.javamail.MimeMessageHelper;
16
import org.springframework.mail.javamail.MimeMessageHelper;
16
import org.springframework.stereotype.Service;
17
import org.springframework.stereotype.Service;
Line 22... Line 23...
22
import java.io.File;
23
import java.io.File;
23
import java.io.IOException;
24
import java.io.IOException;
24
import java.io.InputStream;
25
import java.io.InputStream;
25
import java.nio.file.Files;
26
import java.nio.file.Files;
26
import java.time.LocalDateTime;
27
import java.time.LocalDateTime;
-
 
28
import java.util.ArrayList;
27
import java.util.List;
29
import java.util.List;
28
 
30
 
29
@Service
31
@Service
30
public class MailOutboxService {
32
public class MailOutboxService {
31
 
33
 
Line 46... Line 48...
46
    private String devRecipient;
48
    private String devRecipient;
47
 
49
 
48
    @Autowired
50
    @Autowired
49
    private MailOutboxRepository mailOutboxRepository;
51
    private MailOutboxRepository mailOutboxRepository;
50
 
52
 
-
 
53
    /**
-
 
54
     * Self-reference so each mail is sent in its own transaction. Calling the
-
 
55
     * @Transactional methods directly would bypass the proxy and put the whole
-
 
56
     * batch back into a single transaction.
-
 
57
     */
-
 
58
    @Autowired
-
 
59
    @Lazy
-
 
60
    private MailOutboxService self;
-
 
61
 
51
    @Autowired
62
    @Autowired
52
    @Qualifier("googleMailSender")
63
    @Qualifier("googleMailSender")
53
    private JavaMailSender googleMailSender;
64
    private JavaMailSender googleMailSender;
54
 
65
 
55
    @Autowired
66
    @Autowired
Line 207... Line 218...
207
            }
218
            }
208
        }
219
        }
209
 
220
 
210
    }
221
    }
211
 
222
 
212
    @Transactional(propagation = Propagation.REQUIRES_NEW)
-
 
213
    public void processPendingMails() {
223
    public void processPendingMails() {
-
 
224
        List<Long> pendingIds = self.selectPendingIds();
-
 
225
        LOGGER.info("Processing {} pending mails", pendingIds.size());
-
 
226
        for (Long mailId : pendingIds) {
-
 
227
            try {
-
 
228
                self.sendOne(mailId);
-
 
229
            } catch (Exception e) {
-
 
230
                LOGGER.error("Unexpected error processing mail id={}", mailId, e);
-
 
231
            }
-
 
232
        }
-
 
233
    }
-
 
234
 
-
 
235
    @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
-
 
236
    public List<Long> selectPendingIds() {
214
        List<MailOutbox> pendingMails = mailOutboxRepository.selectPending();
237
        List<MailOutbox> pendingMails = mailOutboxRepository.selectPending();
215
        LOGGER.info("Processing {} pending mails", pendingMails.size());
238
        List<Long> ids = new ArrayList<>(pendingMails.size());
216
        for (MailOutbox mail : pendingMails) {
239
        for (MailOutbox mail : pendingMails) {
217
            sendAndUpdateStatus(mail);
240
            ids.add(mail.getId());
-
 
241
        }
-
 
242
        return ids;
-
 
243
    }
-
 
244
 
-
 
245
    /**
-
 
246
     * One transaction per mail so the outcome is committed as soon as it is known.
-
 
247
     * A crash mid-batch can then lose at most the status of the mail in flight,
-
 
248
     * instead of re-sending every mail already delivered in this cycle.
-
 
249
     */
-
 
250
    @Transactional(propagation = Propagation.REQUIRES_NEW)
-
 
251
    public void sendOne(long mailId) {
-
 
252
        MailOutbox mail = mailOutboxRepository.findById(mailId);
-
 
253
        if (mail == null) {
-
 
254
            return;
218
        }
255
        }
-
 
256
        sendAndUpdateStatus(mail);
219
    }
257
    }
220
 
258
 
221
    @Transactional(propagation = Propagation.REQUIRES_NEW)
259
    @Transactional(propagation = Propagation.REQUIRES_NEW)
222
    public void cleanupOldMails(int daysOld) {
260
    public void cleanupOldMails(int daysOld) {
223
        mailOutboxRepository.deleteOldSentMails(daysOld);
261
        mailOutboxRepository.deleteOldSentMails(daysOld);
Line 282... Line 320...
282
            for (MailOutboxAttachment att : attachments) {
320
            for (MailOutboxAttachment att : attachments) {
283
                helper.addAttachment(att.getFileName(), new ByteArrayResource(att.getFileData()));
321
                helper.addAttachment(att.getFileName(), new ByteArrayResource(att.getFileData()));
284
            }
322
            }
285
        }
323
        }
286
 
324
 
-
 
325
        // Stable per-row Message-ID: a retry then arrives as the same message rather
-
 
326
        // than a new one, so the receiving server can collapse it. Spring preserves an
-
 
327
        // explicitly set Message-ID across MimeMessage.saveChanges().
-
 
328
        message.setHeader("Message-ID", "<mailoutbox-" + mail.getId() + "@smartdukaan.com>");
-
 
329
 
287
        sender.send(message);
330
        sender.send(message);
288
    }
331
    }
289
 
332
 
290
    private JavaMailSender resolveSender(String senderType) {
333
    private JavaMailSender resolveSender(String senderType) {
291
        if (SENDER_GOOGLE.equals(senderType)) {
334
        if (SENDER_GOOGLE.equals(senderType)) {