【问题标题】:ZIO watch file system eventsZIO 监视文件系统事件
【发布时间】:2020-12-14 07:06:37
【问题描述】:

帮助我如何在 ZIO 上组织目录扫描。这是我的版本,但它不会跟踪所有文件创建事件(错过一些事件)。

object Main extends App {

  val program = for {
    stream <- ZIO.succeed(waitEvents)
    _ <- stream.run(ZSink.foreach(k => putStrLn(k.map(e => (e.kind(), e.context())).mkString("\n"))))
  } yield ()

  val managedWatchService = ZManaged.make {
    for {
      watchService <- FileSystem.default.newWatchService
      path = Path("c:/temp")
      _ <- path.register(watchService,
        StandardWatchEventKinds.ENTRY_CREATE,
        StandardWatchEventKinds.ENTRY_DELETE
      )
    } yield watchService
  }(_.close.orDie)

  val lookKey = ZManaged.make {
    managedWatchService.use(watchService => watchService.take)
  }(_.reset)

  val waitEvents = ZStream.fromEffect {
    lookKey.use(key => key.pollEvents)
  }.repeat(Schedule.forever)

  override def run(args: List[String]): ZIO[zio.ZEnv, Nothing, ExitCode] =
    program
      .provideLayer(Console.live ++ Blocking.live ++ Clock.live)
      .exitCode
  
}

感谢您的建议。

【问题讨论】:

    标签: scala nio zio


    【解决方案1】:

    每次轮询事件时,您都会强制 WatchService 关闭并重新创建。由于这可能涉及某些系统句柄,因此它可能相当慢,因此您可能会丢失介于两者之间的文件事件。您更有可能希望生成一次WatchService,然后重复轮询它。我会建议这样的东西:

    object Main extends App {        
      val managedWatchService = ZManaged.make {
        for {
          watchService <- FileSystem.default.newWatchService
          path = Path("c:/temp")
          _ <- path.register(watchService,
            StandardWatchEventKinds.ENTRY_CREATE,
            StandardWatchEventKinds.ENTRY_DELETE
          )
        } yield watchService
      }(_.close.orDie)
          
      // Convert ZManaged[R, E, ZStream[R, E, A]] into ZStream[R, E, A]
      val waitEvents = ZStream.unwrapManaged(
        managedWatchService.mapM(_.take).map { key =>
          // Use simple effect composition instead of a managed for readability.
          ZStream.repeatEffect(key.pollEvents <* key.reset)
           // Optional: Flatten the `List` of values that is returned
           .flattenIterables
        }
      )
    
      val program = waitEvents
        .map(e => (e.kind(), e.context()).toString)
        .foreach(putStrLn).unit
    
      override def run(args: List[String]): ZIO[zio.ZEnv, Nothing, ExitCode] =
        program
          .provideLayer(Console.live ++ Blocking.live ++ Clock.live)
          .exitCode
      
    }
    

    另外,当你使用ZManaged 时,你可能不想这样做

    ZManaged.make(otherManaged.use(doSomething))(tearDown)
    

    因为你会导致终结器乱序执行。 ZManaged 已经可以通过正常的flatMap 组合来处理拆卸的顺序。

    otherManaged.flatMap { other => ZManaged.make(doSomething(other))(tearDown) }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多