Загрузка данных


Добавляем метаданные в State Machine
В Spring State Machine у каждого перехода (transition) есть поле metadata. Тебе нужно пометить «тестовые» переходы при настройке машины.
Пример в конфиге (EnumStateMachineConfigurerAdapter):
java
withExternal()
    .source(UserStatus.NEW)
    .target(UserStatus.TEST_STATUS)
    .event(UserEvents.START_TEST)
    .metadata("test-only", true); // Помечаем переход
Use code with caution.
2. Создаем RequestScope компонент для флага
Чтобы флаг test-mode можно было менять «на лету» (например, через заголовок запроса или просто брать из конфига), создадим бин:
java
@Component
@RequestScope
public class TestContext {
    @Value("${app.test-mode:false}") // Значение по умолчанию из yaml
    private boolean testMode;

    // Геттер и сеттер (сеттер пригодится, если захочешь включать режим через Header)
    public boolean isTestMode() { return testMode; }
}
Use code with caution.
3. Обновляем логику фильтрации
Теперь внедрим этот контекст в твой сервис и добавим фильтр в поток (Stream).
java
@Service
@RequiredArgsConstructor
public class EventService {

    private final TestContext testContext; // Наш RequestScope бин
    private final EnumMapper enumMapper;

    public List<AvailableEventResponse<UserEvents, UserStatus>> fetchAvailableEvents(final User user) {
        return buildStateMachine(user.getStatus())
            .getTransitions()
            .stream()
            .filter(t -> t.getSource().getId().equals(user.getStatus()))
            .filter(t -> t.getTrigger().getEvent().getTransitionType().equals(TransitionType.MANUAL))
            
            // --- НОВАЯ ЛОГИКА ТУТ ---
            .filter(t -> {
                // Извлекаем пометку из метаданных перехода
                Boolean isTestTransition = (Boolean) t.getMetadata().get("test-only");
                if (Boolean.TRUE.equals(isTestTransition)) {
                    // Если переход тестовый, показываем его только если testMode = true
                    return testContext.isTestMode();
                }
                return true; // Обычные переходы показываем всегда
            })
            // ------------------------
            
            .filter(t -> isTransitionAllowed(t, user))
            .map(t -> new AvailableEventResponse<>(
                enumMapper.toResponse(t.getTrigger().getEvent()),
                enumMapper.toResponse(t.getTarget().getId())))
            .distinct()
            .toList();
    }
}
Use code with caution.
Почему это круто:
Гибкость: Если ты изменишь app.test-mode в YAML и нажмешь /actuator/refresh, testContext при следующем запросе подтянет новое значение.
Изоляция: Если ты решишь сделать test-mode зависимым от пользователя (например, только для админов), ты просто поменяешь логику заполнения TestContext, а основной код метода fetchAvailableEvents не изменится.
Чистота: Логика "тестовости" отделена от логики прав доступа (isTransitionAllowed).
Вопрос: Хочешь добавить возможность включать test-mode через HTTP-заголовок (например, X-Test-Enabled: true), чтобы не менять конфиг во всем приложении?
AI responses may include mistakes. Learn more




мы должны добавить все переходы, у перехода с test-only тока если включен режим test mode
Понял, задача в том, чтобы всегда возвращать обычные переходы, а переходы с пометкой test-only добавлять в список только если включен флаг test-mode.
Вот как будет выглядеть обновленный фильтр в твоем коде:
java
public List<AvailableEventResponse<UserEvents, UserStatus>> fetchAvailableEvents(final User user) {

    return buildStateMachine(user.getStatus())
        .getTransitions()
        .stream()
        .filter(t -> t.getSource().getId().equals(user.getStatus()))
        .filter(t -> t.getTrigger().getEvent().getTransitionType().equals(TransitionType.MANUAL))
        
        // Логика фильтрации тестового режима:
        .filter(t -> {
            // Проверяем, есть ли у перехода метка test-only
            boolean isTestOnly = Boolean.TRUE.equals(t.getMetadata().get("test-only"));
            
            if (isTestOnly) {
                // Если переход тестовый, он проходит фильтр только если testMode включен
                return testContext.isTestMode();
            }
            // Если переход НЕ тестовый, он проходит всегда (согласно твоему условию)
            return true;
        })
        
        .filter(t -> isTransitionAllowed(t, user))
        .map(t -> new AvailableEventResponse<>(enumMapper.toResponse(t.getTrigger().getEvent()),
                                               enumMapper.toResponse(t.getTarget().getId())))
        .distinct()
        .toList();
}
Use code with caution.