Fork me on GitHub
#pedestal
<
2018-05-03
>
tianshu16:05:41

I'm very interest in pedestal, I want to write a web server with core.async. is there any examples for pedestal with core.async? also, i'm curious about how to deal with jdbc with core.async.

tianshu16:05:57

thanks for any help.

ddeaguiar16:05:47

Hi @doglooksgood, I’m glad to hear about your interest in Pedestal! I recommend reading through the Pedestal documentation, in particular the section on interceptor return values (http://pedestal.io/reference/interceptors#_interceptor_return_values). Unfortunately, I don’t have a sample project to point you to but I just created an issue (https://github.com/pedestal/pedestal-docs/issues/104) to track getting that done.

ddeaguiar16:05:23

In a nutshell, Pedestal interceptors support going async. You just need to return a core.async channel which will yield an updated context

tianshu16:05:04

that's great, if I understand correct, pedestal can use core.async channel as a response. so basically i can use a go in handler and do everything I want?

tianshu16:05:40

I found on the document that I can return channel in interceptors

ddeaguiar16:05:28

To be clear, you cannot return a channel as a response.

ddeaguiar16:05:42

in other words

ddeaguiar16:05:27

If you have a handler function, it can’t return a channel. But an interceptor can return a channel which will return a context map at some point

ddeaguiar16:05:18

Hm, I need to look into that because the following does not work

(defn home-page
  [request]
  (async/go
    (ring-resp/response "Hello World!")))

ddeaguiar16:05:37

while this does

(def home-page
  (i/interceptor
   {:name ::home-page
    :enter (fn [ctx]
             (async/go
               (assoc ctx :response (ring-resp/response "Hello World!"))))}))

ddeaguiar16:05:57

but I will follow up

tianshu17:05:42

okay, I'll take a look

ddeaguiar17:05:50

@doglooksgood I’m mistaken, when working with servlets you can return a channel as the response body

ddeaguiar17:05:57

but not as the response

ddeaguiar17:05:13

So this works

(defn home-page
  [request]
  (-> (async/go "Hello World!")
      ring-resp/response
      (ring-resp/content-type "text/html")))

ddeaguiar17:05:52

But this behavior is specific to servlet interceptor chain providers

ddeaguiar17:05:33

But I tend to use interceptors in these cases as opposed to handler functions

tianshu17:05:12

what does servlet means here?

tianshu17:05:28

use with some container like tomcat?

ddeaguiar17:05:41

basically if you use jetty, tomcat or immutant to host your pedestal app

ddeaguiar17:05:31

You don’t need to deploy your app as a war. You can start up a container to run it. Jetty is the popular choice and the default

tianshu17:05:08

(defn index [request]
  {:status 200
   :body (go "hello")})

(def routes
  (route/expand-routes
   #{["/index" :get index :route-name :index]}))

(def service-map
  (-> {::http/routes routes
       ::http/type :immutant
       ::http/port 8890}
      http/default-interceptors
      http/dev-interceptors
      http/create-server))

(mount/defstate server
  :start
  (http/start service-map)
  :stop
  (http/stop server))

(comment
  (mount/start #'server))
I just tried with this, but it failed. the error is Caused by: java.lang.IllegalArgumentException: No implementation of method: :default-content-type of protocol: #'io.pedestal.http.impl.servlet-interceptor/WriteableBody found for class: clojure.core.async.impl.channels.ManyToManyChannel

ddeaguiar17:05:02

Hmm, change :immutant to :jetty

tianshu17:05:37

let me have a try

ddeaguiar17:05:45

it should still fail

tianshu17:05:09

yes, I can't start when use jetty

tianshu17:05:22

very strange

ddeaguiar17:05:12

That’s strange. I expect immutant to use the same servlet code as jetty in this case

ddeaguiar17:05:40

hrm, it works for me though

ddeaguiar17:05:19

async response with immutant

tianshu17:05:28

I'm afraid I can't find where is the key point?

ddeaguiar17:05:47

that works for me

tianshu17:05:08

thank you very much