1

ファイルシステムの変更について特定のディレクトリを監視する状況があります。そのディレクトリ内の特定のファイルが変更された場合、それを再度読み取り、既存のキャッシュされた情報をいくつか添付して、atom.

関連するコードは次のようになります

(def posts (atom []))

(defn load-posts! []
  (swap!
   posts
   (fn [old]
     (vec
      (map #(let [raw (json/parse-string % (fn [k] (keyword (.toLowerCase k))))]
              (<snip some processing of raw, including getting some pieces from old>))
           (line-seq (io/reader "watched.json")))))))


;; elsewhere, inside of -main
(watch/start-watch
    [{:path "resources/"
      :event-types [:modify]
      :callback (fn [event filename]
                  (when (and (= :modify event) (= "watched.json" filename))
                    (println "Reloading posts.json ...")
                    (posts/load-posts!)))}
     ...])

これは最終的にローカルで正常に機能しますが、サーバーに展開すると、swap!呼び出しが途中でハングします。

を介してデバッグしようとしましたがprintln、それは私に言いました

  1. ファイルシステム トリガー起動されています。
  2. swap!関数を複数回実行していない
  3. 監視対象のファイルが開かれ、解析されています
  4. ファイルのいくつかのエントリが処理されていますが、その処理はエントリで停止します111(前のエントリと大きく異なるようには見えません)。
  5. 更新は完了しないため、その古い値がatom保持されます
  6. このイベントがハングした後、ファイルシステム イベントは発生しません。

これは、どこかのメモリの問題か、Clojure-Watch (または基礎となる FS-watching ライブラリ) のバグであると思われます。

それを修正したり、さらに診断したりする方法はありますか?

4

1 に答える 1

1

:callbackハングは、 toとして渡された関数内でスローされるエラーによって発生しますwatch/start

この場合の根本的な原因は、変更されたファイルがによってサーバーにコピーされていることですscp(これはアトミックではないため、コピーが完了する前に最初のイベントがトリガーされ、JSON 解析エラーがスローされる原因になります)。

これは、何らかの種類のエラーがスローされたwatch/start場合に黙って失敗するという事実によって悪化します。:callback

ここでの解決策は

  1. rsyncファイルのコピーに使用します。アトミックにコピーします、ターゲット ファイルではイベントを生成せず:modify、関連する一時ファイルのみを生成します。そのアトミック コピーの動作方法により、イベントの通知のみ:createが行われます。

  2. :callbacktry/catchで囲み、catch句でアトムの古い値を返すようにします。これによりload-posts!、複数回実行されますが、最後はファイル コピーの完了時であり、最終的に正しいことを行うはずです。

(私は両方を行いましたが、どちらかが問題を現実的に解決したでしょう)。

3 番目のオプションは、 Hawkdirwatchなどのエラーを報告する FS 監視ライブラリを使用することです(または、おそらくhara.io.watch ? 私はこれらのいずれも使用していないため、コメントできません)。

これを診断するには、:callback体を

(try 
  <body> 
  (catch Exception e 
    (println "ERROR IN SWAP!" e) 
    old))

実際に投げられたものを見るために。JSON 解析エラーが表示されると、何が問題なのかを推測するのは非常に簡単でした。

于 2016-09-08T19:12:41.370 に答える