Загрузка данных
Добавляем метаданные в 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.