Subversion Repositories SmartDukaan

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
36337 amit 1
package com.spice.profitmandi.service.cron;
2
 
3
import com.spice.profitmandi.dao.entity.transaction.CronBatch;
4
import com.spice.profitmandi.dao.entity.transaction.CronBatchItem;
5
import com.spice.profitmandi.dao.enumuration.transaction.CronBatchItemStatus;
6
import com.spice.profitmandi.dao.enumuration.transaction.CronBatchStatus;
7
import com.spice.profitmandi.dao.repository.transaction.CronBatchItemRepository;
8
import com.spice.profitmandi.dao.repository.transaction.CronBatchRepository;
9
import com.spice.profitmandi.service.mail.MailOutboxService;
10
import org.apache.logging.log4j.LogManager;
11
import org.apache.logging.log4j.Logger;
12
import org.springframework.beans.factory.annotation.Autowired;
13
import org.springframework.stereotype.Service;
14
import org.springframework.transaction.annotation.Propagation;
15
import org.springframework.transaction.annotation.Transactional;
16
 
17
import java.time.LocalDateTime;
18
import java.time.format.DateTimeFormatter;
19
import java.util.List;
20
import java.util.Map;
21
 
22
@Service
23
public class CronBatchService {
24
 
25
    private static final Logger LOGGER = LogManager.getLogger(CronBatchService.class);
26
    private static final String[] TECHNOLOGY_EMAIL = {"amit.gupta@smartdukaan.com"};
27
    private static final DateTimeFormatter DTF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
28
 
29
    @Autowired
30
    private CronBatchRepository cronBatchRepository;
31
 
32
    @Autowired
33
    private CronBatchItemRepository cronBatchItemRepository;
34
 
35
    @Autowired
36
    private MailOutboxService mailOutboxService;
37
 
38
    @Transactional(propagation = Propagation.REQUIRES_NEW)
39
    public CronBatch createBatch(String jobName, Map<Integer, String> fofoIdPartnerNameMap) {
40
        CronBatch batch = new CronBatch(jobName);
41
        batch.setTotalCount(fofoIdPartnerNameMap.size());
42
        cronBatchRepository.persist(batch);
43
 
44
        for (Map.Entry<Integer, String> entry : fofoIdPartnerNameMap.entrySet()) {
45
            CronBatchItem item = new CronBatchItem(batch.getId(), entry.getKey(), entry.getValue());
46
            cronBatchItemRepository.persist(item);
47
        }
48
 
49
        LOGGER.info("Created batch {} for job {} with {} items", batch.getId(), jobName, fofoIdPartnerNameMap.size());
50
        return batch;
51
    }
52
 
53
    @Transactional(propagation = Propagation.REQUIRES_NEW)
54
    public void markItemSuccess(int batchId, int fofoId) {
55
        List<CronBatchItem> items = cronBatchItemRepository.selectByBatchIdAndStatus(batchId, CronBatchItemStatus.PENDING);
56
        for (CronBatchItem item : items) {
57
            if (item.getFofoId() == fofoId) {
58
                item.markSuccess();
59
                break;
60
            }
61
        }
62
    }
63
 
64
    @Transactional(propagation = Propagation.REQUIRES_NEW)
65
    public void markItemFailed(int batchId, int fofoId, String errorMessage) {
66
        List<CronBatchItem> items = cronBatchItemRepository.selectByBatchIdAndStatus(batchId, CronBatchItemStatus.PENDING);
67
        for (CronBatchItem item : items) {
68
            if (item.getFofoId() == fofoId) {
69
                item.markFailed(errorMessage);
70
                break;
71
            }
72
        }
73
    }
74
 
75
    @Transactional(propagation = Propagation.REQUIRES_NEW)
76
    public void finalizeBatch(int batchId) {
77
        CronBatch batch = cronBatchRepository.selectById(batchId);
78
        List<CronBatchItem> failedItems = cronBatchItemRepository.selectFailedByBatchId(batchId);
79
 
80
        int failureCount = failedItems.size();
81
        int successCount = batch.getTotalCount() - failureCount;
82
 
83
        batch.setSuccessCount(successCount);
84
        batch.setFailureCount(failureCount);
85
        batch.setCompletedAt(LocalDateTime.now());
86
        batch.setStatus(failureCount == 0 ? CronBatchStatus.COMPLETED : CronBatchStatus.PARTIAL_FAILURE);
87
 
88
        LOGGER.info("Batch {} finalized: {} success, {} failed", batchId, successCount, failureCount);
89
 
90
        if (failureCount > 0) {
91
            sendFailureEmail(batch, failedItems);
92
        }
93
    }
94
 
95
    private void sendFailureEmail(CronBatch batch, List<CronBatchItem> failedItems) {
96
        StringBuilder body = new StringBuilder();
97
        body.append("Cron job: ").append(batch.getJobName()).append("\n");
98
        body.append("Run time: ").append(batch.getStartedAt().format(DTF)).append("\n");
99
        body.append("Total processed: ").append(batch.getTotalCount()).append("\n");
100
        body.append("Success: ").append(batch.getSuccessCount()).append("\n");
101
        body.append("Failures: ").append(batch.getFailureCount()).append("\n\n");
102
        body.append("Partner failures:\n");
103
 
104
        for (CronBatchItem item : failedItems) {
105
            body.append("- ").append(item.getPartnerName())
106
                    .append(" (fofoId: ").append(item.getFofoId()).append(")")
107
                    .append(" — ").append(item.getErrorMessage())
108
                    .append("\n");
109
        }
110
 
111
        String subject = String.format("[CRON ALERT] %s — %d of %d partners failed",
112
                batch.getJobName(), batch.getFailureCount(), batch.getTotalCount());
113
 
114
        try {
115
            mailOutboxService.queueMailViaGoogle(TECHNOLOGY_EMAIL, null, subject, body.toString(),
116
                    "CronBatchService." + batch.getJobName());
117
        } catch (Exception e) {
118
            LOGGER.error("Failed to send batch failure email for batch {}: {}", batch.getId(), e.getMessage());
119
        }
120
    }
121
}