我正在使用Scala中的命令行程序。一些命令将产生后台线程以执行一些工作。一些命令将产生线程,这些线程会以一些延迟重复运行相同的任务。我还需要一个停止命令来阻止现有的后台任务重复(不需要杀死它,只是在完成迭代后退出)。构建这种程序的最佳基元是什么?
我正在考虑使用Futures,例如下面。你们对这个设计有什么看法?你会如何实现这种功能?
case class OneTimeTaskCommand(arg: String)
case class StopTaskCommand(name: String)
case class RepeatingTaskCommand(name: String, delay: Long, arg: String)
def runOneTimeTask(arg: String): Unit = { ... }
def runRepeatingTaskCommand(arg: String): Unit = { ... }
trait Scheduler {
def schedule(name: String, delay: Long): Unit
def unschedule(name: String): Unit
def isScheduled(name: String): Boolean = repeatDelay(name).isDefined
def repeatDelay(name: String): Option[Long]
}
def runCommand(command)(implicit scheduler: Scheduler): Future[Unit] = {
command match {
case OneTimeTaskCommand(arg) => Future(runOneTimeTask(arg))
case StopTaskCommand(name) =>
if (scheduler.isScheduled(name)) {
scheduler.unschedule(name)
Future.successful(())
} else {
Future.failure(new CommandException(s"task $name is not running"))
}
case RepeatingTaskCommand(name, delay, arg) =>
/* function to generate repeating future */
def createFuture(): Future[Unit] = {
runRepeatingTaskCommand(arg)).flatMap { _ =>
scheduler.repeatDelay(name) match {
case Some(d) =>
Thread.sleep(d)
Future(createFuture())
case None =>
Future.successful(())
}
}
}
/* spin off repeating task */
if (scheduler.isScheduled(name)) {
Future.failure(new CommandException(s"task $name is already running"))
} else {
scheduler.schedule(name, delay)
createFuture()
}
}
}
上面的代码将集成到一些读取用户输入并调用以下一些调用的REPL中:
implicit val scheduler: Scheduler = new SchedulerImpl
runCommand(OneTimeTaskCommand(someArg))
// Run backgrounded task to be repeated every second
runCommand(RepeatingTaskCommand("backgrounded-task", 1000L, someArg))
// Stop backgrounded task
runCommand(StopTaskCommand("backgrounded-task"))