yada

kwladyka 2019-01-20T18:36:44.188600Z

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)
      )

kwladyka 2019-01-20T18:37:30.189400Z

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

kwladyka 2019-01-20T18:45:39.189800Z

(-> (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 🙂

kwladyka 2019-01-20T19:12:59.190300Z

oh there is the same issue about :body like with response-for. It is nil.

kwladyka 2019-01-20T19:16:21.191100Z

It looks like it is impossible to use :post with :body for testing with yada, it needs to be with aleph server.

borkdude 2019-01-20T19:16:56.191500Z

that’s why I use this macro:

borkdude 2019-01-20T19:18:29.192500Z

or I use integration testing, I think that’s even better if you want to test your service as an end consumer

kwladyka 2019-01-20T19:20:25.193Z

yeah, I will probably end with one of this solution

kwladyka 2019-01-20T19:20:45.193500Z

Not sure why :body is nil, but maybe I don’t have to know 🙂

borkdude 2019-01-20T19:21:15.194100Z

I think because the interceptor chain doesn’t have the right interceptor which does the schema thing

borkdude 2019-01-20T19:21:43.194300Z

if I remember correctly, long time ago 🙂

kwladyka 2019-01-20T19:23:19.195Z

My main issues is probably about not understanding difference between ring vs aleph + manifold.

borkdude 2019-01-20T19:25:14.195600Z

one difference is that aleph is designed for asynchronous requests

kwladyka 2019-01-20T19:25:25.195900Z

that one I understand 🙂

kwladyka 2019-01-20T19:25:54.196200Z

probably only that one haha 😉

kwladyka 2019-01-20T19:33:14.197400Z

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.

borkdude 2019-01-20T19:46:04.199Z

manifold gives an abstraction over futures/promises and whatnot. it’s used in yada to have asynchronous interceptors

kwladyka 2019-01-20T19:57:10.199900Z

(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

kwladyka 2019-01-20T19:57:26.200100Z

(def handler
  ["/" [["authentication" authentication]
        ["graphql" graphql]
        [true not-found]]])

mccraigmccraig 2019-01-20T20:04:29.201600Z

@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

mccraigmccraig 2019-01-20T20:06:01.203200Z

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)

👍 1
mccraigmccraig 2019-01-20T20:06:38.204Z

it could also use another non-blocking abstraction, like core.async, but that would probably lead to a very different API

mccraigmccraig 2019-01-20T20:07:06.204600Z

i much prefer promises over core.async for point values

kwladyka 2019-01-20T20:07:36.205700Z

“so yada is async and in the same time use promises to be even more async and give better performance”

mccraigmccraig 2019-01-20T20:07:50.205900Z

core.async is ok for streams of values - although Manifold's stream plays very nicely with Deferred so is my go to on clojure

mccraigmccraig 2019-01-20T20:08:32.206700Z

@kwladyka yada uses promises as its principal async abstraction, rather than to improve performance

mccraigmccraig 2019-01-20T20:09:48.207500Z

it's built on aleph, which is also Deferred based, so Deferred is the natural async abstraction for yada to use

kwladyka 2019-01-20T20:10:39.208500Z

Hmm I am probably not enough experienced to imagine specific situations and benefits from it, but I understand general concept 🙂

kwladyka 2019-01-20T20:10:40.208700Z

Thanks

borkdude 2019-01-20T20:12:09.209Z

@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

kwladyka 2019-01-20T20:12:52.209600Z

resource (new-classpath-resource "static") <- it is instead of real resource, so I am not sure about real use case

kwladyka 2019-01-20T20:13:03.209900Z

and this test expect 404

kwladyka 2019-01-20T20:13:08.210300Z

Which is what I get 🙂

kwladyka 2019-01-20T20:13:29.211200Z

But I expect something different

kwladyka 2019-01-20T20:14:19.212400Z

@borkdude I saw that test, but still I don’t know how to use it

borkdude 2019-01-20T20:14:26.212800Z

@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" (-&gt; body :error :foo)))
      (is (= "Schema validation error" (-&gt; body :message)))))

borkdude 2019-01-20T20:15:23.214100Z

note that (y/resource ...) is my custom yada resource with error handler builtin

kwladyka 2019-01-20T20:15:26.214200Z

What is client/request ?

borkdude 2019-01-20T20:16:01.215100Z

that’s just a random HTTP client, shouldn’t matter. but in this case it’s clj-http: [clj-http.client :as client]

borkdude 2019-01-20T20:17:55.215600Z

any http client should do, since it’s just a webserver running on some port

kwladyka 2019-01-20T20:37:44.216400Z

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

kwladyka 2019-01-20T20:38:32.217100Z

unless your’s y/resource is much different, than yada/resource

kwladyka 2019-01-20T20:43:47.217400Z

(ytest/with-aleph url core/graphql
                    (-&gt; @(http/post url #_(str url "/graphql") {:content-type "application/json"
                                                                :body "{\"email\":\"<mailto:foo@example.com|foo@example.com>\",\"password\":\"qwaszx\"}"
                                                                :throw-exceptions false})
                        :body
                        (slurp)))
but this work!

kwladyka 2019-01-20T20:44:09.217700Z

now I have to solve how to do it with full routing

kwladyka 2019-01-20T20:44:50.218Z

And that one is harder

kwladyka 2019-01-20T20:48:51.219Z

vmodel# (vhosts-model [:* ["/" resource#]]) - oh it is probably not designed for that purpose

borkdude 2019-01-20T20:49:58.219600Z

@kwladyka my y/resource is a custom yada resource, that has our interceptor chain and error interceptor chain.

borkdude 2019-01-20T20:50:10.219900Z

I’m testing the behavior of the error rendering in that example

kwladyka 2019-01-20T20:51:06.221Z

Am I understand it correctly ? This macro is designed to test only 1 resource. There is no way to use it with bidi routing?

borkdude 2019-01-20T20:51:08.221200Z

no, it’s only designed to test a single resource. for full testing I’d use integration testing

👍 1
kwladyka 2019-01-20T20:52:23.222100Z

Do you have Docker architecture? Kubernetes for testing or something similar? If yes what do you use for integration testing?

kwladyka 2019-01-20T20:52:39.222500Z

Separate Clojure app only for testing? Bash?

borkdude 2019-01-20T20:53:00.223Z

We just test against a running instance with a database with real data in it (some would call it a staging environment)

borkdude 2019-01-20T20:53:30.223900Z

but it could also be done with a script which spins up your app and then starts the tests in a different process

borkdude 2019-01-20T20:53:35.224200Z

however you like it

kwladyka 2019-01-20T20:53:50.224500Z

sure, just like to listen other people experience 🙂

kwladyka 2019-01-20T20:55:15.225500Z

Personally I will choose probably Dockerfile + bash / Clojure tests for this project on staging environment kubernetes

borkdude 2019-01-20T20:55:21.225700Z

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

borkdude 2019-01-20T20:57:10.227Z

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”

kwladyka 2019-01-20T20:57:28.227300Z

“live” mean on production?

borkdude 2019-01-20T20:57:44.227800Z

a staging environment that’s the version before it goes to production

kwladyka 2019-01-20T20:58:07.228100Z

> That’s why we test it “live” Not sure what you mean here by “live”

kwladyka 2019-01-20T20:58:28.228800Z

manually?

borkdude 2019-01-20T20:58:30.228900Z

I mean, it’s an environment that’s running 100% of the time and also used for QA

borkdude 2019-01-20T20:58:40.229100Z

no, scripted of course

borkdude 2019-01-20T20:59:09.229600Z

I just use clojure.test + clj-http for the API tests

borkdude 2019-01-20T20:59:31.229800Z

and etaoin for browser tests

borkdude 2019-01-20T21:00:34.230500Z

the browser is running in a Docker container

borkdude 2019-01-20T21:01:24.231500Z

all of this isn’t directly related to whether you use yada, ring, pedestal, just choices you can make

kwladyka 2019-01-20T21:02:13.232500Z

Yeah, I want to make SaaS label printer as my private project. I did the job about generate labels very fast. Making Ops, GraphQL, SaaS will take me probably a few months heh

kwladyka 2019-01-20T21:03:10.232900Z

Probably I will choose similar way for testing