# CrewFaxTask.java

    package cloud.wconnect.frontoffice.businesstask.clc;

    import cloud.wconnect.commonlib.cons.BaseConstant;
    import cloud.wconnect.commonlib.service.MailInternalService;
    import cloud.wconnect.commonlib.util.DateTimeUtils;
    import cloud.wconnect.frontoffice.entity.clc.ClcSiteCrewFax;
    import cloud.wconnect.frontoffice.service.clc.IClcSiteCrewFaxService;
    import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.scheduling.annotation.Scheduled;
    import org.springframework.stereotype.Component;

    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    import java.util.concurrent.TimeUnit;

    /**
     * Task: crew fax
     *
     * @author yyt
     * 2023/7/26
     */
    @Slf4j
    @Component
    public class CrewFaxTask {

        @Autowired
        private RedisTemplate<String, Object> redisTemplate;
        @Autowired
        private MailInternalService mailInternalService;
        @Value("${default.timezone}")
        private String defaultTimezone;
        @Autowired
        private IClcSiteCrewFaxService clcSiteCrewFaxService;

        private static final String PREFIX_KEY = "wconnect:task:clc-clear-historical-data:";

        /**
         * 清除历史数据（check-out-date超过90天）
         *
         * @author yyt
         * @date 2023/7/26
         */
        @Scheduled(cron = "${schedule.cron.notify.clc-crew-fax-clear-historical-data}", zone = "${default.timezone}")
        public void clearHistoricalData() {
            log.info("clearCrewFaxHistoricalData... start");
            String alertTitle = "[Warning] - Exceptions About Auto Clear Crew Fax Historical Data";
            StringBuilder warningEmail = new StringBuilder("<p>There is something wrong when auto clear crew fax historical data.</p>");

            try {
                // 处理并发
                String currentDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern(BaseConstant.DATE_FORMAT_YYMMDDHH));
                if (!preventConcurrency(PREFIX_KEY + currentDate)) {
                    log.warn("clearCrewFaxHistoricalData... date:{}. other machines have already executed", currentDate);
                    log.info("clearCrewFaxHistoricalData... end");
                    return;
                }

                // 清除 check-out-date 距今超过90天的数据
                long ninetyDaysAgo = DateTimeUtils.dateNow(defaultTimezone).minusDays(90).toEpochSecond();
                clcSiteCrewFaxService.remove(new QueryWrapper<ClcSiteCrewFax>().lambda().le(ClcSiteCrewFax::getCheckOutDate, ninetyDaysAgo));

            } catch (Exception e) {
                log.warn("clearCrewFaxHistoricalData...  exception occurs:", e);
                warningEmail.append("<p>Exception:").append(e).append("</p>");
                mailInternalService.sendAlertEmail(alertTitle, warningEmail.toString());
            }

            log.info("clearCrewFaxHistoricalData... end");
        }

        /**
         * 防止并发
         *
         * @param key 唯一标识
         * @return 锁成功
         * @author yyt
         * @date 2023/7/26
         */
        private Boolean preventConcurrency(String key) {
            return redisTemplate.opsForValue().setIfAbsent(key, 0, 1, TimeUnit.DAYS);
        }

    }