Skip to content

Instantly share code, notes, and snippets.

@pithyless
Last active April 6, 2018 13:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pithyless/51897363f5b6171a6d8e6368c60ab085 to your computer and use it in GitHub Desktop.
Save pithyless/51897363f5b6171a6d8e6368c60ab085 to your computer and use it in GitHub Desktop.
Pedestal sync vs async error-handling

I expected the async error to be handled by the error-handler interceptor (i.e. [OK] Handling error.).

❯ clj -m dev

Do some work...
[OK] Got a response.
{:async :ok, :sync :ok}

Sync error...
[OK] Handling error.
clojure.lang.ExceptionInfo: java.lang.AssertionError in Interceptor :do-work-sync - Assert failed: Sync error
nil
 at clojure.core$ex_info.invokeStatic (core.clj:4739)
    clojure.core$ex_info.invoke (core.clj:4739)
    io.pedestal.interceptor.chain$throwable__GT_ex_info.invokeStatic (chain.clj:35)

Async error...
Exception in thread "async-dispatch-7" java.lang.AssertionError: Assert failed: Async error
nil
	at dev$fn__9857$fn__9870$state_machine__6416__auto____9875$fn__9877.invoke(dev.clj:20)
	at dev$fn__9857$fn__9870$state_machine__6416__auto____9875.invoke(dev.clj:17)
	at clojure.core.async.impl.ioc_macros$run_state_machine.invokeStatic(ioc_macros.clj:973)
	at clojure.core.async.impl.ioc_macros$run_state_machine.invoke(ioc_macros.clj:972)
	at clojure.core.async.impl.ioc_macros$run_state_machine_wrapped.invokeStatic(ioc_macros.clj:977)
	at clojure.core.async.impl.ioc_macros$run_state_machine_wrapped.invoke(ioc_macros.clj:975)
	at dev$fn__9857$fn__9870.invoke(dev.clj:17)
	at clojure.lang.AFn.run(AFn.java:22)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	at java.lang.Thread.run(Thread.java:748)
{:paths ["src"]
:deps {org.clojure/clojure {:mvn/version "1.9.0"}
org.clojure/core.async {:mvn/version "0.4.474"}
io.pedestal/pedestal.interceptor {:mvn/version "0.5.3"}}}
;; should be saved as `src/dev.clj`
(ns dev
(:require [io.pedestal.interceptor.chain :as interceptor.chain]
[clojure.core.async :as async]
[clojure.stacktrace :as stacktrace]))
(def do-work-sync
{:name :do-work-sync
:enter (fn [ctx]
(if (:sync-error ctx)
(assert nil "Sync error")
(assoc ctx :sync :ok)))})
(def do-work-async
{:name :do-work-async
:enter (fn [ctx]
(let [ch (async/chan)]
(async/go
(async/>! ch
(if (:async-error ctx)
(assert nil "Async error")
(assoc ctx :async :ok))))
ch))})
(def log-work
{:name :log-work
:leave (fn [ctx]
(println "[OK] Got a response.")
(prn (select-keys ctx [:async :sync])))})
(def handle-errors
{:name :error-interceptor
:error (fn [ctx ex]
(println "[OK] Handling error.")
(stacktrace/print-stack-trace ex 3))})
(defn -main []
(let [pipeline [handle-errors log-work do-work-async do-work-sync]]
(println "Do some work...")
(interceptor.chain/execute {} pipeline)
(Thread/sleep 500)
(println "\nSync error...")
(interceptor.chain/execute {:sync-error true} pipeline)
(Thread/sleep 500)
(println "\nAsync error...")
(interceptor.chain/execute {:async-error true} pipeline)
(Thread/sleep 500)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment