Поток данных Spring Cloud: слишком длинное значение для столбца TASK_NAME (DeployerPartitionHandler с пакетом Spring)

У меня есть простое пакетное задание Spring, в котором Kubernetes работает как облачная задача Spring. Это задание использует Spring Batch Partitioning для дальнейшего запуска разделенных шагов в качестве модулей задач в том же кластере Kubernetes.

Основная работа: (соответствующие части)

@Bean
public Job mainControllerJob() {
    LOGGER.info("Creating mainControllerJobbean...");
    return jobBuilderFactory.get("mainControllerJob").incrementer(new RunIdIncrementer())
                .start(testStep(null, null, null)).build();
}

@Bean
public Step testStep(StepBuilderFactory stepBuilderFactory,
        @Qualifier("testPartitioner") Partitioner partitioner, PartitionHandler partitionHandler) {
    LOGGER.info("Creating testStep");
    return stepBuilderFactory.get("testStep")
            .partitioner("testWorkerStep", partitioner).partitionHandler(partitionHandler).build();
}

@Bean
public DeployerPartitionHandler partitionHandler(@Value("${test.partion.app}") String resourceLocation,
        @Value("${test.application.name}") String applicationName, ApplicationContext context,
        TaskLauncher taskLauncher, JobExplorer jobExplorer, DockerResourceLoader dockerResourceLoader) {
    Resource resource = dockerResourceLoader.getResource(resourceLocation);
    DeployerPartitionHandler partitionHandler = new DeployerPartitionHandler(taskLauncher, jobExplorer, resource,
            "testWorkerStep", taskRepository);

    List<String> commandLineArgs = new ArrayList<>();
    commandLineArgs.add("--spring.cloud.task.initialize.enable=false");
    commandLineArgs.add("--spring.batch.initializer.enabled=false");

    commandLineArgs.addAll(Arrays.stream(applicationArguments.getSourceArgs()).filter(
            x -> !x.startsWith("--spring.profiles.active=") && !x.startsWith("--spring.cloud.task.executionid="))
            .collect(Collectors.toList()));
    commandLineArgs.addAll(applicationArguments.getNonOptionArgs());

    partitionHandler.setCommandLineArgsProvider(new PassThroughCommandLineArgsProvider(commandLineArgs));
    partitionHandler.setEnvironmentVariablesProvider(new NoOpEnvironmentVariablesProvider());
    partitionHandler.setMaxWorkers(maxWorkers);
    partitionHandler.setGridSize(gridSize);
    partitionHandler.setApplicationName(applicationName);

    return partitionHandler;
}

Когда дочерний шаг (модуль задач) запускается на k8 указанным выше заданием, я вижу следующее исключение для дочернего шага:

 org.springframework.context.ApplicationContextException: Failed to start bean 'taskLifecycleListener'; nested exception is org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [UPDATE TASK_EXECUTION set START_TIME = ?, TASK_NAME = ?, LAST_UPDATED = ?, PARENT_EXECUTION_ID = ? where TASK_EXECUTION_ID = ?]; 
Value too long for column """TASK_NAME"" VARCHAR(100)": "'test-app,test-app_testJob_testWorkerStep:partition5800' (106)"; 
SQL statement:
    UPDATE TASK_EXECUTION set START_TIME = ?, TASK_NAME = ?, LAST_UPDATED = ?, PARENT_EXECUTION_ID = ? where TASK_EXECUTION_ID = ? [22001-199]; nested exception is org.h2.jdbc.JdbcSQLDataException: Value too long for column """TASK_NAME"" VARCHAR(100)"

Ошибка очевидна. Мне нужно как-то сократить имя шага дочернего раздела, чтобы оно соответствовало ширине столбца внутренней таблицы TASK_EXECUTION.

Я хочу понять, как я могу самостоятельно изменить имя шага дочернего раздела, запущенного с помощью пакетного задания Spring?

Я примерно понимаю, что имя шага создается SimpleStepExecutionSplitter. Однако я не вижу способа изменить это поведение программно. Как я могу изменить имя дочернего шага, а также убедиться, что я делаю это таким образом, чтобы это не повлияло на возможность перезапуска моих заданий / шагов.


person Ping    schedule 17.06.2021    source источник


Ответы (1)


Имя рабочего шага представляет собой объединение имени шага и имени раздела (с разделителем между ними). Имена разделов можно настроить с помощью PartitionNameProvider. Поэтому, если вы хотите контролировать, как генерируются имена разделов, вам нужно сделать так, чтобы ваш Partitioner реализовал интерфейс PartitionNameProvider.

Другой вариант - увеличить размер столбца TASK_NAME.

person Mahmoud Ben Hassine    schedule 18.06.2021
comment
Я не понимал, как использовать интерфейс PartitionNameProvider (getPartitionNames(int gridSize)) - ›Означает ли это, что я должен возвращать список имен для всех моих разделов, где каждая позиция индекса представляет имя для этого номера раздела? Кроме того, я подумал об изменении размера столбца TASK_NAME, но не смог найти способ попросить сервер потока данных использовать мой собственный DDL. Я разместил вопрос в аналогичных строках: stackoverflow.com/questions/68023823/ - person Ping; 18.06.2021
comment
Да, вы должны вернуть имена своих разделов. Размер сетки - это то же значение, что и в Partitioner#partition(int gridSize), которое в основном представляет собой количество разделов (но это только подсказка, поскольку есть варианты использования, где он не используется, например, в MultiResourcePartitioner). - person Mahmoud Ben Hassine; 21.06.2021