This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2019-01-20
Channels
- # announcements (1)
- # beginners (48)
- # cljdoc (6)
- # cljs-dev (1)
- # cljsjs (1)
- # clojure (13)
- # clojure-dev (6)
- # clojure-estonia (1)
- # clojure-europe (1)
- # clojure-finland (8)
- # clojure-gamedev (3)
- # clojure-spec (35)
- # clojure-uk (25)
- # clojurescript (9)
- # datascript (1)
- # datomic (18)
- # figwheel-main (2)
- # fulcro (5)
- # graphql (1)
- # jobs (16)
- # off-topic (76)
- # pathom (39)
- # re-frame (6)
- # reagent (7)
- # remote-jobs (6)
- # rum (3)
- # shadow-cljs (54)
- # spacemacs (8)
- # speculative (2)
- # yada (72)
I found solution:
(-> (peridot/session (yada/handler core/graphql))
(peridot/request "/graphql"
:content-type "application/graphql"
:request-method :post
:body "{ game_by_id(id: \"1237\") { name designers { name }}}")
:response
(deref)
:body
(bs/to-string)
;(edn/read-string)
)
I would like to make a handler to bidi routes handler instead of 1 resource, but this one I don’t know how to do
(-> (peridot/session (as-handler core/handler))
(peridot/request "/graphql"
:content-type "application/graphql"
:request-method :post
:body "{ game_by_id(id: \"1237\") { name designers { name }}}")
:response
(deref)
:body
(bs/to-string)
;(edn/read-string)
)
^ yeah, this one work perfect with routing 🙂It looks like it is impossible to use :post with :body for testing with yada, it needs to be with aleph server.
https://github.com/juxt/yada/blob/ba10db43e1a332f0bfd352cd8ea39f176190c4ff/src/yada/test.clj#L40
or I use integration testing, I think that’s even better if you want to test your service as an end consumer
I think because the interceptor chain doesn’t have the right interceptor which does the schema thing
My main issues is probably about not understanding difference between ring vs aleph + manifold.
Do you understand why Manifold is needed? I understand general description, but I don’t really understand what it is about on deeper level. Why http/get
can’t return normal string instead.
manifold gives an abstraction over futures/promises and whatnot. it’s used in yada to have asynchronous interceptors
(ytest/with-aleph url (as-handler core/handler)
@(http/post (str url "/graphql")))
Syntax error (ExceptionInfo) compiling at (core_test.clj:88:3).
status: 404
How to use your macro? I always have 404. I was trying use core/handler
on many ways but always 404(def handler
["/" [["authentication" authentication]
["graphql" graphql]
[true not-found]]])
@kwladyka yada is async/non-blocking - http/get
can't return a String
, that would be a blocking API, so it has to return a Promise<String>
- and yada is using Manifold's Deferred
as its promise implementation
it uses Manifold's Deferred
instead of clojure's standard promise
because Manifold's Deferred
supports completion callbacks and therefore the composition of promise values required to implement such things as interceptor chains (and most useful non-blocking computations with promises)
it could also use another non-blocking abstraction, like core.async
, but that would probably lead to a very different API
i much prefer promises over core.async
for point values
“so yada is async and in the same time use promises to be even more async and give better performance”
core.async
is ok for streams of values - although Manifold's stream
plays very nicely with Deferred
so is my go to on clojure
@kwladyka yada uses promises as its principal async abstraction, rather than to improve performance
it's built on aleph, which is also Deferred
based, so Deferred
is the natural async abstraction for yada to use
Hmm I am probably not enough experienced to imagine specific situations and benefits from it, but I understand general concept 🙂
@kwladyka how to use the macro, just do a search on github: https://github.com/juxt/yada/search?q=with-aleph&unscoped_q=with-aleph
resource (new-classpath-resource "static")
<- it is instead of real resource, so I am not sure about real use case
@kwladyka Another example:
(with-aleph url
(y/resource {:methods
{:post {:parameters {:body {:foo s/Str}}
:response (fn [ctx] {:a 1})
:produces #{"application/json"}
:consumes #{"application/json"}}}})
(let [response (client/request
(request :post url {}))
body (cheshire/decode (str (:body response)) true)]
(is (= "missing-required-key" (-> body :error :foo)))
(is (= "Schema validation error" (-> body :message)))))
that’s just a random HTTP client, shouldn’t matter. but in this case it’s clj-http: [clj-http.client :as client]
Syntax error (ClassCastException) compiling at (core_test.clj:101:3).
class clojure.lang.PersistentArrayMap cannot be cast to class [B (clojure.lang.PersistentArrayMap is in unnamed module of loader 'app'; [B is in module java.base of loader 'bootstrap')
Jan 20, 2019 9:37:23 PM io.netty.util.concurrent.DefaultPromise notifyListener0
WARNING: An exception was thrown by aleph.netty$wrap_future$reify__15341.operationComplete()
java.lang.NoClassDefFoundError: Could not initialize class manifold.deferred.Deferred$fn__2465
at manifold.deferred.Deferred.success(deferred.clj:398)
at manifold.deferred$success_BANG_.invokeStatic(deferred.clj:243)
at manifold.deferred$success_BANG_.invoke(deferred.clj:240)
at aleph.netty$wrap_future$reify__15341.operationComplete(netty.clj:199)
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:511)
at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:485)
at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:424)
at io.netty.util.concurrent.DefaultPromise.setSuccess(DefaultPromise.java:94)
at io.netty.util.concurrent.MultithreadEventExecutorGroup$1.operationComplete(MultithreadEventExecutorGroup.java:117)
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:511)
at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:485)
at io.netty.util.concurrent.DefaultPromise.access$000(DefaultPromise.java:33)
at io.netty.util.concurrent.DefaultPromise$1.run(DefaultPromise.java:435)
at io.netty.util.concurrent.GlobalEventExecutor$TaskRunner.run(GlobalEventExecutor.java:248)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:834)
It doesn’t work for me(ytest/with-aleph url core/graphql
(-> @(http/post url #_(str url "/graphql") {:content-type "application/json"
:body "{\"email\":\"\",\"password\":\"qwaszx\"}"
:throw-exceptions false})
:body
(slurp)))
but this work!vmodel# (vhosts-model [:* ["/" resource#]])
- oh it is probably not designed for that purpose
@kwladyka my y/resource is a custom yada resource, that has our interceptor chain and error interceptor chain.
Am I understand it correctly ? This macro is designed to test only 1 resource. There is no way to use it with bidi routing?
no, it’s only designed to test a single resource. for full testing I’d use integration testing
Do you have Docker architecture? Kubernetes for testing or something similar? If yes what do you use for integration testing?
We just test against a running instance with a database with real data in it (some would call it a staging environment)
but it could also be done with a script which spins up your app and then starts the tests in a different process
Personally I will choose probably Dockerfile + bash / Clojure tests for this project on staging environment kubernetes
I’m doing something similar with http://re-find.it which is just a SPA without a server, there I start a webserver that serves the static content, and then start some browser tests: https://github.com/borkdude/re-find.web/blob/master/test/re_find/web_test.clj#L152
Docker makes sense too. But for the app we’re using yada for, it’s very resource intensive in terms of memory and needs a lot of other services. That’s why we test it “live”
all of this isn’t directly related to whether you use yada, ring, pedestal, just choices you can make