Skip to content

💡 [Feature Request] Allow BotSession to accept either ScheduledExecutorService or TaskScheduler for scheduling #1562

@yvasyliev

Description

@yvasyliev

Is your feature request related to a problem? Please describe.
I use telegrambots-spring-boot-starter to build Telegram bots and it feels odd that under the hood the library uses JDK's ScheduledExecutorService instead of Spring's TaskScheduler for scheduling.

Unlike ScheduledExecutorService, TaskScheduler is a managed bean created by Spring Boot automatically. And if I want to make ScheduledExecutorService manageable, I need to register a bean manually since TaskScheduler and ScheduledExecutorService are not interchangeable. This is not what I'm expecting from a *starter library.

Describe the solution you'd like
I would expect telegrambots-longpolling to introduce an interface like:

@FunctionalInterface
public interface TelegramLongPollingBotScheduler {
    ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long initialDelay, long period, TimeUnit unit);
}

with the default implementation:

@RequiredArgsConstructor
public class DefaultTelegramLongPollingBotScheduler implements TelegramLongPollingBotScheduler {
    private final ScheduledExecutorService executorService;

    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long initialDelay, long period, TimeUnit unit) {
        return executorService.scheduleAtFixedRate(task, initialDelay, period, unit);
    }
}

Then we would refer to TelegramLongPollingBotScheduler instead of ScheduledExecutorService among the code.

Finally, I would expect telegrambots-spring-boot-starter to introduce another implementation and use it as default:

@RequiredArgsConstructor
public class SpringTelegramLongPollingBotScheduler implements TelegramLongPollingBotScheduler {
    private final TaskScheduler taskScheduler;

    @Override
    public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long initialDelay, long period, TimeUnit unit) {
        var chronoUnit = unit.toChronoUnit();
        var startTime = Instant.now().plus(initialDelay, chronoUnit);
        var period = Duration.of(period, chronoUnit);

        return taskScheduler.scheduleAtFixedRate(task, startTime, period);
    }
}

This way, Spring-based apps can use autoconfigured TaskScheduler for scheduling, and non-Spring apps can either use vanilla ScheduledExecutorService or even provide own implementations of TelegramLongPollingBotScheduler!

Describe alternatives you've considered
Technically it's possible to adapt TaskScheduler interface to ScheduledExecutorService directly using delegate pattern, however it wouldn't be as smooth as dedicated TelegramLongPollingBotScheduler interface, since we need a single method only for scheduling.

Additional context

  1. TelegramLongPollingBotScheduler could resolve a part of telegrambots-springboot-longpolling-starter: Java process never stops after SpringApplication.exit is called #1513 discussion.
  2. I can contribute to this change if the maintainers are fine with it.
  3. Another question I have: why do we need an initial delay and a period of 1 microsecond? Couldn't while (running) {} be enough?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions