He fijado poller de archivos con ejecutor de tareas
ExecutorService executorService = Executors.newFixedThreadPool(10);
LOG.info("Setting up the poller for directory {} ", finalDirectory);
StandardIntegrationFlow standardIntegrationFlow = IntegrationFlows.from(new CustomFileReadingSource(finalDirectory),
c -> c.poller(Pollers.fixedDelay(5, TimeUnit.SECONDS, 5)
.taskExecutor(executorService)
.maxMessagesPerPoll(10)
.advice(new LoggerSourceAdvisor(finalDirectory))
))
//move file to processing first processing
.transform(new FileMoveTransformer("C:/processing", true))
.channel("fileRouter")
.get();
Como se ve He fijado fija threadpool
de 10 y máximo de mensaje 10 por sondeo. Si pongo 10 archivos se sigue procesando uno por uno. Lo que podría ser mal aquí?
* ACTUALIZACIÓN *
Funciona perfectamente bien después de la respuesta de Gary aunque no tengo otro problema ahora.
He fijado mi Poller como esto
setDirectory(new File(path));
DefaultDirectoryScanner scanner = new DefaultDirectoryScanner();
scanner.setFilter(new AcceptAllFileListFilter<>());
setScanner(scanner);
La razón de utilizar AcceptAll
ya que el mismo puede venir otra vez por eso me especie de movimiento del primer archivo. Pero cuando activo el ejecutor de rosca el mismo archivo está siendo procesada por hilos mutliple, supongo que debidoAcceptAllFile
Si cambio de AcceptOnceFileListFilter
que funciona, pero luego el mismo archivo que viene de nuevo, no será recogido de nuevo! ¿Qué puede hacerse para evitar este problema?
Emisión / del insecto
En clase AbstractPersistentAcceptOnceFileListFilter
tenemos este código
@Override
public boolean accept(F file) {
String key = buildKey(file);
synchronized (this.monitor) {
String newValue = value(file);
String oldValue = this.store.putIfAbsent(key, newValue);
if (oldValue == null) { // not in store
flushIfNeeded();
return true;
}
// same value in store
if (!isEqual(file, oldValue) && this.store.replace(key, oldValue, newValue)) {
flushIfNeeded();
return true;
}
return false;
}
}
Ahora, por ejemplo, si tengo la configuración máximo por sondeo 5 y hay dos archivos, entonces es posible mismo archivo sería recogido por dos hilos.
Digamos que mi código mueve los archivos una vez que lo leí.
Pero el otro hilo llegue al accept
método
Si el archivo no existe, entonces volverá el tiempo lastModified como 0 y volverá realidad.
Que produce el problema porque el archivo no está allí.
Si su 0, entonces debe devolver falso que el archivo ya no está allí.
Cuando se agrega un ejecutor de tareas a un poller; todo lo que hace es las manos de rosca planificador de la tarea sondeo fuera de un hilo en el grupo de subprocesos; el maxMessagesPerPoll
es parte de la tarea de sondeo. El poller en sí sólo se ejecuta una vez cada 5 segundos. Para conseguir lo que quiere, se debe añadir un canal ejecutor al flujo ...
@SpringBootApplication
public class So53521593Application {
private static final Logger logger = LoggerFactory.getLogger(So53521593Application.class);
public static void main(String[] args) {
SpringApplication.run(So53521593Application.class, args);
}
@Bean
public IntegrationFlow flow() {
ExecutorService exec = Executors.newFixedThreadPool(10);
return IntegrationFlows.from(() -> "foo", e -> e
.poller(Pollers.fixedDelay(5, TimeUnit.SECONDS)
.maxMessagesPerPoll(10)))
.channel(MessageChannels.executor(exec))
.<String>handle((p, h) -> {
try {
logger.info(p);
Thread.sleep(10_000);
}
catch (InterruptedException e1) {
Thread.currentThread().interrupt();
}
return null;
})
.get();
}
}
EDITAR
Funciona bien para mí...
@Bean
public IntegrationFlow flow() {
ExecutorService exec = Executors.newFixedThreadPool(10);
return IntegrationFlows.from(Files.inboundAdapter(new File("/tmp/foo")).filter(
new FileSystemPersistentAcceptOnceFileListFilter(new SimpleMetadataStore(), "foo")),
e -> e.poller(Pollers.fixedDelay(5, TimeUnit.SECONDS)
.maxMessagesPerPoll(10)))
.channel(MessageChannels.executor(exec))
.handle((p, h) -> {
try {
logger.info(p.toString());
Thread.sleep(10_000);
}
catch (InterruptedException e1) {
Thread.currentThread().interrupt();
}
return null;
})
.get();
}
y
28/11/2018 11: 46: 05,196 INFO 57.607 --- [piscina-1-thread-1] com.example.So53521593Application: /tmp/foo/test1.txt
28/11/2018 11: 46: 05,197 INFO 57.607 --- [piscina-1-thread-2] com.example.So53521593Application: /tmp/foo/test2.txt
y con touch test1.txt
28/11/2018 11: 48: 00,284 INFO 57.607 --- [piscina-1-thread-3] com.example.So53521593Application: /tmp/foo/test1.txt
EDIT1
De acuerdo - reproducido con esta ...
@Bean
public IntegrationFlow flow() {
ExecutorService exec = Executors.newFixedThreadPool(10);
return IntegrationFlows.from(Files.inboundAdapter(new File("/tmp/foo")).filter(
new FileSystemPersistentAcceptOnceFileListFilter(new SimpleMetadataStore(), "foo")),
e -> e.poller(Pollers.fixedDelay(5, TimeUnit.SECONDS)
.maxMessagesPerPoll(10)))
.channel(MessageChannels.executor(exec))
.<File>handle((p, h) -> {
try {
p.delete();
logger.info(p.toString());
Thread.sleep(10_000);
}
catch (InterruptedException e1) {
Thread.currentThread().interrupt();
}
return null;
})
.get();
}
y
28/11/2018 13: 22: 23.689 INFO 75.681 --- [piscina-1-thread-1] com.example.So53521593Application: /tmp/foo/test1.txt
28/11/2018 13: 22: 23.690 INFO 75.681 --- [piscina-1-thread-2] com.example.So53521593Application: /tmp/foo/test2.txt
28/11/2018 13: 22: 23.690 INFO 75.681 --- [piscina-1-thread-3] com.example.So53521593Application: /tmp/foo/test1.txt
28/11/2018 13: 22: 23.690 INFO 75.681 --- [piscina-1-thread-4] com.example.So53521593Application: /tmp/foo/test2.txt