Util to put data into a temporary file and schedule it for deletion after a specified time period. Currently used to store card's rows data when sending notification since it can be large and we don't want to keep it in memory. | (ns metabase.notification.payload.temp-storage (:require [clojure.java.io :as io] [metabase.util.random :as random] [taoensso.nippy :as nippy]) (:import (java.io File) (java.util.concurrent Executors ScheduledThreadPoolExecutor TimeUnit))) |
(set! *warn-on-reflection* true) | |
(def ^:private temp-file-lifetime-seconds (* 5 60)) | |
(def ^:private temp-dir (delay (let [dir (io/file (System/getProperty "java.io.tmpdir") (str "metabase-notification-" (random/random-name)))] (.mkdirs dir) (.deleteOnExit dir) dir))) | |
(def ^:private deletion-scheduler (delay (Executors/newScheduledThreadPool 1))) | |
Schedule file for deletion after specified seconds. | (defn- schedule-deletion! [^File file seconds] (.schedule ^ScheduledThreadPoolExecutor @deletion-scheduler ^Callable (fn [] (when (.exists file) (io/delete-file file true))) ^Long seconds TimeUnit/SECONDS)) |
(defn- temp-file [] (doto (File/createTempFile "notification-" ".npy" @temp-dir) (.deleteOnExit))) | |
(defn- write-to-file [^File file data] (nippy/freeze-to-file file data)) | |
(defn- read-from-file [^File file] (when (.exists file) (nippy/thaw-from-file file))) | |
(.addShutdownHook (Runtime/getRuntime) (Thread. ^Runnable (fn [] (when @deletion-scheduler (.shutdown ^ScheduledThreadPoolExecutor @deletion-scheduler))))) | |
------------------------------------------------------------------------------------------------;; Public APIs ;; ------------------------------------------------------------------------------------------------;; | |
Write data to a temporary file and schedule it for deletion after a specified time period. The file will be automatically deleted after the given number of seconds. Returns a derefable object that, when dereferenced, reads and returns the data from the temporary file. Arguments: data - The data to write to the temporary file seconds - Optional. Number of seconds before file deletion (default: is [[temp-file-lifetime-seconds]]) | (defn to-temp-file! ([data] (to-temp-file! data temp-file-lifetime-seconds)) ([data seconds] (let [f (temp-file)] (schedule-deletion! f seconds) (write-to-file f data) (reify clojure.lang.IDeref (deref [_] (read-from-file f)))))) |