Disclaimer: This is just an educational task to learn how to program in clojure and switch brain to immutable state-way of developing (the provided snipped has some unused variables which I didn't clean up since they will be used soon and are easy to understand).
The current milestone: to implement a solution that reads all lines from a file, if reaching file end - sleep and reopen a file, then continue trying reading the file from the same place.
This code is ugly without doubts. What makes me worrying is that it uses recursion in an ugly manner to maintain state. I think my next iteration will be to try using atoms to maintain mutable state instead of recursions, but not sure yet if it will be any better.
main function currently for testing purposes just reads 3 lines from the channel.
(ns log-multiline-join.tailer (:use [clojure.core.async :only (>!! >! <!! thread chan timeout alt!)]) (:import [java.io RandomAccessFile]) (:gen-class)) (defn create-rac [filename] (RandomAccessFile. filename "r")) (defn read-lines [rac position out stop] (.seek rac position) (if-let [line (.readLine rac)] (do (>!! out line) (recur rac (.getFilePointer rac) out stop)) (.getFilePointer rac))) (defn read-file-recur [filename position out] (let [rac (create-rac filename) position (read-lines rac position out 2)] (println "sleep") (Thread/sleep 1000) (recur filename position out))) (defn tailer [filename out] (read-file-recur filename 0 out)) (defn -main  (let [out (chan)] (thread (tailer "/tmp/file" out)) (println (<!! out)) (println (<!! out)) (println (<!! out)) ))
UPD: this is the latest revision for the same code, it looks a bit better I suppose: https://www.refheap.com/93412