Last active
August 29, 2015 14:07
-
-
Save friemen/193117e93a3d6ced6654 to your computer and use it in GitHub Desktop.
Web Service Integration based on core.async
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns servint.core | |
(:require [org.httpkit.server :as server] | |
[org.httpkit.client :as client] | |
[clojure.core.async :as async :refer [go >! <!]] | |
[compojure.core :refer [defroutes GET]] | |
[compojure.route :as route] | |
[compojure.handler :as handler])) | |
;; A complete webapp that demonstrates how to asynchronously | |
;; query web services | |
(defn http-get | |
"Requests content from url in a non-blocking fashion, returning the | |
result on the specified channel." | |
[ch url] | |
(client/get url #(async/put! ch %)) | |
ch) | |
(defn collect-results | |
"Starts an async process that waits on the specified channel ch for | |
a maximum of max results, or until millis milliseconds have passed | |
by. Returns the process channel that will emit the collected results | |
in one vector." | |
[ch max millis] | |
(let [t-ch (async/timeout millis)] | |
(async/go-loop [results []] | |
;; loop and select via alts! from the channel ch or timeout | |
(let [[result source-ch] (async/alts! [ch t-ch])] | |
(if (= source-ch t-ch) | |
results ; this was a timeout | |
(let [results (conj results result)] ; regular result, append it | |
(if (= max (count results)) | |
results ; maximum reached, return | |
(recur results)))))))) ; recur again at go-loop | |
(defn get-contents | |
"Requests contents for the given seq of urls and returns channel that | |
will contain all responses in one vector." | |
[urls] | |
(let [ch (async/chan)] | |
(doseq [url urls] | |
(http-get ch url)) ; do an async request for each url, the result will go to ch | |
(collect-results ch (count urls) 200))) ; get the results from the channel ch | |
(defn main-page | |
[] | |
{:status 200 | |
:headers {"Content-Type" "text/html"} | |
:body "Hello Web World!"}) | |
(def urls ["http://fssnip.net/20" | |
"https://api.discogs.com/database/search?q=nirvana"]) | |
(defn collect-page | |
[] | |
{:status 200 | |
:body (str (count (async/<!! (get-contents urls))))}) | |
;; define the routing of requests | |
(defroutes app | |
(GET "/" [] | |
(main-page)) | |
(GET "/collect" [] | |
(collect-page)) | |
(route/not-found "Unknown resource.")) | |
;; --------------------------------------------------------------------------- | |
;; Setup HTTP server start! and stop! | |
(defonce http-server (atom nil)) | |
(defn stop! | |
"Stop server if running." | |
[] | |
(when @http-server | |
(@http-server :timeout 100) | |
(reset! http-server nil) | |
:stopped)) | |
(defn start! | |
"Start a new server." | |
[] | |
(reset! http-server (server/run-server (handler/site #'app) {:port 8080})) | |
:started) | |
(defn -main [&args] | |
(start!)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment