Вы можете использовать оба, в зависимости от требований, которые у вас есть для вашего решения, которые там не перечислены. Общее беспокойство, которое вы должны принять во внимание - актеры более низкоуровневые вещи, чем потоки, поэтому они требуют больше кода и отладки.
По сути, потоки хороши для задач, где у вас есть относительно большой объем данных, которые необходимо обработать с низким потреблением памяти. С потоками вам не нужно начинать потоковую передачу каждые n
секунды, вы можете настроить этот поток для запуска вместе с приложением. Это может сделать ваш код более лаконичным, пропустив планировщик logi c. Я опущу ваш DI и архитектуру, напишу решение с псевдокодом:
val yourConsumer: Sink[YourDBRecord] = ???
val recordsSource: Source[YourDBRecord] =
val runnableGraph = (Source repeat ())
.throttle(1, n seconds)
.mapAsync(yourParallelism){_ =>
fetchReasonableAmountOfRecordsFromDB
} mapConcat identity to yourConsumer
Этот поток сделает ваши вещи. Вы даже можете улучшить его с помощью более сложной логики c, чтобы адаптировать частоту опроса в соответствии с рабочими нагрузками, используя обратную связь l oop в графе api. Кроме того, вы можете добавить стратегию обработки ошибок, которую необходимо возобновить, в случае сбоя потока.
Более того, есть соединители alpakka для DBS, которые способны на это, вы можете увидеть, соответствуют ли решения там, где вы хотите, или проверить детали реализации.
Что вы можете получить, сделав это - противодавление, способность работать с потоками, чистым и лаконичным кодом без синхронизированных автоматов, управляемых непосредственно вами. https://doc.akka.io/docs/akka/current/stream/stream-rate.html
Вы также можете создать актера, но тогда вы должны делать все то, что потоки akka делают для вас вручную, то есть обратное давление в случае, если вы хотите взаимодействовать с потоками , планировщик, чанкинг и управление памятью (чтобы не загружать 100000 или около того записей в одном пакете в память), et c.