【问题标题】:Is there a way to invoke an Action without sending a request?有没有办法在不发送请求的情况下调用动作?
【发布时间】:2020-07-22 21:31:24
【问题描述】:

我有一个提供一些 api 的 Play2 应用程序。 在同一个应用程序中,我添加了运行基于 Alpakka 的 etl 的代码。在 etl 引擎盖下,有一个 Future[Done] 在运行,永无止境。目前,我在单独的路由上使用 Web 请求触发 etl 进程。 为了部署我的 etl 服务,我希望能够使用一个特殊的命令来运行我的 Play2 应用程序,该命令理想情况下不会打开服务器,而只是运行 etl 控制器的单个动作。如果无法实现并且必须打开服务器,我想触发该 etl 进程,但将我的 etl 框与传入的 Web 连接隔离。我觉得所有这些都非常hackish,可能有更好的方法。

【问题讨论】:

  • 我认为最好的方法是提取运行实际工作的代码并让您的操作只是调用它。比构建一个单独的应用程序入口点(基本上是Main 类)来实现命令行界面。
  • 但我依靠 Play 框架依赖注入将我的 etl 连接在一起。
  • Play 的默认 DI engine is Guice,因此您需要自己实例化 DI 容器(例如,通过查看 play 的源代码并无耻地复制粘贴 :)),但这是可行的。你可能想重新审视你的设计决策:) Play 是一个网络应用程序框架,所以如果你想让它对网络“封闭”运行,你可能误用了它。具体来说,“将我的 etl 框与传入的网络连接隔离”超出了 Play 可以/应该做的事情 - 这在网络配置或防火墙级别更容易做到。

标签: scala playframework etl devops


【解决方案1】:

我最终的做法是使用scheduled tasks

一个任务可以安排一次,具体取决于配置变量:

class ProtonConnector @Inject()(
    config: TypeSafeConfig,
)(
    implicit actorSystem: ActorSystem
) {

  // Run the stream
  def listen: Future[Done] =
    itemsProtonSource.via(mapFlow).via(solrIndexFlow).runWith(Sink.ignore)

  // Schedule ETL execution
  if (config.scheduleProtonEtlTask) {
    actorSystem.scheduler.scheduleOnce(delay = 1.seconds) {
      logger.debug("Executing proton ETL task...")
      val _ = listen
    }
  }
}

然后我们从environment variable 中提取config.scheduleProtonEtlTask(其值设置为true,因此if 中的代码块将执行)。 然后在我们的 CI/CD 管道中,我们定义了一个新的部署,这个环境变量将由任务配置提供。该部署也可能与外部世界隔离 - 这样,Play2 仍会启动服务器,但无法从本地网络外部访问。

【讨论】:

    猜你喜欢
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-06
    • 1970-01-01
    • 2017-09-15
    • 2010-10-02
    相关资源
    最近更新 更多