Use pipline engine as library
This commit is contained in:
parent
4cc3f6eb3f
commit
45e6447d2e
40 changed files with 114 additions and 874 deletions
5
pom.xml
5
pom.xml
|
|
@ -38,6 +38,11 @@
|
||||||
<artifactId>mybatis-spring-boot-starter</artifactId>
|
<artifactId>mybatis-spring-boot-starter</artifactId>
|
||||||
<version>3.0.4</version>
|
<version>3.0.4</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>ru.nbch</groupId>
|
||||||
|
<artifactId>pipeline-engine</artifactId>
|
||||||
|
<version>1.0</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.postgresql</groupId>
|
<groupId>org.postgresql</groupId>
|
||||||
<artifactId>postgresql</artifactId>
|
<artifactId>postgresql</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,20 @@
|
||||||
package ru.nbch.credit_tracker.config.task;
|
package ru.nbch.credit_tracker.config.task;
|
||||||
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
||||||
import ru.nbch.credit_tracker.mapper.signal.PhonesMapMapper;
|
import ru.nbch.credit_tracker.mapper.signal.PhonesMapMapper;
|
||||||
import ru.nbch.credit_tracker.mapper.signal.UserPackageMapper;
|
import ru.nbch.credit_tracker.mapper.signal.UserPackageMapper;
|
||||||
import ru.nbch.credit_tracker.model.impl.EmptyTerminatePayload;
|
import ru.nbch.credit_tracker.model.impl.*;
|
||||||
import ru.nbch.credit_tracker.model.impl.PartFilePayload;
|
|
||||||
import ru.nbch.credit_tracker.model.impl.SignalXmlFilePayload;
|
|
||||||
import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
|
||||||
import ru.nbch.credit_tracker.model.impl.VoidPayload;
|
|
||||||
import ru.nbch.credit_tracker.service.signal.PackageRecordsService;
|
import ru.nbch.credit_tracker.service.signal.PackageRecordsService;
|
||||||
import ru.nbch.credit_tracker.service.task.SetupParam;
|
import ru.nbch.credit_tracker.service.task.SetupParam;
|
||||||
import ru.nbch.credit_tracker.service.task.impl.KickPipeLineDefaultImpl;
|
import ru.nbch.credit_tracker.service.task.impl.*;
|
||||||
import ru.nbch.credit_tracker.service.task.impl.KickPipeLineRepeatedRestoreImpl;
|
import ru.nbch.pipeline.engine.core.PipelineBackoff;
|
||||||
import ru.nbch.credit_tracker.service.task.impl.KickRecalcPipeLine;
|
import ru.nbch.pipeline.engine.core.setup.IPipeLineStarter;
|
||||||
import ru.nbch.credit_tracker.service.task.impl.NoOpTerminator;
|
import ru.nbch.pipeline.engine.core.setup.IPipeLineTerminator;
|
||||||
import ru.nbch.credit_tracker.service.task.impl.XmlMergeCoordinator;
|
|
||||||
import ru.nbch.credit_tracker.service.task.setup.IPipeLineStarter;
|
import java.util.function.Function;
|
||||||
import ru.nbch.credit_tracker.service.task.setup.IPipeLineTerminator;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
@Configuration
|
@Configuration
|
||||||
public class PipelineStarterConfig {
|
public class PipelineStarterConfig {
|
||||||
|
|
@ -52,4 +46,13 @@ public class PipelineStarterConfig {
|
||||||
public Supplier<IPipeLineTerminator<VoidPayload, EmptyTerminatePayload>> noOpTerminatorFactory() {
|
public Supplier<IPipeLineTerminator<VoidPayload, EmptyTerminatePayload>> noOpTerminatorFactory() {
|
||||||
return NoOpTerminator::new;
|
return NoOpTerminator::new;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public PipelineBackoff pipelineBackoff(CreditTrackerSettings creditTrackerSettings) {
|
||||||
|
return new PipelineBackoff(
|
||||||
|
creditTrackerSettings.getPipeline().errorAttemptCount(),
|
||||||
|
creditTrackerSettings.getPipeline().errorAttemptDelay(),
|
||||||
|
creditTrackerSettings.getPipeline().retryableExceptions()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
package ru.nbch.credit_tracker.config.task;
|
package ru.nbch.credit_tracker.config.task;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
|
import ru.nbch.pipeline.engine.core.StagePayload;
|
||||||
|
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
|
||||||
import ru.nbch.credit_tracker.model.StagePayload;
|
|
||||||
|
|
||||||
public class StageQueueFactory<T extends StagePayload> implements FactoryBean<BlockingQueue<T>> {
|
public class StageQueueFactory<T extends StagePayload> implements FactoryBean<BlockingQueue<T>> {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ import ru.nbch.credit_tracker.model.ValidationResult;
|
||||||
import ru.nbch.credit_tracker.service.UserPackageService;
|
import ru.nbch.credit_tracker.service.UserPackageService;
|
||||||
import ru.nbch.credit_tracker.service.scoring.AuthorizationService;
|
import ru.nbch.credit_tracker.service.scoring.AuthorizationService;
|
||||||
import ru.nbch.credit_tracker.service.signal.SignalRestService;
|
import ru.nbch.credit_tracker.service.signal.SignalRestService;
|
||||||
import ru.nbch.credit_tracker.service.task.Pipeline;
|
|
||||||
import ru.nbch.credit_tracker.service.task.PipelinePackageFabric;
|
import ru.nbch.credit_tracker.service.task.PipelinePackageFabric;
|
||||||
import ru.nbch.credit_tracker.service.task.PipelinePackageOrchestrator;
|
import ru.nbch.credit_tracker.service.task.PipelinePackageOrchestrator;
|
||||||
import ru.nbch.credit_tracker.service.task.SetupParam;
|
import ru.nbch.credit_tracker.service.task.SetupParam;
|
||||||
|
|
@ -40,6 +39,7 @@ import ru.nbch.credit_tracker.utils.CtFileUtils;
|
||||||
import ru.nbch.credit_tracker.utils.EnumUtil;
|
import ru.nbch.credit_tracker.utils.EnumUtil;
|
||||||
import ru.nbch.credit_tracker.utils.LogUtil;
|
import ru.nbch.credit_tracker.utils.LogUtil;
|
||||||
import ru.nbch.credit_tracker.utils.ZipUtils;
|
import ru.nbch.credit_tracker.utils.ZipUtils;
|
||||||
|
import ru.nbch.pipeline.engine.core.Pipeline;
|
||||||
|
|
||||||
import javax.xml.stream.XMLStreamException;
|
import javax.xml.stream.XMLStreamException;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
package ru.nbch.credit_tracker.model;
|
|
||||||
|
|
||||||
import java.util.EnumMap;
|
|
||||||
|
|
||||||
public class PipelineContext<T extends Enum<T>> {
|
|
||||||
private final EnumMap<T, Object> storage;
|
|
||||||
|
|
||||||
public PipelineContext(Class<T> keyClass) {
|
|
||||||
this.storage = new EnumMap<>(keyClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void store(T key, Object value) {
|
|
||||||
storage.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <S> S get(T key) {
|
|
||||||
Object o = storage.get(key);
|
|
||||||
return (S) o;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
package ru.nbch.credit_tracker.model;
|
|
||||||
|
|
||||||
public interface StagePayload {
|
|
||||||
boolean isPoison();
|
|
||||||
default void setContext(PipelineContext<?> context) {}
|
|
||||||
default PipelineContext<?> getContext() {return null;}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
package ru.nbch.credit_tracker.model;
|
|
||||||
|
|
||||||
public interface TerminatePayload {
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
package ru.nbch.credit_tracker.model.impl;
|
package ru.nbch.credit_tracker.model.impl;
|
||||||
|
|
||||||
import ru.nbch.credit_tracker.model.TerminatePayload;
|
import ru.nbch.pipeline.engine.core.TerminatePayload;
|
||||||
|
|
||||||
public class EmptyTerminatePayload implements TerminatePayload {
|
public class EmptyTerminatePayload implements TerminatePayload {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
package ru.nbch.credit_tracker.model.impl;
|
package ru.nbch.credit_tracker.model.impl;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import ru.nbch.credit_tracker.enums.PoisonType;
|
import ru.nbch.credit_tracker.enums.PoisonType;
|
||||||
import ru.nbch.credit_tracker.model.StagePayload;
|
import ru.nbch.pipeline.engine.core.StagePayload;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class PartFilePayload implements StagePayload {
|
public class PartFilePayload implements StagePayload {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
package ru.nbch.credit_tracker.model.impl;
|
package ru.nbch.credit_tracker.model.impl;
|
||||||
|
|
||||||
|
import ru.nbch.pipeline.engine.core.TerminatePayload;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import ru.nbch.credit_tracker.model.TerminatePayload;
|
|
||||||
|
|
||||||
public record SignalXmlFilePayload(Path signalXmlFilePath) implements TerminatePayload {
|
public record SignalXmlFilePayload(Path signalXmlFilePath) implements TerminatePayload {
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
package ru.nbch.credit_tracker.model.impl;
|
package ru.nbch.credit_tracker.model.impl;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import ru.nbch.credit_tracker.enums.PoisonType;
|
import ru.nbch.credit_tracker.enums.PoisonType;
|
||||||
import ru.nbch.credit_tracker.model.PipelineContext;
|
|
||||||
import ru.nbch.credit_tracker.model.StagePayload;
|
|
||||||
import ru.nbch.credit_tracker.model.SubjectProfile;
|
import ru.nbch.credit_tracker.model.SubjectProfile;
|
||||||
|
import ru.nbch.pipeline.engine.core.PipelineContext;
|
||||||
|
import ru.nbch.pipeline.engine.core.StagePayload;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
public class SubjectPayload implements StagePayload {
|
public class SubjectPayload implements StagePayload {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package ru.nbch.credit_tracker.model.impl;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import ru.nbch.credit_tracker.enums.PoisonType;
|
import ru.nbch.credit_tracker.enums.PoisonType;
|
||||||
import ru.nbch.credit_tracker.model.StagePayload;
|
import ru.nbch.pipeline.engine.core.StagePayload;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public class VoidPayload implements StagePayload {
|
public class VoidPayload implements StagePayload {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
package ru.nbch.credit_tracker.service.mode.common;
|
package ru.nbch.credit_tracker.service.mode.common;
|
||||||
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.List;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
@ -11,7 +9,6 @@ import ru.nbch.credit_tracker.enums.Status;
|
||||||
import ru.nbch.credit_tracker.mapper.signal.PackagesRecordsMapper;
|
import ru.nbch.credit_tracker.mapper.signal.PackagesRecordsMapper;
|
||||||
import ru.nbch.credit_tracker.mapper.signal.UserPackageMapper;
|
import ru.nbch.credit_tracker.mapper.signal.UserPackageMapper;
|
||||||
import ru.nbch.credit_tracker.service.MonitoringErrorProcesingService;
|
import ru.nbch.credit_tracker.service.MonitoringErrorProcesingService;
|
||||||
import ru.nbch.credit_tracker.service.task.Pipeline;
|
|
||||||
import ru.nbch.credit_tracker.service.task.PipelinePackageFabric;
|
import ru.nbch.credit_tracker.service.task.PipelinePackageFabric;
|
||||||
import ru.nbch.credit_tracker.service.task.PipelinePackageOrchestrator;
|
import ru.nbch.credit_tracker.service.task.PipelinePackageOrchestrator;
|
||||||
import ru.nbch.credit_tracker.service.task.SetupParam;
|
import ru.nbch.credit_tracker.service.task.SetupParam;
|
||||||
|
|
@ -19,6 +16,10 @@ import ru.nbch.credit_tracker.service.task.impl.PipelineMode;
|
||||||
import ru.nbch.credit_tracker.service.task.impl.Saver;
|
import ru.nbch.credit_tracker.service.task.impl.Saver;
|
||||||
import ru.nbch.credit_tracker.utils.CTUtil;
|
import ru.nbch.credit_tracker.utils.CTUtil;
|
||||||
import ru.nbch.credit_tracker.utils.error.ExceptionUtils;
|
import ru.nbch.credit_tracker.utils.error.ExceptionUtils;
|
||||||
|
import ru.nbch.pipeline.engine.core.Pipeline;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Сервис для завершения обработки пакетов находящихся в статусе PROCESSING
|
* Сервис для завершения обработки пакетов находящихся в статусе PROCESSING
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
package ru.nbch.credit_tracker.service.mode.common;
|
package ru.nbch.credit_tracker.service.mode.common;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
|
@ -10,12 +8,15 @@ import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
||||||
import ru.nbch.credit_tracker.entities.app.UserPackage;
|
import ru.nbch.credit_tracker.entities.app.UserPackage;
|
||||||
import ru.nbch.credit_tracker.mapper.signal.UserPackageMapper;
|
import ru.nbch.credit_tracker.mapper.signal.UserPackageMapper;
|
||||||
import ru.nbch.credit_tracker.service.signal.PhonesMapService;
|
import ru.nbch.credit_tracker.service.signal.PhonesMapService;
|
||||||
import ru.nbch.credit_tracker.service.task.Pipeline;
|
|
||||||
import ru.nbch.credit_tracker.service.task.PipelinePackageFabric;
|
import ru.nbch.credit_tracker.service.task.PipelinePackageFabric;
|
||||||
import ru.nbch.credit_tracker.service.task.PipelinePackageOrchestrator;
|
import ru.nbch.credit_tracker.service.task.PipelinePackageOrchestrator;
|
||||||
import ru.nbch.credit_tracker.service.task.PipelineRecalcPDOrchestrator;
|
import ru.nbch.credit_tracker.service.task.PipelineRecalcPDOrchestrator;
|
||||||
import ru.nbch.credit_tracker.service.task.SetupParam;
|
import ru.nbch.credit_tracker.service.task.SetupParam;
|
||||||
import ru.nbch.credit_tracker.service.task.impl.PipelineMode;
|
import ru.nbch.credit_tracker.service.task.impl.PipelineMode;
|
||||||
|
import ru.nbch.pipeline.engine.core.Pipeline;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
package ru.nbch.credit_tracker.service.mode.migration;
|
package ru.nbch.credit_tracker.service.mode.migration;
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.nbch.credit_tracker.service.task.Pipeline;
|
|
||||||
import ru.nbch.credit_tracker.service.task.PipelineMigrationPackageFabric;
|
import ru.nbch.credit_tracker.service.task.PipelineMigrationPackageFabric;
|
||||||
import ru.nbch.credit_tracker.service.task.PipelineRecalcPDOrchestrator;
|
import ru.nbch.credit_tracker.service.task.PipelineRecalcPDOrchestrator;
|
||||||
import ru.nbch.credit_tracker.service.task.SetupParam;
|
import ru.nbch.credit_tracker.service.task.SetupParam;
|
||||||
import ru.nbch.credit_tracker.service.task.impl.PipelineMode;
|
import ru.nbch.credit_tracker.service.task.impl.PipelineMode;
|
||||||
|
import ru.nbch.pipeline.engine.core.Pipeline;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
package ru.nbch.credit_tracker.service.task;
|
|
||||||
|
|
||||||
import ru.nbch.credit_tracker.model.PipelineContext;
|
|
||||||
import ru.nbch.credit_tracker.model.StagePayload;
|
|
||||||
import ru.nbch.credit_tracker.refactoring.Suspicios;
|
|
||||||
|
|
||||||
public interface Handler<X extends StagePayload, Z extends StagePayload> {
|
|
||||||
Z handle(X taskPayload);
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
default <T extends Enum<T>> PipelineContext<T> obtainContext(Class<T> keyClass, X input) {
|
|
||||||
PipelineContext<?> ctx = input.getContext();
|
|
||||||
return (PipelineContext<T>) ctx;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suspicios("Удалить?")
|
|
||||||
default void handleOnPoison(X poison){
|
|
||||||
//do nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
default int preferredConcurrency() {return 10;}
|
|
||||||
|
|
||||||
Z cookPoison();
|
|
||||||
}
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
package ru.nbch.credit_tracker.service.task;
|
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import ru.nbch.credit_tracker.model.PipelineContext;
|
|
||||||
import ru.nbch.credit_tracker.service.task.setup.IPipeLineTerminator;
|
|
||||||
import ru.nbch.credit_tracker.utils.LogUtil;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
|
|
||||||
public class Pipeline {
|
|
||||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
|
||||||
private Runnable starter;
|
|
||||||
private IPipeLineTerminator<?,?> terminator;
|
|
||||||
private List<Stage<?, ?>> stages;
|
|
||||||
private Future<?> starterFuture;
|
|
||||||
private Future<?> terminatorFuture;
|
|
||||||
private final AtomicBoolean closed = new AtomicBoolean(false);
|
|
||||||
private PipelineContext<?> context;
|
|
||||||
private volatile long startTime;
|
|
||||||
|
|
||||||
public void start(ExecutorService executorService) {
|
|
||||||
this.startTime = System.currentTimeMillis();
|
|
||||||
this.starterFuture = executorService.submit(LogUtil.wrap(LogUtil.extractMdcMap(), starter));
|
|
||||||
this.terminatorFuture = executorService.submit(LogUtil.wrap(LogUtil.extractMdcMap(), terminator));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
if (closed.compareAndSet(false, true)) {
|
|
||||||
log.info("closing the pipeline...");
|
|
||||||
stages.forEach(Stage::close);
|
|
||||||
this.starterFuture.cancel(true);
|
|
||||||
this.terminatorFuture.cancel(true);
|
|
||||||
} else {
|
|
||||||
log.info("pipeline already closed.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Stage<?, ?> getLast() {
|
|
||||||
return stages.getLast();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Runnable getStarter() {
|
|
||||||
return starter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStarter(Runnable starter) {
|
|
||||||
this.starter = starter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IPipeLineTerminator<?, ?> getTerminator() {
|
|
||||||
return terminator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTerminator(IPipeLineTerminator<?, ?> terminator) {
|
|
||||||
this.terminator = terminator;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Stage<?, ?>> getStages() {
|
|
||||||
return stages;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setStages(List<Stage<?, ?>> stages) {
|
|
||||||
this.stages = stages;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getStartTime() {
|
|
||||||
return startTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setContext(PipelineContext<?> context) {
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T extends Enum<T>> PipelineContext<T> obtainContext(Class<T> keyClass) {
|
|
||||||
return (PipelineContext<T>) context;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
package ru.nbch.credit_tracker.service.task;
|
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.List;
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
@Service
|
|
||||||
public class PipelineBackoff {
|
|
||||||
private final Integer retryCount;
|
|
||||||
private final Duration delay;
|
|
||||||
private final List<Class<? extends Throwable>> retryableExceptions;
|
|
||||||
|
|
||||||
public PipelineBackoff(CreditTrackerSettings creditTrackerSettings) {
|
|
||||||
this.retryCount = creditTrackerSettings.getPipeline().errorAttemptCount();
|
|
||||||
this.delay = creditTrackerSettings.getPipeline().errorAttemptDelay();
|
|
||||||
this.retryableExceptions = creditTrackerSettings.getPipeline().retryableExceptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void backoff() {
|
|
||||||
try {
|
|
||||||
Thread.sleep(delay.toMillis());
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isRetryable(final Throwable throwable) {
|
|
||||||
return retryableExceptions.stream().anyMatch(aClass -> aClass.isAssignableFrom(throwable.getClass()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -12,9 +12,11 @@ import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
||||||
import ru.nbch.credit_tracker.model.impl.VoidPayload;
|
import ru.nbch.credit_tracker.model.impl.VoidPayload;
|
||||||
import ru.nbch.credit_tracker.service.task.impl.FidIdUpdater;
|
import ru.nbch.credit_tracker.service.task.impl.FidIdUpdater;
|
||||||
import ru.nbch.credit_tracker.service.task.impl.FidNameUpdaterMigration;
|
import ru.nbch.credit_tracker.service.task.impl.FidNameUpdaterMigration;
|
||||||
import ru.nbch.credit_tracker.service.task.setup.IPipeLineStarter;
|
import ru.nbch.pipeline.engine.core.Pipeline;
|
||||||
import ru.nbch.credit_tracker.service.task.setup.IPipeLineTerminator;
|
import ru.nbch.pipeline.engine.core.PipelineBackoff;
|
||||||
import ru.nbch.credit_tracker.service.task.setup.PipeLineBuilder;
|
import ru.nbch.pipeline.engine.core.setup.IPipeLineStarter;
|
||||||
|
import ru.nbch.pipeline.engine.core.setup.IPipeLineTerminator;
|
||||||
|
import ru.nbch.pipeline.engine.core.setup.PipeLineBuilderV2;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
@ -53,7 +55,7 @@ public class PipelineMigrationPackageFabric implements InitializingBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pipeline buildRecalculationPDMigration(SetupParam setupParam) throws Exception {
|
public Pipeline buildRecalculationPDMigration(SetupParam setupParam) throws Exception {
|
||||||
return PipeLineBuilder.first(nameUpdaterQueueFactory.getObject(), idUpdaterQueueFactory.getObject())
|
return PipeLineBuilderV2.first(nameUpdaterQueueFactory.getObject(), idUpdaterQueueFactory.getObject())
|
||||||
.handler(fidNameUpdaterMigration)
|
.handler(fidNameUpdaterMigration)
|
||||||
.andThen()
|
.andThen()
|
||||||
.stage(noOpQueueFactory.getObject())
|
.stage(noOpQueueFactory.getObject())
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,11 @@ import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
||||||
import ru.nbch.credit_tracker.config.task.StageQueueFactory;
|
import ru.nbch.credit_tracker.config.task.StageQueueFactory;
|
||||||
import ru.nbch.credit_tracker.model.impl.*;
|
import ru.nbch.credit_tracker.model.impl.*;
|
||||||
import ru.nbch.credit_tracker.service.task.impl.*;
|
import ru.nbch.credit_tracker.service.task.impl.*;
|
||||||
import ru.nbch.credit_tracker.service.task.setup.IPipeLineStarter;
|
import ru.nbch.pipeline.engine.core.Pipeline;
|
||||||
import ru.nbch.credit_tracker.service.task.setup.IPipeLineTerminator;
|
import ru.nbch.pipeline.engine.core.PipelineBackoff;
|
||||||
import ru.nbch.credit_tracker.service.task.setup.PipeLineBuilder;
|
import ru.nbch.pipeline.engine.core.setup.IPipeLineStarter;
|
||||||
|
import ru.nbch.pipeline.engine.core.setup.IPipeLineTerminator;
|
||||||
|
import ru.nbch.pipeline.engine.core.setup.PipeLineBuilderV2;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
@ -70,7 +72,7 @@ public class PipelinePackageFabric implements InitializingBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pipeline build(SetupParam setupParam) throws Exception {
|
public Pipeline build(SetupParam setupParam) throws Exception {
|
||||||
return PipeLineBuilder.first(nameEnricherQueueFactory.getObject(), idEnricherQueueFactory.getObject())
|
return PipeLineBuilderV2.first(nameEnricherQueueFactory.getObject(), idEnricherQueueFactory.getObject())
|
||||||
.handler(fidNameEnricher)
|
.handler(fidNameEnricher)
|
||||||
.andThen()
|
.andThen()
|
||||||
.stage(sendSignalQueueFactory.getObject())
|
.stage(sendSignalQueueFactory.getObject())
|
||||||
|
|
@ -84,7 +86,7 @@ public class PipelinePackageFabric implements InitializingBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pipeline buildRecalculationPD(SetupParam setupParam) throws Exception {
|
public Pipeline buildRecalculationPD(SetupParam setupParam) throws Exception {
|
||||||
return PipeLineBuilder.first(nameUpdaterQueueFactory.getObject(), idUpdaterQueueFactory.getObject())
|
return PipeLineBuilderV2.first(nameUpdaterQueueFactory.getObject(), idUpdaterQueueFactory.getObject())
|
||||||
.handler(fidNameUpdater)
|
.handler(fidNameUpdater)
|
||||||
.andThen()
|
.andThen()
|
||||||
.stage(noOpQueueFactory.getObject())
|
.stage(noOpQueueFactory.getObject())
|
||||||
|
|
@ -98,7 +100,7 @@ public class PipelinePackageFabric implements InitializingBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Pipeline buildRecalculationPDMigration(SetupParam setupParam) throws Exception {
|
public Pipeline buildRecalculationPDMigration(SetupParam setupParam) throws Exception {
|
||||||
return PipeLineBuilder.first(nameUpdaterQueueFactory.getObject(), idUpdaterQueueFactory.getObject())
|
return PipeLineBuilderV2.first(nameUpdaterQueueFactory.getObject(), idUpdaterQueueFactory.getObject())
|
||||||
.handler(fidNameUpdaterMigration)
|
.handler(fidNameUpdaterMigration)
|
||||||
.andThen()
|
.andThen()
|
||||||
.stage(noOpQueueFactory.getObject())
|
.stage(noOpQueueFactory.getObject())
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,5 @@
|
||||||
package ru.nbch.credit_tracker.service.task;
|
package ru.nbch.credit_tracker.service.task;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Semaphore;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
@ -19,6 +13,14 @@ import ru.nbch.credit_tracker.service.signal.SignalRestService;
|
||||||
import ru.nbch.credit_tracker.service.task.impl.PipelineMode;
|
import ru.nbch.credit_tracker.service.task.impl.PipelineMode;
|
||||||
import ru.nbch.credit_tracker.service.task.impl.XmlMergeCoordinator;
|
import ru.nbch.credit_tracker.service.task.impl.XmlMergeCoordinator;
|
||||||
import ru.nbch.credit_tracker.utils.error.ExceptionUtils;
|
import ru.nbch.credit_tracker.utils.error.ExceptionUtils;
|
||||||
|
import ru.nbch.pipeline.engine.core.Pipeline;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class PipelinePackageOrchestrator {
|
public class PipelinePackageOrchestrator {
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,16 @@
|
||||||
package ru.nbch.credit_tracker.service.task;
|
package ru.nbch.credit_tracker.service.task;
|
||||||
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Semaphore;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
||||||
import ru.nbch.credit_tracker.utils.error.ExceptionUtils;
|
import ru.nbch.credit_tracker.utils.error.ExceptionUtils;
|
||||||
|
import ru.nbch.pipeline.engine.core.Pipeline;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class PipelineRecalcPDOrchestrator {
|
public class PipelineRecalcPDOrchestrator {
|
||||||
|
|
|
||||||
|
|
@ -1,227 +0,0 @@
|
||||||
package ru.nbch.credit_tracker.service.task;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Future;
|
|
||||||
import java.util.concurrent.SynchronousQueue;
|
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
|
||||||
import ru.nbch.credit_tracker.model.PipelineContext;
|
|
||||||
import ru.nbch.credit_tracker.model.StagePayload;
|
|
||||||
import ru.nbch.credit_tracker.utils.LogUtil;
|
|
||||||
import ru.nbch.credit_tracker.utils.TaskTimer;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
public class Stage<X extends StagePayload, Z extends StagePayload> implements Runnable {
|
|
||||||
private final Handler<X, Z> dispatcher;
|
|
||||||
private final BlockingQueue<X> in;
|
|
||||||
private final BlockingQueue<Z> out;
|
|
||||||
private final ExecutorService ioPool;
|
|
||||||
private Consumer<Z> consumer = null;
|
|
||||||
private final String dispatcherName;
|
|
||||||
private Pipeline pipeline;
|
|
||||||
private PipelineBackoff pipelineBackoff;
|
|
||||||
private final TaskTimer stopWatch = new TaskTimer();
|
|
||||||
|
|
||||||
private static final ThreadPoolExecutor.CallerRunsPolicy callerRunsPolicy
|
|
||||||
= new ThreadPoolExecutor.CallerRunsPolicy();
|
|
||||||
private PipelineContext<?> context;
|
|
||||||
|
|
||||||
public Stage(Handler<X, Z> dispatcher,
|
|
||||||
BlockingQueue<X> in,
|
|
||||||
BlockingQueue<Z> out) {
|
|
||||||
if (dispatcher.preferredConcurrency() < 2) {
|
|
||||||
throw new IllegalStateException("preferred concurrency must be at least 2");
|
|
||||||
}
|
|
||||||
this.dispatcher = dispatcher;
|
|
||||||
this.in = in;
|
|
||||||
this.out = out;
|
|
||||||
this.dispatcherName = dispatcher.getClass().getSimpleName();
|
|
||||||
var mdcMap = LogUtil.extractMdcMap();
|
|
||||||
BlockingQueue<Runnable> handoffQueue = new SynchronousQueue<>();
|
|
||||||
this.ioPool = new ThreadPoolExecutor(dispatcher.preferredConcurrency(),
|
|
||||||
dispatcher.preferredConcurrency(),
|
|
||||||
0L, TimeUnit.MINUTES,
|
|
||||||
handoffQueue,
|
|
||||||
r -> {
|
|
||||||
Thread t = new Thread(LogUtil.wrap(mdcMap, r));
|
|
||||||
t.setName("pipe-handler-%s-%d".formatted(dispatcherName, t.threadId()));
|
|
||||||
return t;
|
|
||||||
},
|
|
||||||
(r, executor) -> {
|
|
||||||
log.info("stage {}: all threads are working; switch to CallerRunsPolicy", dispatcherName);
|
|
||||||
try {
|
|
||||||
//блокировать отправителя, пока какой‑то рабочий поток не возьмёт задачу
|
|
||||||
handoffQueue.put(r);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
// callerRunsPolicy.rejectedExecution(r, executor);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
List<Future<Void>> inflight = new ArrayList<>();
|
|
||||||
log.info("this is main thread for {}", dispatcherName);
|
|
||||||
try {
|
|
||||||
int counter = 0;
|
|
||||||
while (true) {
|
|
||||||
X b = takeQuiet();
|
|
||||||
counter++;
|
|
||||||
log.trace("Take item from queue counter: {}", counter);
|
|
||||||
if (wasInterrupted()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (b.isPoison()) {
|
|
||||||
log.info("Got poison");
|
|
||||||
// дождаться всех in-flight задач
|
|
||||||
for (Future<Void> f : inflight) {
|
|
||||||
if (wasInterrupted()) {
|
|
||||||
log.info("stage {} was interrupted while waiting for tasks to finish", dispatcherName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
f.get();
|
|
||||||
}
|
|
||||||
dispatcher.handleOnPoison(b);
|
|
||||||
putQuiet(out, dispatcher.cookPoison());
|
|
||||||
log.info("stage {} finished.", dispatcherName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int finalCounter = counter;
|
|
||||||
AtomicInteger retryForSingleTask = new AtomicInteger(0);
|
|
||||||
log.trace("submit task");
|
|
||||||
Future<Void> f = ioPool.submit(() -> {
|
|
||||||
while (retryForSingleTask.incrementAndGet() < pipelineBackoff.getRetryCount()) {
|
|
||||||
try {
|
|
||||||
if (Thread.currentThread().isInterrupted()) {
|
|
||||||
log.info("stage {} was interrupted. skipping task {}...", dispatcherName, finalCounter);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
log.info("stage {} task {} started.", dispatcher.getClass().getSimpleName(), finalCounter);
|
|
||||||
Z p;
|
|
||||||
try (var m = stopWatch.start(dispatcherName + "-handler")) {
|
|
||||||
if (b.getContext() == null) {
|
|
||||||
b.setContext(context);
|
|
||||||
}
|
|
||||||
p = dispatcher.handle(b);
|
|
||||||
p.setContext(b.getContext()); // нужно т.к. в конце придет в терминатор
|
|
||||||
}
|
|
||||||
if (Thread.currentThread().isInterrupted()) {
|
|
||||||
log.info("after {} task {} finished, worker has been interrupted. not putting result in queue.",
|
|
||||||
dispatcherName, finalCounter);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
putQuiet(out, p);
|
|
||||||
log.info("stage {} task {} ended.", dispatcher.getClass().getSimpleName(), finalCounter);
|
|
||||||
return null;
|
|
||||||
} catch (Exception e) {
|
|
||||||
boolean isRetryable = pipelineBackoff.isRetryable(e);
|
|
||||||
if (!isRetryable) {
|
|
||||||
log.error("{} ERROR: {}", dispatcherName, ExceptionUtils.getStackTrace(e));
|
|
||||||
pipeline.close();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
log.warn("{} RETRY AFTER ERROR: {}", dispatcherName, ExceptionUtils.getStackTrace(e));
|
|
||||||
pipelineBackoff.backoff();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.error("tried for {} times, failed batch...", retryForSingleTask.get());
|
|
||||||
pipeline.close();
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
inflight.add(f);
|
|
||||||
if ((counter % 20) == 0) {
|
|
||||||
log.debug("Clean inflight future");
|
|
||||||
inflight.removeIf(Future::isDone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("Error for {}: {}; {}", dispatcherName, info(), ExceptionUtils.getStackTrace(e));
|
|
||||||
putQuiet(out, dispatcher.cookPoison());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private String info() {
|
|
||||||
ThreadPoolExecutor casted = (ThreadPoolExecutor) ioPool;
|
|
||||||
return "executor active tasks: %d; queue size: %d, completed tasks: %d".formatted(
|
|
||||||
casted.getActiveCount(),
|
|
||||||
casted.getQueue().size(),
|
|
||||||
casted.getCompletedTaskCount()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean wasInterrupted() {
|
|
||||||
if (Thread.interrupted()) {
|
|
||||||
log.warn("pipeline was interrupted...");
|
|
||||||
//putQuiet(out, dispatcher.cookPoison());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void startRunning() {
|
|
||||||
ioPool.submit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
log.info("Stage {} is getting shutdown", dispatcher.getClass().getSimpleName());
|
|
||||||
log.trace("Stage time stats: {}", stopWatch.info());
|
|
||||||
ioPool.shutdownNow(); // прерываем обработчики
|
|
||||||
}
|
|
||||||
|
|
||||||
void putQuiet(BlockingQueue<Z> q, Z b) {
|
|
||||||
try {
|
|
||||||
if (consumer != null) {
|
|
||||||
consumer.accept(b);
|
|
||||||
}
|
|
||||||
try (var m = stopWatch.start(dispatcherName + "-put")) {
|
|
||||||
q.put(b);
|
|
||||||
}
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
log.error("Error for {}: {}; {}", dispatcherName, info(), ExceptionUtils.getStackTrace(e));
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
X takeQuiet() {
|
|
||||||
try (var m = stopWatch.start(dispatcherName + "-take")) {
|
|
||||||
return in.take();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
log.error("Main thread for {}: {}; {}", dispatcherName, info(), ExceptionUtils.getStackTrace(e));
|
|
||||||
Thread.currentThread().interrupt();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockingQueue<X> getIn() {
|
|
||||||
return in;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setConsumer(Consumer<Z> consumer) {
|
|
||||||
this.consumer = consumer;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPipeline(Pipeline pipeline) {
|
|
||||||
this.pipeline = pipeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBackoff(PipelineBackoff pipelineBackoff) {
|
|
||||||
this.pipelineBackoff = pipelineBackoff;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setContext(PipelineContext<?> context) {
|
|
||||||
this.context = context;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PipelineContext<?> getContext() {
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -12,9 +12,9 @@ import ru.nbch.credit_tracker.model.impl.PartFilePayload;
|
||||||
import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
||||||
import ru.nbch.credit_tracker.service.indic.PersonService;
|
import ru.nbch.credit_tracker.service.indic.PersonService;
|
||||||
import ru.nbch.credit_tracker.service.signal.PackageRecordsService;
|
import ru.nbch.credit_tracker.service.signal.PackageRecordsService;
|
||||||
import ru.nbch.credit_tracker.service.task.Handler;
|
|
||||||
import ru.nbch.credit_tracker.service.xml.stax.SignalsStaxXmlWriterV2;
|
import ru.nbch.credit_tracker.service.xml.stax.SignalsStaxXmlWriterV2;
|
||||||
import ru.nbch.credit_tracker.utils.CTUtil;
|
import ru.nbch.credit_tracker.utils.CTUtil;
|
||||||
|
import ru.nbch.pipeline.engine.core.Handler;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
||||||
import ru.nbch.credit_tracker.model.impl.VoidPayload;
|
import ru.nbch.credit_tracker.model.impl.VoidPayload;
|
||||||
import ru.nbch.credit_tracker.service.indic.PersonService;
|
import ru.nbch.credit_tracker.service.indic.PersonService;
|
||||||
import ru.nbch.credit_tracker.service.signal.PackageRecordsService;
|
import ru.nbch.credit_tracker.service.signal.PackageRecordsService;
|
||||||
import ru.nbch.credit_tracker.service.task.Handler;
|
|
||||||
import ru.nbch.credit_tracker.utils.CTUtil;
|
import ru.nbch.credit_tracker.utils.CTUtil;
|
||||||
|
import ru.nbch.pipeline.engine.core.Handler;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,17 @@ import org.springframework.stereotype.Service;
|
||||||
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
||||||
import ru.nbch.credit_tracker.entities.app.PhonesMap;
|
import ru.nbch.credit_tracker.entities.app.PhonesMap;
|
||||||
import ru.nbch.credit_tracker.entities.indic.Name;
|
import ru.nbch.credit_tracker.entities.indic.Name;
|
||||||
import ru.nbch.credit_tracker.model.*;
|
import ru.nbch.credit_tracker.model.FlagData;
|
||||||
|
import ru.nbch.credit_tracker.model.IdData;
|
||||||
|
import ru.nbch.credit_tracker.model.NameData;
|
||||||
|
import ru.nbch.credit_tracker.model.SubjectProfile;
|
||||||
import ru.nbch.credit_tracker.model.impl.PackageVariable;
|
import ru.nbch.credit_tracker.model.impl.PackageVariable;
|
||||||
import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
||||||
import ru.nbch.credit_tracker.service.indic.PersonService;
|
import ru.nbch.credit_tracker.service.indic.PersonService;
|
||||||
import ru.nbch.credit_tracker.service.signal.PackageRecordsService;
|
import ru.nbch.credit_tracker.service.signal.PackageRecordsService;
|
||||||
import ru.nbch.credit_tracker.service.task.Handler;
|
|
||||||
import ru.nbch.credit_tracker.utils.CTUtil;
|
import ru.nbch.credit_tracker.utils.CTUtil;
|
||||||
|
import ru.nbch.pipeline.engine.core.Handler;
|
||||||
|
import ru.nbch.pipeline.engine.core.PipelineContext;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
|
||||||
|
|
@ -11,8 +11,8 @@ import ru.nbch.credit_tracker.service.UserPackageService;
|
||||||
import ru.nbch.credit_tracker.service.indic.PersonService;
|
import ru.nbch.credit_tracker.service.indic.PersonService;
|
||||||
import ru.nbch.credit_tracker.service.signal.PackageRecordsService;
|
import ru.nbch.credit_tracker.service.signal.PackageRecordsService;
|
||||||
import ru.nbch.credit_tracker.service.signal.PhonesMapService;
|
import ru.nbch.credit_tracker.service.signal.PhonesMapService;
|
||||||
import ru.nbch.credit_tracker.service.task.Handler;
|
|
||||||
import ru.nbch.credit_tracker.utils.CTUtil;
|
import ru.nbch.credit_tracker.utils.CTUtil;
|
||||||
|
import ru.nbch.pipeline.engine.core.Handler;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@ import ru.nbch.credit_tracker.model.impl.PackageVariable;
|
||||||
import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
||||||
import ru.nbch.credit_tracker.service.indic.PersonService;
|
import ru.nbch.credit_tracker.service.indic.PersonService;
|
||||||
import ru.nbch.credit_tracker.service.signal.PhonesMapService;
|
import ru.nbch.credit_tracker.service.signal.PhonesMapService;
|
||||||
import ru.nbch.credit_tracker.service.task.Handler;
|
|
||||||
import ru.nbch.credit_tracker.utils.CTUtil;
|
import ru.nbch.credit_tracker.utils.CTUtil;
|
||||||
|
import ru.nbch.pipeline.engine.core.Handler;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
package ru.nbch.credit_tracker.service.task.impl;
|
package ru.nbch.credit_tracker.service.task.impl;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
||||||
|
|
@ -11,14 +8,18 @@ import ru.nbch.credit_tracker.entities.app.UserPackage;
|
||||||
import ru.nbch.credit_tracker.enums.PoisonType;
|
import ru.nbch.credit_tracker.enums.PoisonType;
|
||||||
import ru.nbch.credit_tracker.exceptions.SignalClientException;
|
import ru.nbch.credit_tracker.exceptions.SignalClientException;
|
||||||
import ru.nbch.credit_tracker.mapper.signal.UserPackageMapper;
|
import ru.nbch.credit_tracker.mapper.signal.UserPackageMapper;
|
||||||
import ru.nbch.credit_tracker.model.PipelineContext;
|
|
||||||
import ru.nbch.credit_tracker.model.SubjectProfile;
|
import ru.nbch.credit_tracker.model.SubjectProfile;
|
||||||
import ru.nbch.credit_tracker.model.impl.PackageVariable;
|
import ru.nbch.credit_tracker.model.impl.PackageVariable;
|
||||||
import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
||||||
import ru.nbch.credit_tracker.service.signal.PackageRecordsService;
|
import ru.nbch.credit_tracker.service.signal.PackageRecordsService;
|
||||||
import ru.nbch.credit_tracker.service.task.SetupParam;
|
import ru.nbch.credit_tracker.service.task.SetupParam;
|
||||||
import ru.nbch.credit_tracker.service.task.setup.IPipeLineStarter;
|
|
||||||
import ru.nbch.credit_tracker.utils.error.ExceptionUtils;
|
import ru.nbch.credit_tracker.utils.error.ExceptionUtils;
|
||||||
|
import ru.nbch.pipeline.engine.core.PipelineContext;
|
||||||
|
import ru.nbch.pipeline.engine.core.setup.IPipeLineStarter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
public abstract class KickPipeLine implements IPipeLineStarter<SubjectPayload> {
|
public abstract class KickPipeLine implements IPipeLineStarter<SubjectPayload> {
|
||||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
package ru.nbch.credit_tracker.service.task.impl;
|
package ru.nbch.credit_tracker.service.task.impl;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
||||||
|
|
@ -12,14 +10,17 @@ import ru.nbch.credit_tracker.mapper.signal.PhonesMapMapper;
|
||||||
import ru.nbch.credit_tracker.mapper.signal.UserPackageMapper;
|
import ru.nbch.credit_tracker.mapper.signal.UserPackageMapper;
|
||||||
import ru.nbch.credit_tracker.model.IdData;
|
import ru.nbch.credit_tracker.model.IdData;
|
||||||
import ru.nbch.credit_tracker.model.NameData;
|
import ru.nbch.credit_tracker.model.NameData;
|
||||||
import ru.nbch.credit_tracker.model.PipelineContext;
|
|
||||||
import ru.nbch.credit_tracker.model.SubjectProfile;
|
import ru.nbch.credit_tracker.model.SubjectProfile;
|
||||||
import ru.nbch.credit_tracker.model.impl.PackageVariable;
|
import ru.nbch.credit_tracker.model.impl.PackageVariable;
|
||||||
import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
import ru.nbch.credit_tracker.model.impl.SubjectPayload;
|
||||||
import ru.nbch.credit_tracker.service.signal.PackageRecordsService;
|
import ru.nbch.credit_tracker.service.signal.PackageRecordsService;
|
||||||
import ru.nbch.credit_tracker.service.task.SetupParam;
|
import ru.nbch.credit_tracker.service.task.SetupParam;
|
||||||
import ru.nbch.credit_tracker.service.task.setup.IPipeLineStarter;
|
|
||||||
import ru.nbch.credit_tracker.utils.error.ExceptionUtils;
|
import ru.nbch.credit_tracker.utils.error.ExceptionUtils;
|
||||||
|
import ru.nbch.pipeline.engine.core.PipelineContext;
|
||||||
|
import ru.nbch.pipeline.engine.core.setup.IPipeLineStarter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
|
||||||
public class KickRecalcPipeLine implements IPipeLineStarter<SubjectPayload> {
|
public class KickRecalcPipeLine implements IPipeLineStarter<SubjectPayload> {
|
||||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
package ru.nbch.credit_tracker.service.task.impl;
|
package ru.nbch.credit_tracker.service.task.impl;
|
||||||
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
import ru.nbch.credit_tracker.model.impl.EmptyTerminatePayload;
|
import ru.nbch.credit_tracker.model.impl.EmptyTerminatePayload;
|
||||||
import ru.nbch.credit_tracker.model.impl.VoidPayload;
|
import ru.nbch.credit_tracker.model.impl.VoidPayload;
|
||||||
import ru.nbch.credit_tracker.service.task.setup.IPipeLineTerminator;
|
import ru.nbch.pipeline.engine.core.setup.IPipeLineTerminator;
|
||||||
|
|
||||||
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public final class NoOpTerminator implements IPipeLineTerminator<VoidPayload, EmptyTerminatePayload> {
|
public final class NoOpTerminator implements IPipeLineTerminator<VoidPayload, EmptyTerminatePayload> {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,15 @@
|
||||||
package ru.nbch.credit_tracker.service.task.impl;
|
package ru.nbch.credit_tracker.service.task.impl;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import java.io.InputStream;
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
import java.io.OutputStream;
|
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
||||||
import java.io.OutputStreamWriter;
|
import ru.nbch.credit_tracker.model.impl.PartFilePayload;
|
||||||
import java.io.Writer;
|
import ru.nbch.credit_tracker.model.impl.SignalXmlFilePayload;
|
||||||
|
import ru.nbch.pipeline.engine.core.setup.IPipeLineTerminator;
|
||||||
|
import ru.nbch.pipeline.engine.utils.TaskTimer;
|
||||||
|
|
||||||
|
import javax.xml.stream.*;
|
||||||
|
import java.io.*;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
|
@ -12,19 +17,6 @@ import java.nio.file.StandardOpenOption;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import javax.xml.stream.XMLInputFactory;
|
|
||||||
import javax.xml.stream.XMLOutputFactory;
|
|
||||||
import javax.xml.stream.XMLStreamConstants;
|
|
||||||
import javax.xml.stream.XMLStreamException;
|
|
||||||
import javax.xml.stream.XMLStreamReader;
|
|
||||||
import javax.xml.stream.XMLStreamWriter;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
|
||||||
import ru.nbch.credit_tracker.config.settings.CreditTrackerSettings;
|
|
||||||
import ru.nbch.credit_tracker.model.impl.PartFilePayload;
|
|
||||||
import ru.nbch.credit_tracker.model.impl.SignalXmlFilePayload;
|
|
||||||
import ru.nbch.credit_tracker.service.task.setup.IPipeLineTerminator;
|
|
||||||
import ru.nbch.credit_tracker.utils.TaskTimer;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public final class XmlMergeCoordinator implements IPipeLineTerminator<PartFilePayload, SignalXmlFilePayload> {
|
public final class XmlMergeCoordinator implements IPipeLineTerminator<PartFilePayload, SignalXmlFilePayload> {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
package ru.nbch.credit_tracker.service.task.setup;
|
|
||||||
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import ru.nbch.credit_tracker.model.PipelineContext;
|
|
||||||
import ru.nbch.credit_tracker.model.StagePayload;
|
|
||||||
|
|
||||||
public interface IPipeLineStarter<Q extends StagePayload> {
|
|
||||||
void startFillingQueue(BlockingQueue<Q> queue);
|
|
||||||
|
|
||||||
default void setContext(PipelineContext<?> context) {}
|
|
||||||
}
|
|
||||||
|
|
@ -1,11 +0,0 @@
|
||||||
package ru.nbch.credit_tracker.service.task.setup;
|
|
||||||
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.concurrent.CompletableFuture;
|
|
||||||
import ru.nbch.credit_tracker.model.StagePayload;
|
|
||||||
import ru.nbch.credit_tracker.model.TerminatePayload;
|
|
||||||
|
|
||||||
public interface IPipeLineTerminator<Q extends StagePayload, X extends TerminatePayload> extends Runnable {
|
|
||||||
void setPollingQueue(BlockingQueue<Q> queue);
|
|
||||||
CompletableFuture<X> doneFuture();
|
|
||||||
}
|
|
||||||
|
|
@ -1,100 +0,0 @@
|
||||||
package ru.nbch.credit_tracker.service.task.setup;
|
|
||||||
|
|
||||||
import ru.nbch.credit_tracker.model.PipelineContext;
|
|
||||||
import ru.nbch.credit_tracker.model.StagePayload;
|
|
||||||
import ru.nbch.credit_tracker.service.task.Pipeline;
|
|
||||||
import ru.nbch.credit_tracker.service.task.PipelineBackoff;
|
|
||||||
import ru.nbch.credit_tracker.service.task.Stage;
|
|
||||||
import ru.nbch.credit_tracker.service.task.setup.step.HandlerStep;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
|
|
||||||
public class PipeLineBuilder<FIRST extends StagePayload, LAST extends StagePayload> {
|
|
||||||
private final List<Stage<?, ?>> stages;
|
|
||||||
private Stage<FIRST, ?> firstStage;
|
|
||||||
private BlockingQueue<LAST> lastQueue;
|
|
||||||
private IPipeLineStarter<FIRST> pipeLineStarter;
|
|
||||||
private IPipeLineTerminator<LAST, ?> pipeLineTerminator;
|
|
||||||
private PipelineBackoff backoff;
|
|
||||||
private PipelineContext<?> context;
|
|
||||||
|
|
||||||
private PipeLineBuilder() {
|
|
||||||
this.stages = new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <I extends StagePayload, O extends StagePayload>
|
|
||||||
HandlerStep<I, I, O> first(BlockingQueue<I> inputQueue, BlockingQueue<O> outputQueue) {
|
|
||||||
PipeLineBuilder<I, O> builder = new PipeLineBuilder<>();
|
|
||||||
builder.lastQueue = outputQueue;
|
|
||||||
HandlerStep<I, I, O> step = StageBuilder.create(inputQueue, outputQueue);
|
|
||||||
((StageBuilder<I, I, O>) step).setParent(builder);
|
|
||||||
return step;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <NEXT extends StagePayload>
|
|
||||||
HandlerStep<FIRST, LAST, NEXT> stage(BlockingQueue<NEXT> outputQueue) {
|
|
||||||
HandlerStep<FIRST, LAST, NEXT> step = StageBuilder.create(lastQueue, outputQueue);
|
|
||||||
lastQueue = (BlockingQueue<LAST>) outputQueue;
|
|
||||||
((StageBuilder<FIRST, LAST, NEXT>) step).setParent((PipeLineBuilder<FIRST, NEXT>) this);
|
|
||||||
return step;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PipeLineBuilder<FIRST, LAST> fillInitialQueue(IPipeLineStarter<FIRST> pipeLineStarter) {
|
|
||||||
Objects.requireNonNull(pipeLineStarter, "pipeLineStarter is required");
|
|
||||||
if (firstStage == null) {
|
|
||||||
throw new IllegalStateException("Pipeline has no stages");
|
|
||||||
}
|
|
||||||
this.pipeLineStarter = pipeLineStarter;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PipeLineBuilder<FIRST, LAST> pollFinishingQueue(IPipeLineTerminator<LAST, ?> pipeLineTerminator) {
|
|
||||||
Objects.requireNonNull(pipeLineTerminator, "pipeLineTerminator is required");
|
|
||||||
this.pipeLineTerminator = pipeLineTerminator;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public PipeLineBuilder<FIRST, LAST> backoff(PipelineBackoff backoff) {
|
|
||||||
this.backoff = backoff;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T extends Enum<T>>
|
|
||||||
PipeLineBuilder<FIRST, LAST> context(Class<T> contextKeyClass) {
|
|
||||||
this.context = new PipelineContext<>(contextKeyClass);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Pipeline build() {
|
|
||||||
Pipeline p = new Pipeline();
|
|
||||||
p.setStarter(() -> {
|
|
||||||
stages.forEach(stage -> {
|
|
||||||
stage.setPipeline(p);
|
|
||||||
stage.setBackoff(backoff);
|
|
||||||
stage.setContext(context);
|
|
||||||
stage.startRunning();
|
|
||||||
});
|
|
||||||
pipeLineStarter.setContext(context);
|
|
||||||
pipeLineStarter.startFillingQueue(firstStage.getIn());
|
|
||||||
});
|
|
||||||
pipeLineTerminator.setPollingQueue(lastQueue);
|
|
||||||
p.setTerminator(pipeLineTerminator);
|
|
||||||
p.setStages(stages);
|
|
||||||
p.setContext(context);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
<I extends StagePayload, O extends StagePayload>
|
|
||||||
void addStage(Stage<I, O> stage) {
|
|
||||||
Objects.requireNonNull(stage, "stage is required");
|
|
||||||
if (stages.isEmpty()) {
|
|
||||||
this.firstStage = (Stage<FIRST, ?>) stage;
|
|
||||||
}
|
|
||||||
stages.add(stage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
package ru.nbch.credit_tracker.service.task.setup;
|
|
||||||
|
|
||||||
import ru.nbch.credit_tracker.model.StagePayload;
|
|
||||||
import ru.nbch.credit_tracker.refactoring.Suspicios;
|
|
||||||
import ru.nbch.credit_tracker.service.task.Handler;
|
|
||||||
import ru.nbch.credit_tracker.service.task.Stage;
|
|
||||||
import ru.nbch.credit_tracker.service.task.setup.step.BuildStep;
|
|
||||||
import ru.nbch.credit_tracker.service.task.setup.step.HandlerStep;
|
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.BlockingQueue;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Step Builder для Stage:
|
|
||||||
* Обязательная последовательность: handler(...) -> poison(...) -> buildStage()
|
|
||||||
*/
|
|
||||||
public class StageBuilder<FIRST extends StagePayload, I extends StagePayload, O extends StagePayload>
|
|
||||||
implements HandlerStep<FIRST, I, O>, BuildStep<FIRST, O> {
|
|
||||||
|
|
||||||
private PipeLineBuilder<FIRST, O> parent;
|
|
||||||
private final BlockingQueue<I> inputQueue;
|
|
||||||
private final BlockingQueue<O> outputQueue;
|
|
||||||
private Handler<I, O> handler;
|
|
||||||
private Consumer<O> consumer = null;
|
|
||||||
|
|
||||||
private StageBuilder(BlockingQueue<I> inputQueue, BlockingQueue<O> outputQueue) {
|
|
||||||
this.inputQueue = Objects.requireNonNull(inputQueue, "inputQueue is required");
|
|
||||||
this.outputQueue = Objects.requireNonNull(outputQueue, "outputQueue is required");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Стартовая фабрика возвращает первый шаг — HandlerStep */
|
|
||||||
public static <FIRST extends StagePayload, I extends StagePayload, O extends StagePayload>
|
|
||||||
HandlerStep<FIRST, I, O> create(BlockingQueue<I> inputQueue, BlockingQueue<O> outputQueue) {
|
|
||||||
return new StageBuilder<>(inputQueue, outputQueue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setParent(PipeLineBuilder<FIRST, O> parent) {
|
|
||||||
this.parent = Objects.requireNonNull(parent, "parent is required");
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===================== ШАГИ =====================
|
|
||||||
|
|
||||||
/** Шаг 1: задать обработчик */
|
|
||||||
@Override
|
|
||||||
public BuildStep<FIRST, O> handler(Handler<I, O> handler) {
|
|
||||||
this.handler = Objects.requireNonNull(handler, "handler is required");
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suspicios("Удалить?")
|
|
||||||
@Override
|
|
||||||
public BuildStep<FIRST, O> handlerResult(Consumer<O> consumer) {
|
|
||||||
this.consumer = Objects.requireNonNull(consumer, "consumer is required");
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Шаг 3: собрать Stage и вернуться к PipeLineBuilder */
|
|
||||||
@Override
|
|
||||||
public PipeLineBuilder<FIRST, O> andThen() {
|
|
||||||
if (parent == null) {
|
|
||||||
throw new IllegalStateException("parent PipeLineBuilder is not set");
|
|
||||||
}
|
|
||||||
if (handler == null) {
|
|
||||||
throw new IllegalStateException("handler must be set before buildStage()");
|
|
||||||
}
|
|
||||||
|
|
||||||
Stage<I, O> stage = new Stage<>(handler, inputQueue, outputQueue);
|
|
||||||
stage.setConsumer(consumer);
|
|
||||||
parent.addStage(stage);
|
|
||||||
return parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===================== Step-interfaces =====================
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
package ru.nbch.credit_tracker.service.task.setup.step;
|
|
||||||
|
|
||||||
import ru.nbch.credit_tracker.model.StagePayload;
|
|
||||||
import ru.nbch.credit_tracker.refactoring.Suspicios;
|
|
||||||
import ru.nbch.credit_tracker.service.task.setup.PipeLineBuilder;
|
|
||||||
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
public interface BuildStep<FIRST extends StagePayload, O extends StagePayload> {
|
|
||||||
PipeLineBuilder<FIRST, O> andThen();
|
|
||||||
|
|
||||||
@Suspicios("Удалить?")
|
|
||||||
BuildStep<FIRST, O> handlerResult(Consumer<O> consumer);
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
package ru.nbch.credit_tracker.service.task.setup.step;
|
|
||||||
|
|
||||||
import ru.nbch.credit_tracker.model.StagePayload;
|
|
||||||
import ru.nbch.credit_tracker.service.task.Handler;
|
|
||||||
|
|
||||||
public interface HandlerStep<FIRST extends StagePayload, I extends StagePayload, O extends StagePayload> {
|
|
||||||
BuildStep<FIRST, O> handler(Handler<I, O> handler);
|
|
||||||
}
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
package ru.nbch.credit_tracker.utils;
|
package ru.nbch.credit_tracker.utils;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.slf4j.MDC;
|
import org.slf4j.MDC;
|
||||||
import ru.nbch.credit_tracker.utils.error.ExceptionUtils;
|
import ru.nbch.credit_tracker.utils.error.ExceptionUtils;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
// TODO update library to use provided LogUtil
|
||||||
public class LogUtil {
|
public class LogUtil {
|
||||||
private final static Logger log = LoggerFactory.getLogger(LogUtil.class);
|
private final static Logger log = LoggerFactory.getLogger(LogUtil.class);
|
||||||
public static final String mdcKey = "ru.nbch.credit_tracker.log.mdc.key";
|
public static final String mdcKey = "ru.nbch.credit_tracker.log.mdc.key";
|
||||||
|
|
|
||||||
|
|
@ -1,166 +0,0 @@
|
||||||
package ru.nbch.credit_tracker.utils;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
import java.util.concurrent.atomic.LongAdder;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class TaskTimer {
|
|
||||||
private final ConcurrentMap<String, TaskStats> stats = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Начать измерение времени для задачи с именем taskName.
|
|
||||||
* Используется обычно через try-with-resources:
|
|
||||||
*
|
|
||||||
* try (var m = timer.start("dispatcher.handle")) {
|
|
||||||
* dispatcher.handle(b);
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
public Measurement start(String taskName) {
|
|
||||||
return new Measurement(this, taskName, System.nanoTime());
|
|
||||||
}
|
|
||||||
|
|
||||||
void record(String taskName, long durationNanos) {
|
|
||||||
TaskStats s = stats.computeIfAbsent(taskName, key -> new TaskStats());
|
|
||||||
s.record(durationNanos);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Снимок статистики по всем задачам на текущий момент.
|
|
||||||
*/
|
|
||||||
public Map<String, StatsSnapshot> snapshot() {
|
|
||||||
return stats.entrySet().stream()
|
|
||||||
.collect(Collectors.toUnmodifiableMap(
|
|
||||||
Map.Entry::getKey,
|
|
||||||
e -> e.getValue().snapshot()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Снимок статистики по одной задаче.
|
|
||||||
*/
|
|
||||||
public StatsSnapshot snapshot(String taskName) {
|
|
||||||
TaskStats s = stats.get(taskName);
|
|
||||||
return s == null ? StatsSnapshot.empty() : s.snapshot();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String info() {
|
|
||||||
return snapshot().entrySet().stream().map(stringStatsSnapshotEntry ->
|
|
||||||
"%s: %s".formatted(stringStatsSnapshotEntry.getKey(), stringStatsSnapshotEntry.getValue())).collect(Collectors.joining("\n", "\n", ""));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ---------- Вспомогательные классы ----------
|
|
||||||
|
|
||||||
public static final class StatsSnapshot {
|
|
||||||
public final long count;
|
|
||||||
public final long totalNanos;
|
|
||||||
public final long minNanos;
|
|
||||||
public final long maxNanos;
|
|
||||||
|
|
||||||
public StatsSnapshot(long count, long totalNanos, long minNanos, long maxNanos) {
|
|
||||||
this.count = count;
|
|
||||||
this.totalNanos = totalNanos;
|
|
||||||
this.minNanos = minNanos;
|
|
||||||
this.maxNanos = maxNanos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static StatsSnapshot empty() {
|
|
||||||
return new StatsSnapshot(0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double avgMillis() {
|
|
||||||
return count == 0 ? 0.0 : (totalNanos / 1_000_000.0) / count;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double totalMillis() {
|
|
||||||
return totalNanos / 1_000_000.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double minMillis() {
|
|
||||||
return minNanos == 0 ? 0.0 : minNanos / 1_000_000.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double maxMillis() {
|
|
||||||
return maxNanos == 0 ? 0.0 : maxNanos / 1_000_000.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "StatsSnapshot{" +
|
|
||||||
"count=" + count +
|
|
||||||
", totalMillis=" + totalMillis() +
|
|
||||||
", avgMillis=" + avgMillis() +
|
|
||||||
", minMillis=" + minMillis() +
|
|
||||||
", maxMillis=" + maxMillis() +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final class TaskStats {
|
|
||||||
private final LongAdder count = new LongAdder();
|
|
||||||
private final LongAdder totalNanos = new LongAdder();
|
|
||||||
private final AtomicLong minNanos = new AtomicLong(Long.MAX_VALUE);
|
|
||||||
private final AtomicLong maxNanos = new AtomicLong(Long.MIN_VALUE);
|
|
||||||
|
|
||||||
void record(long durationNanos) {
|
|
||||||
count.increment();
|
|
||||||
totalNanos.add(durationNanos);
|
|
||||||
|
|
||||||
// min
|
|
||||||
for (;;) {
|
|
||||||
long current = minNanos.get();
|
|
||||||
if (durationNanos >= current) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (minNanos.compareAndSet(current, durationNanos)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// max
|
|
||||||
for (;;) {
|
|
||||||
long current = maxNanos.get();
|
|
||||||
if (durationNanos <= current) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (maxNanos.compareAndSet(current, durationNanos)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StatsSnapshot snapshot() {
|
|
||||||
long c = count.sum();
|
|
||||||
if (c == 0) {
|
|
||||||
return StatsSnapshot.empty();
|
|
||||||
}
|
|
||||||
long total = totalNanos.sum();
|
|
||||||
long min = minNanos.get();
|
|
||||||
long max = maxNanos.get();
|
|
||||||
if (min == Long.MAX_VALUE) min = 0;
|
|
||||||
if (max == Long.MIN_VALUE) max = 0;
|
|
||||||
return new StatsSnapshot(c, total, min, max);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public final class Measurement implements AutoCloseable {
|
|
||||||
private final String taskName;
|
|
||||||
private final long startNanos;
|
|
||||||
private boolean closed = false;
|
|
||||||
|
|
||||||
private Measurement(TaskTimer timer, String taskName, long startNanos) {
|
|
||||||
this.taskName = taskName;
|
|
||||||
this.startNanos = startNanos;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
if (closed) return;
|
|
||||||
closed = true;
|
|
||||||
long duration = System.nanoTime() - startNanos;
|
|
||||||
TaskTimer.this.record(taskName, duration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Reference in a new issue