Play Frameworkのauto-reloadingは、Vagrantのsynced folderで効かなかった

VagrantのUbuntu環境で、Play Frameworkを使ったアプリの開発をしたいと思い試しています。

Playはソースコードが更新されると、自動的にコンパイルが走ってくれるauto-reloadingという機能が便利です。この機能をVagrantで試していて気がついたのですが、どうやら共有フォルダにあるソースコードは更新されてても、自動でコンパイルがかからないようです。controllersもviewsもどちらも変更してみましたが、やはりだめです。

そんなことはないんじゃないか？と思い、共有フォルダではないフォルダで試してみたら、ちゃんとreloadされていたので、原因は共有フォルダにあることが分かりました。


## PlayKeys.playWatchServiceを試す → ダメ

いろいろググっていたら「[Play 2.3.2 auto reload is not working on shared folder · Issue #3246 · playframework/playframework](https://github.com/playframework/playframework/issues/3246#issuecomment-51017410)」というissueを見つけました。

PlayはOSレベルの機能でファイルの変更を検知しているとのことで、NFSなどはOSが対応していないので検知できないそうです。ここで提案されていた解決策は、次のコードを`build.sbt`に書くことです。

```
PlayKeys.playWatchService := play.sbtplugin.run.PlayWatchService.sbt(pollInterval.value)
```

これを追加すると500msの間隔で、ファイルをポーリングして検知できるようになるそうです。

これをbuild.sbtの最後にコピペして、念のためactivatorを終了して起動しなおし、activatorのコンソールで`run`を実行しました。が、やはり更新を検出できないようです。

## NFSにしてみる

さきほどのissueにリンクしているissue「[Play 2.3.x not detecting changes to static resources in shared folder · Issue #4208 · playframework/playframework](https://github.com/playframework/playframework/issues/4208)」に気づきました。こちらの課題を報告している方が、Vagrantの共有フォルダの設定がNFSで解決したそうなので、NFSにしてみます。

Vagrantfileに次を追記して

```rb:Vagrantfile
  config.vm.synced_folder ".", "/vagrant", type: "nfs"
```

Vagrantを起動しなおします。

```
vagrant reload
```

ちなみに、Vagrantfile全体としてはこんなふうになっています。

```ruby:Vagrantfile
# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "shouldbee/ubuntu-14.04-with-docker"
  config.vm.box_version = "0.5"
  config.vm.synced_folder ".", "/vagrant", type: "nfs"

  host = RbConfig::CONFIG['host_os']

  case host
  when /darwin/ # mac
    cpus = `sysctl -n hw.ncpu`.to_i
  when /linux/
    cpus = `nproc`.to_i
  else
    cpus = 2
  end

  config.vm.provider "vmware_fusion" do |v|
    v.vmx["memsize"] = "512"
    v.vmx["numvcpus"] = cpus
  end
end

```

起動したら、activatorを実行して、

```
vagrant ssh
./activator
run
```

ソースコードを変更してみます。が、だめでした。


Vagrantの共有フォルダの設定を変更してみます。

```rb
  config.vm.synced_folder ".", "/vagrant", type: "nfs", mount_options: ["lookupcache=none"]
```

Vagrantを再起動して、試します。

```
vagrant reload
vagrant ssh
./activator
run
```

やはり、ソースコードを更新しても検知されませんでした。


## `~run` → 遅い

今度はPlayのauto-reloadingを使うのは諦めて、`~run`してみることにしました。そうしたところ、コンパイルは自動的に行われるようになりましたが、Playで起動しているサーバには反映されないようで、一旦`Ctrl+D`を押してはじめてサーバが再起動して反映されるようでした。これでも、使えないことはないですが、`Ctrl+D`を押さないと行けないのと、起動の処理自体に5〜10秒かかるが繰り返しになってくるとストレスになりそうです。

## 情報求む

うまい解決策があれば教えてもられると嬉しいです :bow: 

---------------------------------------

[2015-05-25]追記

## rsyncを試してみた

Vagrantのrsyncファイル共有機能を使って、Playのプロジェクトを同期するのを試してみました。Vagrantfileには同期したいプロジェクトの指定します。

```rb:Vagrantfile
  config.vm.synced_folder ".", "/new-ui", type: "rsync",
    rsync__exclude: [
      "/.idea/",
      "/.idea_modules/",
      "/project/project/",
      "/project/target/",
      "/target/",
    ]
```

これを設定したら、`vagrant reload`で再起動します。その後、同期が常に行われるように、もうひとつターミナルを開いて`vagrant rsync-auto`を実行しておきます。

rsyncなら普通のファイルシステムにソースコードを配置できるので、予想通りPlayのauto-reloadingが動きました。が、VMの性能の壁があり、僕の環境では、ホストマシンのMacでは1秒程度でリロードが終わるのに対して、rsync先のゲストマシンでは20〜30秒程度かかってしまうようです。