FAQ

[Compojure] how to (most efficiently?) serve a static file after compojure app decides to do so

Don Jackson
Feb 18, 2012 at 1:14 am
Here is my scenario:

Information needed by the first page of my application is very complex to compute, so the user has to wait seconds. I want to do better.

Let's say I can pre-compute a reasonable version of each user's data beforehand/every night, and I could stick this info in files somewhere (one file/user).

Now when the user hits the app, the server checks to see if a suitable precomputed version is available. If so, the server wants to return the data
to the requestor.

Obviously my app could go read that file and then use that info to generate the response.

How could I do better than this?

My preliminary investigation uncovered the "sendfile" facility that some web servers provide.

http://wiki.nginx.org/XSendfile
http://wiki.nginx.org/JavaServers
http://blog.lighttpd.net/articles/2006/07/02/x-sendfile
http://tomcat.apache.org/tomcat-6.0-doc/aio.html

This seems like it might be what I should do.

Before I head down that road, are there simpler alternatives?
Can I make jetty do this for me somehow? (without nginx….)





--
You received this message because you are subscribed to the Google Groups "Compojure" group.
To post to this group, send email to compojure@googlegroups.com.
To unsubscribe from this group, send email to compojure+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/compojure?hl=en.
reply

Search Discussions

2 responses

  • James Reeves at Feb 18, 2012 at 2:13 am

    On 18 February 2012 01:13, Don Jackson wrote:
    Information needed by the first page of my application is very complex to compute,  so the user has to wait seconds.  I want to do better.

    Let's say I can pre-compute a reasonable version of each user's data beforehand/every night, and I could stick this info in files somewhere (one file/user).

    Now when the user hits the app, the server checks to see if a suitable precomputed version is available.  If so, the server wants to return the data
    to the requestor.
    A naive version of this is pretty straightforward:

    (ns example.app
    (:import org.apache.commons.codec.digest.DigestUtils)
    (:require [clojure.java.io :as io]))

    (defn- find-cache-file [args]
    (io/file
    "/path/to/file/cache"
    (DigestUtils/shaHex (pr-str args))))

    (defn file-cache [func]
    (fn [& args]
    (let [file (find-cache-file args)]
    (if (.exists file)
    file
    (let [response (apply func args)]
    (spit file response)
    response)))))

    (def cached-complex-function
    (file-cache complex-function))

    Then you can just use cached-complex-function in place of
    complex-function. If the function has been called before with those
    arguments, a java.io.File object is returned, which Compojure serves
    up as a static file. Otherwise the response is found and saved in a
    file before being returned.

    Cache expiry, i.e. clearing up old files to save space, is something
    that probably needs to be added to make sure you don't run out of disk
    space.

    - James

    --
    You received this message because you are subscribed to the Google Groups "Compojure" group.
    To post to this group, send email to compojure@googlegroups.com.
    To unsubscribe from this group, send email to compojure+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/compojure?hl=en.
  • Don Jackson at Feb 19, 2012 at 7:58 am
    This worked great, thank you, James!
    On Feb 17, 2012, at 6:12 PM, James Reeves wrote:

    On 18 February 2012 01:13, Don Jackson
    wrote:
    Information needed by the first page of my application is very complex to compute, so the user has to wait seconds. I want to do better.

    Let's say I can pre-compute a reasonable version of each user's data beforehand/every night, and I could stick this info in files somewhere (one file/user).

    Now when the user hits the app, the server checks to see if a suitable precomputed version is available. If so, the server wants to return the data
    to the requestor.
    A naive version of this is pretty straightforward:

    (ns example.app
    (:import org.apache.commons.codec.digest.DigestUtils)
    (:require [clojure.java.io :as io]))

    (defn- find-cache-file [args]
    (io/file
    "/path/to/file/cache"
    (DigestUtils/shaHex (pr-str args))))

    (defn file-cache [func]
    (fn [& args]
    (let [file (find-cache-file args)]
    (if (.exists file)
    file
    (let [response (apply func args)]
    (spit file response)
    response)))))

    (def cached-complex-function
    (file-cache complex-function))

    Then you can just use cached-complex-function in place of
    complex-function. If the function has been called before with those
    arguments, a java.io.File object is returned, which Compojure serves
    up as a static file. Otherwise the response is found and saved in a
    file before being returned.

    Cache expiry, i.e. clearing up old files to save space, is something
    that probably needs to be added to make sure you don't run out of disk
    space.

    - James

    --
    You received this message because you are subscribed to the Google Groups "Compojure" group.
    To post to this group, send email to compojure@googlegroups.com.
    To unsubscribe from this group, send email to compojure+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/compojure?hl=en.
    --
    You received this message because you are subscribed to the Google Groups "Compojure" group.
    To post to this group, send email to compojure@googlegroups.com.
    To unsubscribe from this group, send email to compojure+unsubscribe@googlegroups.com.
    For more options, visit this group at http://groups.google.com/group/compojure?hl=en.

Related Discussions

Discussion Navigation
viewthread | post

2 users in discussion

Don Jackson: 2 posts James Reeves: 1 post