///|
/// The graceful-shutdown gate a serving zRPC server drains through: before
/// shutdown, calls dispatch normally and count as in-flight; once shutdown is
/// initiated new calls come back Unavailable while in-flight ones run to
/// completion, and `is_drained` reports when the last one has finished.
///
///     moon run src/examples/09-shutdown
#coverage.skip
fn main {
  let rpc = @moonzero.RpcServer::new(
    @moonzero.RpcServerConf::new(name="greeter"),
  )
  rpc.group("hello.Greeter").register("SayHello", req => req)
  let coord = @moonzero.ShutdownCoordinator::new()

  // While serving, a graceful dispatch runs the handler and returns Ok.
  println(
    "serving dispatch -> " +
    result(
      rpc.dispatch_graceful(
        coord,
        "/hello.Greeter/SayHello",
        @utf8.encode("emm"),
      ),
    ),
  )
  println(
    "  shutting_down=" +
    coord.is_shutting_down().to_string() +
    " in_flight=" +
    coord.in_flight().to_string(),
  )

  // The bracket a running call holds: begin_call registers it in-flight.
  let admitted = coord.begin_call()
  println(
    "mid-flight call admitted=" +
    admitted.to_string() +
    " in_flight=" +
    coord.in_flight().to_string() +
    " drained=" +
    coord.is_drained().to_string(),
  )

  // Shutdown begins: new calls are refused Unavailable, the in-flight one is not.
  coord.initiate_shutdown()
  println(
    "after initiate_shutdown, new dispatch -> " +
    result(
      rpc.dispatch_graceful(coord, "/hello.Greeter/SayHello", @utf8.encode("x")),
    ),
  )
  println("  still draining, drained=" + coord.is_drained().to_string())

  // The last in-flight call finishes and the server is fully drained.
  coord.end_call()
  println(
    "last call ended, in_flight=" +
    coord.in_flight().to_string() +
    " drained=" +
    coord.is_drained().to_string(),
  )
}

///|
fn result(r : Result[Bytes, @moonrpc.Status]) -> String {
  match r {
    Ok(b) => "ok(" + @utf8.decode_lossy(b[:]) + ")"
    Err(s) => "err(" + s.name() + ")"
  }
}