Add automatic acquisition scheduler runtime

This commit is contained in:
litoral05
2026-05-20 08:43:25 +01:00
parent 15b342edff
commit 70e95a2b55
6 changed files with 198 additions and 2 deletions
@@ -1,12 +1,13 @@
package com.litoralregas.backend;
import com.litoralregas.backend.acquisition.scheduler.AcquisitionSchedulerProperties;
import com.litoralregas.backend.modbus.ModbusConnectionProperties;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@SpringBootApplication
@EnableConfigurationProperties(ModbusConnectionProperties.class)
@EnableConfigurationProperties({ModbusConnectionProperties.class, AcquisitionSchedulerProperties.class})
public class BackendApplication {
public static void main(String[] args) {
@@ -0,0 +1,66 @@
package com.litoralregas.backend.acquisition.scheduler;
import java.time.Instant;
public class AcquisitionRuntimeStatus {
private boolean running;
private Instant lastStartedAt;
private Instant lastFinishedAt;
private Integer lastSuccessfulReads;
private Integer lastFailedReads;
private String lastError;
public boolean isRunning() {
return running;
}
public void setRunning(boolean running) {
this.running = running;
}
public Instant getLastStartedAt() {
return lastStartedAt;
}
public void setLastStartedAt(Instant lastStartedAt) {
this.lastStartedAt = lastStartedAt;
}
public Instant getLastFinishedAt() {
return lastFinishedAt;
}
public void setLastFinishedAt(Instant lastFinishedAt) {
this.lastFinishedAt = lastFinishedAt;
}
public Integer getLastSuccessfulReads() {
return lastSuccessfulReads;
}
public void setLastSuccessfulReads(Integer lastSuccessfulReads) {
this.lastSuccessfulReads = lastSuccessfulReads;
}
public Integer getLastFailedReads() {
return lastFailedReads;
}
public void setLastFailedReads(Integer lastFailedReads) {
this.lastFailedReads = lastFailedReads;
}
public String getLastError() {
return lastError;
}
public void setLastError(String lastError) {
this.lastError = lastError;
}
}
@@ -0,0 +1,19 @@
package com.litoralregas.backend.acquisition.scheduler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
@Configuration
public class AcquisitionSchedulerConfig {
@Bean
public TaskScheduler acquisitionTaskScheduler() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(1);
scheduler.setThreadNamePrefix("acquisition-scheduler-");
scheduler.initialize();
return scheduler;
}
}
@@ -0,0 +1,26 @@
package com.litoralregas.backend.acquisition.scheduler;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "litoralregas.acquisition.scheduler")
public class AcquisitionSchedulerProperties {
private boolean enabled = false;
private long fixedDelayMillis = 3000;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public long getFixedDelayMillis() {
return fixedDelayMillis;
}
public void setFixedDelayMillis(long fixedDelayMillis) {
this.fixedDelayMillis = fixedDelayMillis;
}
}
@@ -0,0 +1,80 @@
package com.litoralregas.backend.acquisition.scheduler;
import com.litoralregas.backend.acquisition.polling.AcquisitionPollResult;
import com.litoralregas.backend.acquisition.block.BlockPollingService;
import jakarta.annotation.PostConstruct;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.stereotype.Service;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicBoolean;
@Service
public class AcquisitionSchedulerService {
private final BlockPollingService blockPollingService;
private final AcquisitionSchedulerProperties properties;
private final TaskScheduler taskScheduler;
private final AcquisitionRuntimeStatus runtimeStatus = new AcquisitionRuntimeStatus();
private final AtomicBoolean polling = new AtomicBoolean(false);
public AcquisitionSchedulerService(
BlockPollingService blockPollingService,
AcquisitionSchedulerProperties properties,
TaskScheduler taskScheduler
) {
this.blockPollingService = blockPollingService;
this.properties = properties;
this.taskScheduler = taskScheduler;
}
@PostConstruct
public void startScheduler() {
if (!properties.isEnabled()) {
System.out.println("Acquisition scheduler disabled.");
return;
}
System.out.println("Starting acquisition scheduler.");
taskScheduler.scheduleWithFixedDelay(
this::safePoll,
properties.getFixedDelayMillis()
);
}
public AcquisitionRuntimeStatus getRuntimeStatus() {
return runtimeStatus;
}
private void safePoll() {
if (!polling.compareAndSet(false, true)) {
System.out.println("Skipping acquisition cycle because previous cycle is still running.");
return;
}
runtimeStatus.setRunning(true);
runtimeStatus.setLastStartedAt(Instant.now());
runtimeStatus.setLastError(null);
try {
AcquisitionPollResult result = blockPollingService.pollOnceByBlocks();
runtimeStatus.setLastSuccessfulReads(result.successfulReads());
runtimeStatus.setLastFailedReads(result.failedReads());
} catch (Exception exception) {
runtimeStatus.setLastError(exception.getMessage());
exception.printStackTrace();
} finally {
runtimeStatus.setRunning(false);
runtimeStatus.setLastFinishedAt(Instant.now());
polling.set(false);
}
}
}
+5 -1
View File
@@ -21,4 +21,8 @@ litoralregas:
port: 533
timeout-millis: 500
max-attempts: 3
retry-delay-millis: 1000
retry-delay-millis: 1000
acquisition:
scheduler:
enabled: true
fixed-delay-millis: 3000