Skip to content

Instantly share code, notes, and snippets.

@mfikes
Created September 9, 2018 15:28
Show Gist options
  • Save mfikes/03172ce8dd62439431026b7b94ec201f to your computer and use it in GitHub Desktop.
Save mfikes/03172ce8dd62439431026b7b94ec201f to your computer and use it in GitHub Desktop.
Async file io in Clojure
(ns api-server.file-io
(:use [clojure.tools.logging :only (info warn error)])
(:import (java.nio.channels CompletionHandler AsynchronousFileChannel)
(java.nio ByteBuffer)
(java.nio.file.attribute FileAttribute)
(java.nio.file StandardOpenOption)
(java.util.concurrent Executors))
(:require [clojure.core.async :as async :refer [chan go put! close!]]
[clojure.java.io :as io]))
(def asynch-file-executor (Executors/newFixedThreadPool 8))
(defn file-exits!?
[file]
(.exists (io/as-file file)))
(defn- file-uri
[file]
(.toURI (io/as-file file)))
(defn read-file!
[file]
(let [ch (chan)
path (java.nio.file.Paths/get (file-uri file))
fileChannel (AsynchronousFileChannel/open path #{StandardOpenOption/READ} asynch-file-executor (make-array FileAttribute 0))
buffer (ByteBuffer/allocate (.size fileChannel))]
(.read fileChannel buffer 0 nil
(proxy [CompletionHandler] []
(completed [result attachment]
(.close fileChannel)
(.flip buffer)
(put! ch buffer))
(failed [e attachment]
(.close fileChannel)
(put! ch e))))
ch))
(defn write-file!
[file buffer]
(let [ch (chan)]
(try
(let [path (java.nio.file.Paths/get (file-uri file))
fileChannel (AsynchronousFileChannel/open path #{StandardOpenOption/WRITE} asynch-file-executor (make-array FileAttribute 0))]
(.write fileChannel buffer 0 nil
(proxy [CompletionHandler] []
(completed [result attachment]
(.close fileChannel)
(close! ch))
(failed [e attachment]
(.close fileChannel)
(put! ch e)))))
(catch Throwable t
(warn t "Failed writing file" file)
(put! ch t)))
ch))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment