Datomic Ion Connection Refused

So turns out it’s relatively straightforward to sidestep this problem if your interest is deploying a clojurescript app to connect to the ion.

Just serve it from within, word of warning, this isn’t the best way to do it, I’d preferably be sticking my cljs app in say an s3 bucket/cloudfront serving it from there, but for now this will serve.

I might come back in a month or two to improve the situation here.

There is however a few stumbling blocks to this master plan.

  1. Serving index.html with executable js:
    You need your :resource-path set as well as adjusting :content-security-policy-settings.
    In my case that’s:
(ns ion.service
  (:require [ring.util.response :as r]
            [io.pedestal.http :as http]
            [io.pedestal.http.route :as route]
            [io.pedestal.http.body-params :as body-params]
            [io.pedestal.ions :as provider]))

(defn home
  [request]
  (r/content-type
    (r/resource-response "public/index.html")
    "text/html"))

(def common-interceptors [(body-params/body-params) http/json-body])

(def routes #{["/" :get (conj common-interceptors `home)]
              ["/about" :get (conj common-interceptors `about)]})

(defn accept-all [origin] true)

(def service {::http/routes routes
              ::http/allowed-origins accept-all
              ::http/resource-path "/public"
              ::http/secure-headers {:content-security-policy-settings {:script-src "* 'unsafe-inline'"}}
              ::http/chain-provider provider/ion-provider})
  1. In your clojurescript project add cljsbuild configs to stick stuff in public, I’m using figwheel with re-frame, but this should work with whatever you want!
;;; Stick this inside the [:cljsbuild :builds] vector
;;; NOTE: <backend ion project> can be a relative path!

{:id           "iondev"
 :source-paths ["src/cljs"]
 :figwheel     {:on-jsload "frontend-client.core/mount-root"}
 :compiler     {:main                 frontend-client.core
                :output-to            "<backend ion project>/resources/public/js/compiled/app.js"
                :output-dir           "<backend ion project>/resources/public/js/compiled/out"
                :asset-path           "js/compiled/out"
                :source-map-timestamp true
                :preloads             [devtools.preload
                                       day8.re-frame-10x.preload]
                :closure-defines      {"re_frame.trace.trace_enabled_QMARK_" true
                                       "day8.re_frame.tracing.trace_enabled_QMARK_" true}
                :external-config      {:devtools/config {:features-to-install :all}}}}

    {:id           "ionmin"
     :source-paths ["src/cljs"]
     :compiler     {:main            frontend-client.core
                    :output-to       "<backend ion project>/resources/public/js/compiled/app.js"
                    :output-dir      "<backend ion project>/resources/public/js/compiled/min"
                    :optimizations   :advanced
                    :closure-defines {goog.DEBUG false}
                    :pretty-print    false}}

;;; For completeness I add the line below to the `:clean-targets` vector
"<backend ion project>/resources/public/js/compiled/"

So in my case I can now do:

;; Terminal 1: (repl)
clojure -Adev:log:jetty:rebel

;; Terminal 2: (proxy)
bash datomic-socks-proxy <ion stack name>

;; Terminal 3: (deploy)
clojure -Adev -m datomic.ion.dev '{:op :push :uname "app-test"}'
clojure -Adev -m datomic.ion.dev '{:op :deploy, :group <ion stack name>, :uname "app-test"}'
;;; Then copy/paste result of :status-command to see when it's done

;; Terminal 4: (fig) <- This is the terminal sitting in the frontend-client project
;;; dev
lein figwheel iondev
;;; or do the below before using Terminal 3 to deploy the generated compiled code
lein clean
lein cljsbuild once ionmin

There, that’s basically where I’m at present, hopefully I don’t encounter any more issues =)…

Well I’m back >_<…

I’m just getting these now, not sure why…

Cloudwatch Logs

{:cognitect.anomalies/category :cognitect.anomalies/unavailable, :cognitect.anomalies/message "Connection refused", :clojio/throwable :java.net.ConnectException, :clojio/socket-error :connect, :clojio/at 1562877500359, :clojio/remote "10.213.5.116", :clojio/queue :queued-input, :datomic.ion.lambda.handler/retries 0}

bash datomic-socks-proxy

debug1: channel 2: free: direct-tcpip: listening port 8182 for entry.<ion stack name>.eu-west-1.datomic.net port 8182, connect from 127.0.0.1 port 59565 to 127.0.0.1 port 8182, nchannels 3
debug1: Connection to port 8182 forwarding to socks port 0 requested.
debug1: channel 2: new [dynamic-tcpip]
channel 2: open failed: connect failed: Connection refused
debug1: channel 2: free: direct-tcpip: listening port 8182 for entry.<ion stack name>.eu-west-1.datomic.net port 8182, connect from ::1 port 59566 to ::1 port 8182, nchannels 3

Stacktrace

ERROR i.p.http.impl.servlet-interceptor  - {:msg "Dev interceptor caught an exception; Forwarding it as the response.", :line 314}
clojure.lang.ExceptionInfo: clojure.lang.ExceptionInfo in Interceptor :ion.service/datomic-interceptor - Unable to connect to localhost:8182
        at io.pedestal.interceptor.chain$throwable__GT_ex_info.invokeStatic(chain.clj:35)
        at io.pedestal.interceptor.chain$throwable__GT_ex_info.invoke(chain.clj:32)
        at io.pedestal.interceptor.chain$try_f.invokeStatic(chain.clj:57)
        at io.pedestal.interceptor.chain$try_f.invoke(chain.clj:44)
        at io.pedestal.interceptor.chain$process_all_with_binding.invokeStatic(chain.clj:171)
        at io.pedestal.interceptor.chain$process_all_with_binding.invoke(chain.clj:146)
        at io.pedestal.interceptor.chain$process_all$fn__15663.invoke(chain.clj:188)
        at clojure.lang.AFn.applyToHelper(AFn.java:152)
        at clojure.lang.AFn.applyTo(AFn.java:144)
        at clojure.core$apply.invokeStatic(core.clj:665)
        at clojure.core$with_bindings_STAR_.invokeStatic(core.clj:1973)
        at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1973)
        at clojure.lang.RestFn.invoke(RestFn.java:425)
        at io.pedestal.interceptor.chain$process_all.invokeStatic(chain.clj:186)
        at io.pedestal.interceptor.chain$process_all.invoke(chain.clj:182)
        at io.pedestal.interceptor.chain$enter_all.invokeStatic(chain.clj:235)
        at io.pedestal.interceptor.chain$enter_all.invoke(chain.clj:229)
        at io.pedestal.interceptor.chain$execute.invokeStatic(chain.clj:379)
        at io.pedestal.interceptor.chain$execute.invoke(chain.clj:352)
        at io.pedestal.interceptor.chain$execute.invokeStatic(chain.clj:389)
        at io.pedestal.interceptor.chain$execute.invoke(chain.clj:352)
        at io.pedestal.http.impl.servlet_interceptor$interceptor_service_fn$fn__20627.invoke(servlet_interceptor.clj:351)
        at io.pedestal.http.servlet.FnServlet.service(servlet.clj:28)
        at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:865)
        at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:535)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
        at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1253)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
        at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:473)
        at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
        at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1155)
        at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
        at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
        at org.eclipse.jetty.server.Server.handle(Server.java:531)
        at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:352)
        at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
        at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:281)
        at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:102)
        at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
        at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:760)
        at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:678)
        at java.lang.Thread.run(Thread.java:745)
Caused by: clojure.lang.ExceptionInfo: Unable to connect to localhost:8182
        at datomic.client.impl.cloud$get_s3_auth_path.invokeStatic(cloud.clj:175)
        at datomic.client.impl.cloud$get_s3_auth_path.invoke(cloud.clj:166)
        at datomic.client.impl.cloud$create_client.invokeStatic(cloud.clj:207)
        at datomic.client.impl.cloud$create_client.invoke(cloud.clj:190)
        at clojure.lang.Var.invoke(Var.java:384)
        at datomic.client.api.impl$dynarun.invokeStatic(impl.clj:19)
        at datomic.client.api.impl$dynarun.invoke(impl.clj:16)
        at datomic.client.api.impl$dynacall.invokeStatic(impl.clj:26)
        at datomic.client.api.impl$dynacall.invoke(impl.clj:23)
        at datomic.client.api.async$client.invokeStatic(async.clj:66)
        at datomic.client.api.async$client.invoke(async.clj:62)
        at datomic.client.api.sync$client.invokeStatic(sync.clj:77)
        at datomic.client.api.sync$client.invoke(sync.clj:75)
        at clojure.lang.Var.invoke(Var.java:384)
        at datomic.client.api.impl$dynarun.invokeStatic(impl.clj:19)
        at datomic.client.api.impl$dynarun.invoke(impl.clj:16)
        at datomic.client.api.impl$dynacall.invokeStatic(impl.clj:26)
        at datomic.client.api.impl$dynacall.invoke(impl.clj:23)
        at datomic.client.api$client.invokeStatic(api.clj:87)
        at datomic.client.api$client.invoke(api.clj:54)
        at datomic.client.api$client.invokeStatic(api.clj:84)
        at datomic.client.api$client.invoke(api.clj:54)
        at ion.service$fn__23175.invokeStatic(service.clj:97)
        at ion.service$fn__23175.invoke(service.clj:95)
        at clojure.lang.AFn.applyToHelper(AFn.java:154)
        at clojure.lang.AFn.applyTo(AFn.java:144)
        at clojure.core$apply.invokeStatic(core.clj:665)
        at clojure.core$memoize$fn__6862.doInvoke(core.clj:6353)
        at clojure.lang.RestFn.invoke(RestFn.java:408)
        at ion.service$get_connection.invokeStatic(service.clj:108)
        at ion.service$get_connection.invoke(service.clj:104)
        at ion.service$fn__23186.invokeStatic(service.clj:139)
        at ion.service$fn__23186.invoke(service.clj:135)
        at io.pedestal.interceptor.chain$try_f.invokeStatic(chain.clj:54)
        ... 39 common frames omitted

Rather disconcerting as I don’t believe I’ve done anything so I’m not sure why it’s suddenly not working…


Looking at the docs, it seems my version is older than the current version of 480-8772, however I hope that’s not the reason it’s not working. It would be pretty problematic if my live site stops working because my dependencies are “out of date”…


Ok so a quick sanity test of checking the proxy via:

curl -x socks5h://localhost:$DATOMIC_SOCKS_PORT http://entry.$DATOMIC_SYSTEM.$DATOMIC_REGION.datomic.net:8182/
curl: (7) Failed to receive SOCKS5 connect request ack.

Proxy:

debug1: channel 2: new [dynamic-tcpip]
channel 2: open failed: connect failed: Connection refused
debug1: channel 2: free: direct-tcpip: listening port 8182 for entry.<ion stack name>.eu-west-1.datomic.net port 8182, connect from ::1 port 62825 to ::1 port 8182, nchannels 3

Shows that’s also failing… So next step seems to be to look at cloudformation, but that appears to be fine… A pickle to be sure.


And now it just seems to be working again :thinking: