SUPPORT-9561: fix url saving and scheduler

This commit is contained in:
gulnaz 2025-11-26 11:47:59 +03:00
parent fb30eb553d
commit 491ffd9504
6 changed files with 62 additions and 49 deletions

View file

@ -0,0 +1,14 @@
package ervu.enums;
import ru.cg.webbpm.modules.webkit.annotations.Model;
/**
* @author gulnaz
*/
@Model
public enum ExcerptStatus {
NONE,
PENDING,
READY,
NOT_FOUND
}

View file

@ -5,6 +5,7 @@ import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit; import java.time.temporal.ChronoUnit;
import java.util.Optional; import java.util.Optional;
import ervu.enums.ExcerptStatus;
import ervu_lkrp_ul.ervu_lkrp_ul.db_beans.public_.tables.records.ExcerptHistoryRecord; import ervu_lkrp_ul.ervu_lkrp_ul.db_beans.public_.tables.records.ExcerptHistoryRecord;
import org.jooq.DSLContext; import org.jooq.DSLContext;
import org.jooq.impl.DSL; import org.jooq.impl.DSL;
@ -29,7 +30,7 @@ public class ExcerptHistoryDao {
} }
public Optional<ExcerptHistoryRecord> get(String ervuId, String prnOid) { public Optional<ExcerptHistoryRecord> get(String ervuId, String prnOid) {
return dslContext.select(EXCERPT_HISTORY.ID) return dslContext.select(EXCERPT_HISTORY.ID, EXCERPT_HISTORY.URL)
.from(EXCERPT_HISTORY) .from(EXCERPT_HISTORY)
.where(EXCERPT_HISTORY.ID.eq( .where(EXCERPT_HISTORY.ID.eq(
select(DSL.max(EXCERPT_HISTORY.ID)) select(DSL.max(EXCERPT_HISTORY.ID))
@ -43,19 +44,11 @@ public class ExcerptHistoryDao {
public String getStatus(String ervuId, String prnOid) { public String getStatus(String ervuId, String prnOid) {
return dslContext.select(coalesce( return dslContext.select(coalesce(
field( field(select(EXCERPT_HISTORY.STATUS)
select(
case_()
.when(EXCERPT_HISTORY.DATETIME.isNull(), "in-progress")
.else_("ready")
)
.from(EXCERPT_HISTORY) .from(EXCERPT_HISTORY)
.where( .where(EXCERPT_HISTORY.ERVU_ID.eq(ervuId)
EXCERPT_HISTORY.ERVU_ID.eq(ervuId) .and(EXCERPT_HISTORY.PRN_OID.eq(prnOid)))
.and(EXCERPT_HISTORY.PRN_OID.eq(prnOid)) ), ExcerptStatus.NONE.name()
)
),
"none"
)).fetchAnyInto(String.class); )).fetchAnyInto(String.class);
} }
@ -63,21 +56,25 @@ public class ExcerptHistoryDao {
dslContext.insertInto(EXCERPT_HISTORY) dslContext.insertInto(EXCERPT_HISTORY)
.set(EXCERPT_HISTORY.ERVU_ID, ervuId) .set(EXCERPT_HISTORY.ERVU_ID, ervuId)
.set(EXCERPT_HISTORY.PRN_OID, prnOid) .set(EXCERPT_HISTORY.PRN_OID, prnOid)
.execute(); .set(EXCERPT_HISTORY.STATUS, ExcerptStatus.PENDING.name())
}
public void insert(String ervuId, String prnOid, String url) {
dslContext.insertInto(EXCERPT_HISTORY)
.set(EXCERPT_HISTORY.ERVU_ID, ervuId)
.set(EXCERPT_HISTORY.PRN_OID, prnOid)
.set(EXCERPT_HISTORY.URL, url)
.set(EXCERPT_HISTORY.DATETIME, Timestamp.valueOf(LocalDateTime.now())) .set(EXCERPT_HISTORY.DATETIME, Timestamp.valueOf(LocalDateTime.now()))
.execute(); .execute();
} }
public void update(Long id, String url) { public void insert(String ervuId, String prnOid, String url, String status) {
dslContext.insertInto(EXCERPT_HISTORY)
.set(EXCERPT_HISTORY.ERVU_ID, ervuId)
.set(EXCERPT_HISTORY.PRN_OID, prnOid)
.set(EXCERPT_HISTORY.URL, url)
.set(EXCERPT_HISTORY.STATUS, status)
.set(EXCERPT_HISTORY.DATETIME, Timestamp.valueOf(LocalDateTime.now()))
.execute();
}
public void update(Long id, String url, String status) {
dslContext.update(EXCERPT_HISTORY) dslContext.update(EXCERPT_HISTORY)
.set(EXCERPT_HISTORY.URL, url) .set(EXCERPT_HISTORY.URL, url)
.set(EXCERPT_HISTORY.STATUS, status)
.set(EXCERPT_HISTORY.DATETIME, Timestamp.valueOf(LocalDateTime.now())) .set(EXCERPT_HISTORY.DATETIME, Timestamp.valueOf(LocalDateTime.now()))
.where(EXCERPT_HISTORY.ID.eq(id)) .where(EXCERPT_HISTORY.ID.eq(id))
.execute(); .execute();
@ -90,10 +87,14 @@ public class ExcerptHistoryDao {
.execute(); .execute();
} }
public void deleteOlderThan(long hours) { public void deleteOlderThan(long readyFileHours, long pendingFileHours) {
dslContext.deleteFrom(EXCERPT_HISTORY) dslContext.deleteFrom(EXCERPT_HISTORY)
.where(EXCERPT_HISTORY.DATETIME.le( .where(EXCERPT_HISTORY.STATUS.eq(ExcerptStatus.READY.name())
Timestamp.valueOf(LocalDateTime.now().minus(hours, ChronoUnit.HOURS)))) .and(EXCERPT_HISTORY.DATETIME.le(
Timestamp.valueOf(LocalDateTime.now().minus(readyFileHours, ChronoUnit.HOURS)))))
.or(EXCERPT_HISTORY.STATUS.in(ExcerptStatus.PENDING.name(), ExcerptStatus.NOT_FOUND.name())
.and(EXCERPT_HISTORY.DATETIME.le(
Timestamp.valueOf(LocalDateTime.now().minus(pendingFileHours, ChronoUnit.HOURS)))))
.execute(); .execute();
} }
} }

View file

@ -1,9 +1,9 @@
package ru.micord.ervu.kafka.listener; package ru.micord.ervu.kafka.listener;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicReference;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import ervu.enums.ExcerptStatus;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.kafka.annotation.KafkaListener; import org.springframework.kafka.annotation.KafkaListener;
@ -50,7 +50,7 @@ public class ExcerptListener {
if (!excerptResponse.getSuccess()) { if (!excerptResponse.getSuccess()) {
if (excerptResponse.getData() != null) { if (excerptResponse.getData() != null) {
data = excerptResponse.getData(); data = excerptResponse.getData();
excerptHistoryDao.delete(data.getOrgId(), data.getPrnOid()); saveUrl(data.getOrgId(), data.getPrnOid(), fileUrl);
} }
throw new ExcerptResponseException( throw new ExcerptResponseException(
"Error with getting excerpt url " + excerptResponse.getMessage()); "Error with getting excerpt url " + excerptResponse.getMessage());
@ -59,7 +59,7 @@ public class ExcerptListener {
|| excerptResponse.getData().getFileUrl().isEmpty()) { || excerptResponse.getData().getFileUrl().isEmpty()) {
if (excerptResponse.getData() != null) { if (excerptResponse.getData() != null) {
data = excerptResponse.getData(); data = excerptResponse.getData();
excerptHistoryDao.delete(data.getOrgId(), data.getPrnOid()); saveUrl(data.getOrgId(), data.getPrnOid(), fileUrl);
} }
auditService.processDownloadEvent(data, 0, fileName, 1, auditService.processDownloadEvent(data, 0, fileName, 1,
AuditConstants.FAILURE_STATUS_TYPE, fileUrl AuditConstants.FAILURE_STATUS_TYPE, fileUrl
@ -70,14 +70,7 @@ public class ExcerptListener {
data = excerptResponse.getData(); data = excerptResponse.getData();
fileUrl = data.getFileUrl(); fileUrl = data.getFileUrl();
fileName = UrlUtils.extractFileNameFromUrl(fileUrl); fileName = UrlUtils.extractFileNameFromUrl(fileUrl);
String ervuId = excerptResponse.getData().getOrgId(); saveUrl(data.getOrgId(), data.getPrnOid(), fileUrl);
String prnOid = excerptResponse.getData().getPrnOid();
AtomicReference<String> fileRef = new AtomicReference<>(fileUrl);
excerptHistoryDao.get(ervuId, prnOid)
.ifPresentOrElse(
record -> excerptHistoryDao.update(record.getId(), fileRef.get()),
() -> excerptHistoryDao.insert(ervuId, prnOid, fileRef.get())
);
} }
catch (Exception e) { catch (Exception e) {
auditService.processDownloadEvent(data, 0, fileName, 1, auditService.processDownloadEvent(data, 0, fileName, 1,
@ -90,4 +83,12 @@ public class ExcerptListener {
public String getGroupId() { public String getGroupId() {
return groupId + "-" + UUID.randomUUID(); return groupId + "-" + UUID.randomUUID();
} }
private void saveUrl(String ervuId, String prnOid, String fileUrl) {
String status = fileUrl == null ? ExcerptStatus.NOT_FOUND.name() : ExcerptStatus.READY.name();
excerptHistoryDao.get(ervuId, prnOid).ifPresentOrElse(
record -> excerptHistoryDao.update(record.getId(), fileUrl, status),
() -> excerptHistoryDao.insert(ervuId, prnOid, fileUrl, status)
);
}
} }

View file

@ -14,16 +14,18 @@ public class ExcerptCleanScheduler {
private final ExcerptHistoryDao excerptHistoryDao; private final ExcerptHistoryDao excerptHistoryDao;
@Value("${excerpt.lifetime.hours:24}") @Value("${excerpt.ready.lifetime.hours:24}")
private long fileLifetime; private long readyFileLifetime;
@Value("${excerpt.pending.lifetime.hours:8}")
private long pendingFileLifetime;
public ExcerptCleanScheduler(ExcerptHistoryDao excerptHistoryDao) { public ExcerptCleanScheduler(ExcerptHistoryDao excerptHistoryDao) {
this.excerptHistoryDao = excerptHistoryDao; this.excerptHistoryDao = excerptHistoryDao;
} }
@Scheduled(fixedDelayString = "${excerpt.cleanup.delay:30000}") @Scheduled(cron = "${excerpt.cleanup.cron:0 */30 * * * *}")
@SchedulerLock(name = "oldExcerptFilesCleaning") @SchedulerLock(name = "oldExcerptFilesCleaning")
public void cleanOld() { public void cleanOld() {
excerptHistoryDao.deleteOlderThan(fileLifetime); excerptHistoryDao.deleteOlderThan(readyFileLifetime, pendingFileLifetime);
} }
} }

View file

@ -3,7 +3,7 @@ import {Subscription} from "rxjs";
import {InMemoryStaticGrid} from "../grid/InMemoryStaticGrid"; import {InMemoryStaticGrid} from "../grid/InMemoryStaticGrid";
import {OnDestroy} from "@angular/core"; import {OnDestroy} from "@angular/core";
import {HttpClient} from "@angular/common/http"; import {HttpClient} from "@angular/common/http";
import {ExcerptStatus} from "../enum/ExcerptStatus"; import { ExcerptStatus } from "../../../generated/ervu/enums/ExcerptStatus";
@AnalyticalScope(AbstractButton) @AnalyticalScope(AbstractButton)
export class ErvuFileRequestDialogButton extends Behavior implements OnDestroy { export class ErvuFileRequestDialogButton extends Behavior implements OnDestroy {
@ -34,7 +34,7 @@ export class ErvuFileRequestDialogButton extends Behavior implements OnDestroy {
this.httpClient = this.injector.get(HttpClient); this.httpClient = this.injector.get(HttpClient);
this.gridLoadedSubscription = this.grid.gridLoaded.subscribe(() => { this.gridLoadedSubscription = this.grid.gridLoaded.subscribe(() => {
this.button.setEnabled(this.grid.getRowDataSize() > 0 this.button.setEnabled(this.grid.getRowDataSize() > 0
&& this.fileStatus !== ExcerptStatus.IN_PROGRESS); && this.fileStatus !== ExcerptStatus.PENDING);
this.button.setVisible(this.grid.getRowDataSize() > 0); this.button.setVisible(this.grid.getRowDataSize() > 0);
}); });
} }
@ -46,11 +46,11 @@ export class ErvuFileRequestDialogButton extends Behavior implements OnDestroy {
this.fileStatus = status; this.fileStatus = status;
if (this.grid.isInitialized() && this.grid.getRowDataSize() > 0) { if (this.grid.isInitialized() && this.grid.getRowDataSize() > 0) {
this.button.setEnabled(status !== ExcerptStatus.IN_PROGRESS); this.button.setEnabled(status !== ExcerptStatus.PENDING);
this.button.setVisible(true); this.button.setVisible(true);
} }
if (status === ExcerptStatus.IN_PROGRESS) { if (status === ExcerptStatus.PENDING) {
this.button.setTooltip(this.requestSentMsg); this.button.setTooltip(this.requestSentMsg);
this.text.setValue(this.requestSentMsg); this.text.setValue(this.requestSentMsg);

View file

@ -1,5 +0,0 @@
export enum ExcerptStatus {
NONE = 'none',
IN_PROGRESS = 'in-progress',
READY = 'ready'
}