This commit is contained in:
parent
8b643ced96
commit
031d09d7e3
11 changed files with 507 additions and 13 deletions
|
|
@ -0,0 +1,61 @@
|
|||
package ru.spcex.clearing.backendapi.controller.test;
|
||||
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import java.util.Map;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class EditImdgObjectAction {
|
||||
@ApiModelProperty(
|
||||
value = "IMDG map name",
|
||||
example = "Map_Registry"
|
||||
)
|
||||
@JsonProperty
|
||||
private String mapName;
|
||||
|
||||
@ApiModelProperty(
|
||||
value = "Full class name of IMDG object",
|
||||
example = "ru.clearing.classes.statics.data.registry.Registry"
|
||||
)
|
||||
@JsonProperty
|
||||
private String fullClassName;
|
||||
|
||||
@ApiModelProperty(value = "IMDG object id")
|
||||
@JsonProperty
|
||||
private Long objId;
|
||||
|
||||
@ApiModelProperty(value = "Fields and replacement values")
|
||||
@JsonProperty
|
||||
private Map<String, Object> fields;
|
||||
|
||||
public String getMapName() {
|
||||
return mapName;
|
||||
}
|
||||
|
||||
public void setMapName(String mapName) {
|
||||
this.mapName = mapName;
|
||||
}
|
||||
|
||||
public String getFullClassName() {
|
||||
return fullClassName;
|
||||
}
|
||||
|
||||
public void setFullClassName(String fullClassName) {
|
||||
this.fullClassName = fullClassName;
|
||||
}
|
||||
|
||||
public Long getObjId() {
|
||||
return objId;
|
||||
}
|
||||
|
||||
public void setObjId(Long objId) {
|
||||
this.objId = objId;
|
||||
}
|
||||
|
||||
public Map<String, Object> getFields() {
|
||||
return fields;
|
||||
}
|
||||
|
||||
public void setFields(Map<String, Object> fields) {
|
||||
this.fields = fields;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,131 @@
|
|||
package ru.spcex.clearing.backendapi.controller.test;
|
||||
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import io.swagger.annotations.ApiResponse;
|
||||
import io.swagger.annotations.ApiResponses;
|
||||
import java.lang.reflect.Field;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.util.Map;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import ru.spcex.clearing.backendapi.errors.BackEndError;
|
||||
import ru.spcex.platform.classes.base.SpcexObjectBase;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||
import ru.spcex.platform.utils.error.ValidationException;
|
||||
import ru.spcex.platform.utils.text.TextUtil;
|
||||
|
||||
@Profile("dev")
|
||||
@Controller
|
||||
@RequestMapping("/anonymous/imdg-api")
|
||||
public class EditObjectController {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private static final ObjectMapper json = new ObjectMapper();
|
||||
private final ImdgProvider imdgProvider;
|
||||
|
||||
@Autowired
|
||||
public EditObjectController(ImdgProvider imdgProvider) {
|
||||
this.imdgProvider = imdgProvider;
|
||||
}
|
||||
|
||||
@ApiOperation(value = "Edit any object.")
|
||||
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = String.class)})
|
||||
@RequestMapping(method = RequestMethod.POST, path = "/edit/object", produces = MediaType.TEXT_PLAIN_VALUE)
|
||||
@ResponseBody
|
||||
public String updateObjectById(@ApiParam(value = "Command params in JSON format.", required = true)
|
||||
@RequestBody EditImdgObjectAction action) throws ClassNotFoundException, ValidationException, IllegalAccessException {
|
||||
log.info("Edit any object method");
|
||||
validate(action);
|
||||
Class<?> rawParameterType = ClassUtils.forName(action.getFullClassName(), ClassUtils.getDefaultClassLoader());
|
||||
if (!SpcexObjectBase.class.isAssignableFrom(rawParameterType)) {
|
||||
throw new ValidationException(new EnumMessage(BackEndError.ValidationError, "fullClassName"));
|
||||
}
|
||||
Class<? extends SpcexObjectBase> parameterType = rawParameterType.asSubclass(SpcexObjectBase.class);
|
||||
Long id = action.getObjId();
|
||||
String mapName = action.getMapName();
|
||||
Imdg<SpcexObjectBase> imdg = (Imdg<SpcexObjectBase>) imdgProvider.getImdg(mapName, parameterType);
|
||||
SpcexObjectBase objectToUpdate = imdg.getSingleObjectByID(id);
|
||||
if (objectToUpdate == null) {
|
||||
throw new ValidationException(new EnumMessage(BackEndError.ResourceNotFound, "id"));
|
||||
}
|
||||
|
||||
setFields(objectToUpdate, action.getFields());
|
||||
imdg.update(objectToUpdate);
|
||||
return "success: object.id = " + id;
|
||||
}
|
||||
|
||||
private void validate(EditImdgObjectAction action) throws ValidationException {
|
||||
if (TextUtil.isEmpty(action.getMapName())) {
|
||||
throw new ValidationException(new EnumMessage(BackEndError.ValidationError, "mapName"));
|
||||
}
|
||||
if (TextUtil.isEmpty(action.getFullClassName())) {
|
||||
throw new ValidationException(new EnumMessage(BackEndError.ValidationError, "fullClassName"));
|
||||
}
|
||||
if (action.getObjId() == null) {
|
||||
throw new ValidationException(new EnumMessage(BackEndError.ValidationError, "objId"));
|
||||
}
|
||||
if (action.getFields() == null || action.getFields().isEmpty()) {
|
||||
throw new ValidationException(new EnumMessage(BackEndError.ValidationError, "fields"));
|
||||
}
|
||||
}
|
||||
|
||||
private void setFields(SpcexObjectBase objectToUpdate, Map<String, Object> fieldsToChange) throws ValidationException, IllegalAccessException {
|
||||
for (Map.Entry<String, Object> fieldToChange : fieldsToChange.entrySet()) {
|
||||
Field field = findField(objectToUpdate.getClass(), fieldToChange.getKey());
|
||||
field.setAccessible(true);
|
||||
field.set(objectToUpdate, toFieldValue(field, fieldToChange.getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
private Field findField(Class<?> objectClass, String fieldName) throws ValidationException {
|
||||
Class<?> currentClass = objectClass;
|
||||
while (currentClass != null) {
|
||||
try {
|
||||
return currentClass.getDeclaredField(fieldName);
|
||||
} catch (NoSuchFieldException ignored) {
|
||||
currentClass = currentClass.getSuperclass();
|
||||
}
|
||||
}
|
||||
throw new ValidationException(new EnumMessage(BackEndError.ValidationError, "fields." + fieldName));
|
||||
}
|
||||
|
||||
private Object toFieldValue(Field field, Object value) throws ValidationException {
|
||||
if (value == null) {
|
||||
if (field.getType().isPrimitive()) {
|
||||
throw new ValidationException(new EnumMessage(BackEndError.ValidationError, field.getName()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Class<?> fieldType = field.getType();
|
||||
if (fieldType.isAssignableFrom(value.getClass())) {
|
||||
return value;
|
||||
}
|
||||
if (fieldType.isEnum() && value instanceof String) {
|
||||
return Enum.valueOf((Class<Enum>) fieldType.asSubclass(Enum.class), (String) value);
|
||||
}
|
||||
if (fieldType == LocalDate.class && value instanceof String) {
|
||||
return LocalDate.parse((String) value);
|
||||
}
|
||||
if (fieldType == LocalDateTime.class && value instanceof String) {
|
||||
return LocalDateTime.parse((String) value);
|
||||
}
|
||||
if (fieldType == LocalTime.class && value instanceof String) {
|
||||
return LocalTime.parse((String) value);
|
||||
}
|
||||
return json.convertValue(value, json.getTypeFactory().constructType(field.getGenericType()));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
package ru.spcex.clearing.service;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.misc.Session;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.platform.enumeration.WorkflowStatus;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
|
||||
@Service
|
||||
public class IsActiveSessionRunningService {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final Imdg<Session> ssnImdg;
|
||||
|
||||
public IsActiveSessionRunningService(ImdgProvider imdgProvider) {
|
||||
this.ssnImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class);
|
||||
}
|
||||
|
||||
public boolean isThereAnActiveSession() {
|
||||
Collection<Session> activeSessions = ssnImdg.getCollectionObjectsByFieldValues(Map.of(
|
||||
"workflowStatus", WorkflowStatus.Active.getKey()
|
||||
));
|
||||
activeSessions.stream().findFirst().ifPresent(
|
||||
session -> log.debug("found session.id {}", session.getId())
|
||||
);
|
||||
return !activeSessions.isEmpty();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,14 @@
|
|||
package ru.spcex.clearing.service.executors;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -25,12 +34,24 @@ import ru.spcex.clearing.platform.messaging.domain.cud.gateway.AssetOperationApp
|
|||
import ru.spcex.clearing.platform.messaging.domain.cud.gateway.SingleAssetResponse;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.importexport.SwtExporterRequest;
|
||||
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
|
||||
import ru.spcex.clearing.service.IsActiveSessionRunningService;
|
||||
import ru.spcex.clearing.service.registry.AssetTBFProcessing;
|
||||
import ru.spcex.clearing.service.registry.RegistryManager;
|
||||
import ru.spcex.clearing.service.schedule.TasksDelayedBySessionServiceV2;
|
||||
import ru.spcex.clearing.service.schedule.TradingTimeService;
|
||||
import ru.spcex.clearing.service.validation.ValidationStored;
|
||||
import ru.spcex.clearing.session.stage.util.RegistryUtil;
|
||||
import ru.spcex.platform.enumeration.*;
|
||||
import ru.spcex.platform.enumeration.InOutDirection;
|
||||
import ru.spcex.platform.enumeration.InOutSDfType;
|
||||
import ru.spcex.platform.enumeration.OperationStatus;
|
||||
import ru.spcex.platform.enumeration.RegistryDesignation;
|
||||
import ru.spcex.platform.enumeration.RegistryStatus;
|
||||
import ru.spcex.platform.enumeration.RegistryTradingParams;
|
||||
import ru.spcex.platform.enumeration.RegistryUnit;
|
||||
import ru.spcex.platform.enumeration.SdfTable;
|
||||
import ru.spcex.platform.enumeration.Sender;
|
||||
import ru.spcex.platform.enumeration.StatementType;
|
||||
import ru.spcex.platform.enumeration.WorkflowStatus;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgId;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
|
|
@ -39,18 +60,8 @@ import ru.spcex.platform.imdg.api.predicate.specific.SecuritySelector;
|
|||
import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||
import ru.spcex.platform.utils.enumeration.IEnumId;
|
||||
import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
||||
import ru.spcex.platform.utils.validation.IValidator;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD;
|
||||
import ru.spcex.platform.utils.validation.IValidator;
|
||||
|
||||
@Service
|
||||
public class Sdf10Executor {
|
||||
|
|
@ -70,6 +81,8 @@ public class Sdf10Executor {
|
|||
private final KafkaSender kafkaSender;
|
||||
private final SecuritySelector<Security> scrtSlct;
|
||||
private final AssetTBFProcessing assets;
|
||||
private final TasksDelayedBySessionServiceV2 delayedService;
|
||||
private final IsActiveSessionRunningService sessionChecker;
|
||||
|
||||
private final static String OK = "OK";
|
||||
private final static String SYNTAX_ERROR = "Синтаксическая ошибка (файл сформирован неверно)";
|
||||
|
|
@ -90,7 +103,7 @@ public class Sdf10Executor {
|
|||
public Sdf10Executor(ImdgProvider imdgProvider,
|
||||
RegistryManager rgsMng, IMessageResolver messageResolver,
|
||||
@Qualifier("sdf10Validator") Function<SDf10, IValidator> sDf10Validator,
|
||||
TradingTimeService tradingTimeService, KafkaSender kafkaSender, AssetTBFProcessing assets) {
|
||||
TradingTimeService tradingTimeService, KafkaSender kafkaSender, AssetTBFProcessing assets, TasksDelayedBySessionServiceV2 delayedService, IsActiveSessionRunningService sessionChecker) {
|
||||
this.imdgProvider = imdgProvider;
|
||||
this.statementImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Statement, Statement.class);
|
||||
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
|
||||
|
|
@ -102,9 +115,11 @@ public class Sdf10Executor {
|
|||
this.kafkaSender = kafkaSender;
|
||||
this.sdf10Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf10, SDf10.class);
|
||||
this.sdf11Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf11, SDf11.class);
|
||||
this.sessionChecker = sessionChecker;
|
||||
this.plannerAllTodayImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_PlannerAllToday, PlannerAllToday.class);
|
||||
this.scrtSlct = new SecuritySelector<>(imdgProvider, Security.class);
|
||||
this.assets = assets;
|
||||
this.delayedService = delayedService;
|
||||
}
|
||||
|
||||
public void execute(BaseRequest<StatementRequest> systemRequest) {
|
||||
|
|
@ -125,9 +140,21 @@ public class Sdf10Executor {
|
|||
sendToExporter(sdf11GroupId);
|
||||
return;
|
||||
}
|
||||
if (sessionChecker.isThereAnActiveSession()) {
|
||||
log.info("delaying SDF10 execution for groupId={} - session is active", groupId);
|
||||
pauseAll(sdfs);
|
||||
delayedService.subscribe(groupId);
|
||||
return;
|
||||
}
|
||||
Collection<AssetOperationRequest> requests = new ArrayList<>();
|
||||
boolean sdf11WasCreated = false;
|
||||
for (SDf10 sDf10 : sdfs) {
|
||||
if (systemRequest.getRequestPayload().isDelayed() && !WorkflowStatus.Pause.equalsByKey(sDf10.getWorkflowStatus())) {
|
||||
log.warn("got delayed SDF10 request groupId: {}. sdf10.id {} is not in {} status.", groupId, sDf10.getId(), WorkflowStatus.Pause.getKey());
|
||||
continue;
|
||||
}
|
||||
sDf10.setWorkflowStatus(WorkflowStatus.Blocked.getKey());
|
||||
sdf10Imdg.update(sDf10);
|
||||
IValidator validator = sDf10Validator.apply(sDf10);
|
||||
Optional<EnumMessage> err = validator.tillFirstError();
|
||||
Security security = validator.getStored(ValidationStored.SecurityBySecurityCode);
|
||||
|
|
@ -188,6 +215,18 @@ public class Sdf10Executor {
|
|||
}
|
||||
}
|
||||
|
||||
private void pauseAll(Collection<SDf10> sdfs) {
|
||||
Map<Long, SDf10> sdfById = sdfs.stream()
|
||||
.collect(Collectors.toMap(
|
||||
SDf10::getId,
|
||||
sdf -> {
|
||||
sdf.setWorkflowStatus(WorkflowStatus.Pause.getKey());
|
||||
return sdf;
|
||||
}
|
||||
));
|
||||
sdf10Imdg.putAll(sdfById);
|
||||
}
|
||||
|
||||
private void createDs_iResponseFromGateway(Long accountId, String securitySymbol,
|
||||
BigDecimal summ, String outDocument) {
|
||||
Optional<Registry> as_t = rgsMng.searchByAccSec(accountId, securitySymbol, RegistryTradingParams.AS_T);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,143 @@
|
|||
package ru.spcex.clearing.service.schedule;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.misc.Session;
|
||||
import ru.clearing.classes.statics.data.sdf.SDf10;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.balance.StatementRequest;
|
||||
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
|
||||
import ru.spcex.clearing.service.IsActiveSessionRunningService;
|
||||
import ru.spcex.platform.enumeration.SdfTable;
|
||||
import ru.spcex.platform.enumeration.WorkflowStatus;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgEntryListener;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
import ru.spcex.platform.imdg.api.listener.ImdgEntryEvent;
|
||||
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
|
||||
import ru.spcex.platform.utils.log.ExceptionUtils;
|
||||
import ru.spcex.platform.utils.time.TimeUtil;
|
||||
|
||||
@Service
|
||||
public class TasksDelayedBySessionServiceV2 implements ImdgEntryListener<Session>,
|
||||
DisposableBean, InitializingBean {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final Set<Long> groupIds;
|
||||
private final ExecutorService singleThreadExecutor;
|
||||
private final KafkaSender kafka;
|
||||
private final Imdg<SDf10> sdf10Imdg;
|
||||
private final ImdgProvider imdgProvider;
|
||||
private final IsActiveSessionRunningService sessionChecker;
|
||||
|
||||
@Autowired
|
||||
public TasksDelayedBySessionServiceV2(@Qualifier("kafkaSenderWithoutRequestInfo")
|
||||
KafkaSender kafka, ImdgProvider imdgProvider, IsActiveSessionRunningService sessionChecker) {
|
||||
this.kafka = kafka;
|
||||
this.imdgProvider = imdgProvider;
|
||||
this.sdf10Imdg = imdgProvider.getImdg(IMDGDistributedNames.Map_SDf10, SDf10.class);
|
||||
this.sessionChecker = sessionChecker;
|
||||
this.groupIds = new LinkedHashSet<>();
|
||||
this.singleThreadExecutor = Executors.newSingleThreadExecutor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
submitWrap(this::checkDelayedStatusesOnStartup);
|
||||
this.imdgProvider.waitAvailable();
|
||||
Imdg<Session> ssnImdg = this.imdgProvider.getImdg(IMDGDistributedNames.Map_Session, Session.class);
|
||||
ssnImdg.addListener(this);
|
||||
}
|
||||
|
||||
private void checkDelayedStatusesOnStartup() {
|
||||
imdgProvider.waitAvailable();
|
||||
ImdgPredicateBuilder pb = sdf10Imdg.predicateBuilder();
|
||||
Collection<SDf10> sdfs = sdf10Imdg.getCollectionObjectsByPredicate(
|
||||
pb.and(
|
||||
pb.greatEqual("generationTime", TimeUtil.localDateToInstant(LocalDate.now())),
|
||||
pb.equals("workflowStatus", WorkflowStatus.Pause.getKey())
|
||||
)
|
||||
);
|
||||
List<Long> groupIds = sdfs.stream()
|
||||
.map(SDf10::getGenerationId)
|
||||
.distinct()
|
||||
.toList();
|
||||
log.info("{} sdf10 on startup; {} groups", sdfs.size(), groupIds.size());
|
||||
if (sessionChecker.isThereAnActiveSession()) {
|
||||
log.info("there is an active session: sdf10 stay delayed");
|
||||
synchronized (this.groupIds) {
|
||||
groupIds.forEach(this::subscribe);
|
||||
}
|
||||
} else {
|
||||
groupIds.forEach(this::notifyEventReceiver);
|
||||
}
|
||||
}
|
||||
|
||||
public void subscribe(Long groupId) {
|
||||
synchronized (groupIds) {
|
||||
groupIds.add(groupId);
|
||||
}
|
||||
log.info("sdf10 groupId={} delayed", groupId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void innerEntryUpdated(ImdgEntryEvent<Session> event) {
|
||||
if (notSessionEndEvent(event.getOldValue(), event.getValue())) {
|
||||
log.trace("not a session end event.");
|
||||
return;
|
||||
}
|
||||
synchronized (groupIds) {
|
||||
List<Long> filtered = new ArrayList<>(groupIds);
|
||||
groupIds.clear();
|
||||
submitWrap(() -> filtered.forEach(this::notifyEventReceiver));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean notSessionEndEvent(Session sessionOldValue, Session sessionNewValue) {
|
||||
if (sessionOldValue == null || sessionNewValue == null) {
|
||||
log.warn("old value null {}, new value null {}",
|
||||
sessionOldValue == null, sessionNewValue == null);
|
||||
return true;
|
||||
}
|
||||
String oldWS = sessionOldValue.getWorkflowStatus();
|
||||
String newWS = sessionNewValue.getWorkflowStatus();
|
||||
log.trace("workflow statuses: {} -> {}", oldWS, newWS);
|
||||
return !(WorkflowStatus.Active.equalsByKey(oldWS) && !WorkflowStatus.Active.equalsByKey(newWS));
|
||||
}
|
||||
|
||||
private void notifyEventReceiver(Long groupId) {
|
||||
StatementRequest request = new StatementRequest();
|
||||
request.setGroupId(groupId);
|
||||
request.setTable(SdfTable.SDF_10);
|
||||
request.setDelayed(true);
|
||||
kafka.sendRequestToQueue(Consts.STATEMENT_PROCESS, request);
|
||||
}
|
||||
|
||||
private void submitWrap(Runnable task) {
|
||||
singleThreadExecutor.submit(() -> {
|
||||
try {
|
||||
task.run();
|
||||
} catch (Exception e) {
|
||||
log.error(ExceptionUtils.getStackTrace(e));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
this.singleThreadExecutor.close();
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import ru.spcex.platform.classes.base.SpcexObjectBase;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgEntryListener;
|
||||
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
|
||||
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.adapter.predicate.ImdgPredicateBuilderHazelcast;
|
||||
|
|
@ -350,4 +351,9 @@ public class ImdgHazelcast<T extends SpcexObjectBase> implements Imdg<T> {
|
|||
public ImdgPredicateBuilder predicateBuilder() {
|
||||
return ImdgPredicateBuilderHazelcast.instance();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener(ImdgEntryListener<T> listener) {
|
||||
map.addEntryListener(new ImdgHazelcastListener<>(listener), true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
package ru.spcex.platform.imdg.iml.hazelcast.adapter;
|
||||
|
||||
import com.hazelcast.core.EntryEvent;
|
||||
import com.hazelcast.map.listener.EntryAddedListener;
|
||||
import com.hazelcast.map.listener.EntryUpdatedListener;
|
||||
import ru.spcex.platform.imdg.api.ImdgEntryListener;
|
||||
import ru.spcex.platform.imdg.api.listener.ImdgEntryEvent;
|
||||
|
||||
public class ImdgHazelcastListener<T> implements
|
||||
EntryUpdatedListener<Long, T>,
|
||||
EntryAddedListener<Long, T>
|
||||
{
|
||||
|
||||
private final ImdgEntryListener<T> delegate;
|
||||
|
||||
public ImdgHazelcastListener(ImdgEntryListener<T> delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void entryUpdated(EntryEvent<Long, T> event) {
|
||||
this.delegate.innerEntryUpdated(new ImdgEntryEvent<>(event.getValue(), event.getOldValue(), event.getKey()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void entryAdded(EntryEvent<Long, T> event) {
|
||||
this.delegate.innerEntryAdded(new ImdgEntryEvent<>(event.getValue(), event.getOldValue(), event.getKey()));
|
||||
}
|
||||
}
|
||||
|
|
@ -133,4 +133,8 @@ public interface Imdg<T extends SpcexObjectBase> {
|
|||
default ImdgPredicateBuilder predicateBuilder() {
|
||||
throw new UnsupportedOperationException("not implemented predicateBuilder API");
|
||||
}
|
||||
|
||||
default void addListener(ImdgEntryListener<T> listener) {
|
||||
throw new UnsupportedOperationException("not implemented addListener");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package ru.spcex.platform.imdg.api;
|
||||
|
||||
import ru.spcex.platform.imdg.api.listener.ImdgEntryEvent;
|
||||
|
||||
public interface ImdgEntryListener<T> {
|
||||
default void innerEntryAdded(ImdgEntryEvent<T> event) {
|
||||
|
||||
}
|
||||
|
||||
default void innerEntryUpdated(ImdgEntryEvent<T> event) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package ru.spcex.platform.imdg.api.listener;
|
||||
|
||||
public class ImdgEntryEvent<T> {
|
||||
private final T value;
|
||||
private final T oldValue;
|
||||
private final Long key;
|
||||
|
||||
public ImdgEntryEvent(T value, T oldValue, Long key) {
|
||||
this.value = value;
|
||||
this.oldValue = oldValue;
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public T getOldValue() {
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
public Long getKey() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,8 @@ public class StatementRequest {
|
|||
private Long childGenerationId;
|
||||
@JsonProperty
|
||||
private boolean continueSdf = false;
|
||||
@JsonProperty
|
||||
private boolean delayed = false;
|
||||
|
||||
public Long getGroupId() {
|
||||
return groupId;
|
||||
|
|
@ -68,4 +70,12 @@ public class StatementRequest {
|
|||
public void setFromAccount(boolean fromAccount) {
|
||||
this.fromAccount = fromAccount;
|
||||
}
|
||||
|
||||
public boolean isDelayed() {
|
||||
return delayed;
|
||||
}
|
||||
|
||||
public void setDelayed(boolean delayed) {
|
||||
this.delayed = delayed;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue