package com.ruoyi.shadow.kernel; import com.ruoyi.ft546.protocol.Ft546EncodedCommand; import com.ruoyi.ft546.protocol.Ft546SrgvCommandIntent; import com.ruoyi.shadow.facts.ShadowFactBatch; import com.ruoyi.shadow.facts.ShadowFactBatchValidator; import com.ruoyi.shadow.facts.ShadowFactValidation; import com.ruoyi.wcs.application.ReadOnlyDispatchCycle; import com.ruoyi.wcs.application.ShadowDispatchResult; import com.ruoyi.wcs.application.dispatch.DispatchSnapshot; import java.time.Instant; import java.util.List; import java.util.Objects; import java.util.function.Function; public final class Ft546ShadowCycle { private final ShadowFactBatchValidator validator; private final Function assembler; private final ReadOnlyDispatchCycle dispatchCycle; private final RecordingFt546CommandGateway commandGateway; public Ft546ShadowCycle( ShadowFactBatchValidator validator, Function assembler, ReadOnlyDispatchCycle dispatchCycle, RecordingFt546CommandGateway commandGateway) { this.validator = Objects.requireNonNull(validator, "validator"); this.assembler = Objects.requireNonNull(assembler, "assembler"); this.dispatchCycle = Objects.requireNonNull(dispatchCycle, "dispatchCycle"); this.commandGateway = Objects.requireNonNull(commandGateway, "commandGateway"); } public ShadowCycleResult run(ShadowFactBatch batch, Instant now) { ShadowFactValidation validation = validator.validate(batch, now); if (validation.getStatus() != ShadowFactValidation.Status.COMPARABLE) { return ShadowCycleResult.insufficient(validation.getReasonCode()); } final DispatchSnapshot snapshot; try { snapshot = assembler.apply(batch); } catch (RuntimeException failure) { return ShadowCycleResult.insufficient( "INVALID_KERNEL_FACTS:" + message(failure)); } ShadowDispatchResult result; try { result = dispatchCycle.run(snapshot); } catch (IllegalArgumentException failure) { return ShadowCycleResult.insufficient( "INVALID_COMMAND_FACTS:" + message(failure)); } if (result.getDecisions().isRetrySnapshotChanged()) { return ShadowCycleResult.retry(result.getDecisions()); } final List encoded; try { encoded = commandGateway.recordAll(result.getIntents()); } catch (RuntimeException failure) { return ShadowCycleResult.insufficient( "INVALID_COMMAND_FACTS:" + message(failure)); } return ShadowCycleResult.comparable(result.getDecisions(), result.getIntents(), encoded); } private static String message(RuntimeException failure) { String value = failure.getMessage(); return value == null || value.trim().isEmpty() ? failure.getClass().getSimpleName() : value.trim(); } }