Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add defresolver async? options #90

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
8 changes: 8 additions & 0 deletions src/gosura/helpers/error.clj
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,11 @@
(error nil resolver-errors))
([resolved-value resolver-errors]
(resolve-as resolved-value resolver-errors)))

(defn error-response
[throwable]
{:message (ex-message throwable)
:info (str throwable)
:type (.getName (class throwable))
:stacktrace (->> (.getStackTrace throwable)
(map str))})
41 changes: 28 additions & 13 deletions src/gosura/helpers/resolver2.clj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(ns gosura.helpers.resolver2
"gosura.helpers.resolver의 v2입니다."
(:require [com.walmartlabs.lacinia.resolve :refer [resolve-as]]
(:require [com.walmartlabs.lacinia.resolve :refer [resolve-as] :as resolve]
[failjure.core :as f]
[gosura.auth :as auth]
[gosura.helpers.error :as error]
Expand All @@ -20,16 +20,29 @@
[catch-exceptions? body]
(if catch-exceptions?
`(try
~@body
~body
(catch Exception e#
(log/error e#)
(resolve-as
nil
{:message (ex-message e#)
:info (str e#)
:type (.getName (class e#))
:stacktrace (->> (.getStackTrace e#)
(map str))})))
(error/error-response e#))))
body))

(defn transform-body
[body return-camel-case?]
(cond-> body
return-camel-case? (update-resolver-result transform-keys->camelCaseKeyword)))

(defmacro wrap-async-body
[async? return-camel-case? body]
(if async?
`(let [result# (resolve/resolve-promise)]
(prom/future
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

require에 추가가 안되어있는 것 같은데, 잘 동작하나여?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이미 있었습니다. superlifter관련로직때문이었던거같아요

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

엇 제 의미는 이 네임스페이스에서 alias가 없는데도 prom이 동작하는가? 가 궁금했는데 그게 동작을 하나보네요?! 😮

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

링크가 안가지는데 요렇게 require에 있습니다.
[promesa.core :as prom]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[promesa.core :as prom]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아앗...

(try
(resolve/deliver! result# (transform-body ~body ~return-camel-case?))
(catch Throwable t#
(resolve/deliver! result# nil (error/error-response t#)))))
result#)
body))

(defmacro wrap-resolver-body
Expand All @@ -47,10 +60,11 @@
"
[{:keys [this ctx arg parent]} option args body]
(let [{:keys [auth kebab-case? return-camel-case? required-keys-in-parent
filters decode-ids-by-keys catch-exceptions?]
filters decode-ids-by-keys catch-exceptions? async?]
:or {kebab-case? true
return-camel-case? true
catch-exceptions? true
async? false
required-keys-in-parent []}} option
result (gensym 'result_)
auth-filter-opts `(auth/->auth-result ~auth ~ctx)
Expand All @@ -67,9 +81,10 @@
(if (or (nil? ~auth-filter-opts)
(and ~auth-filter-opts
(not (f/failed? ~auth-filter-opts))))
(let [~result (do (let ~let-mapping (wrap-catch-body ~catch-exceptions? ~body)))]
(cond-> ~result
~return-camel-case? (update-resolver-result transform-keys->camelCaseKeyword)))
(let [~result (do (let ~let-mapping (->> ~@body
(wrap-async-body ~async? ~return-camel-case?)
(wrap-catch-body ~catch-exceptions?))))]
(transform-body ~result ~return-camel-case?))
(resolve-as nil {:message "Unauthorized"})))))


Expand Down Expand Up @@ -114,7 +129,7 @@
* :parent-id: 부모로부터 전달되는 id 정보 예) {:pre-fn relay/decode-global-id->db-id :prop :id :agg :id} {:prop :user-id :agg :id}
* :pre-fn: 전처리
* :prop: 부모로부터 전달 받는 키값
* :agg: 데이터를 모으는 키값
* :agg: 데이터를 모으는 키값
## 반환
* 객체 목록
"
Expand Down Expand Up @@ -161,7 +176,7 @@
* :parent-id: 부모로부터 전달되는 id 정보 예) {:pre-fn relay/decode-global-id->db-id :prop :id :agg :id} {:prop :user-id :agg :id}
* :pre-fn: 전처리
* :prop: 부모로부터 전달 받는 키값
* :agg: 데이터를 모으는 키값
* :agg: 데이터를 모으는 키값
## 반환
* 객체 하나
"
Expand Down
81 changes: 58 additions & 23 deletions test/gosura/helpers/resolver_test.clj
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
(ns gosura.helpers.resolver-test
(:require [clojure.test :refer [are deftest is run-tests testing]]
[gosura.helpers.resolver :as gosura-resolver]
[com.walmartlabs.lacinia.resolve :as resolve]
[gosura.helpers.resolver2 :as gosura-resolver2])
(:import [clojure.lang ExceptionInfo]))

Expand Down Expand Up @@ -79,12 +80,10 @@
(get-in ctx [:identity :cc]))

(def auth-column-name :userId)
(def arg-in-resolver (atom {}))

(gosura-resolver2/defresolver test-resolver
{:auth [user-auth auth-column-name]}
[ctx arg parent]
(reset! arg-in-resolver arg)
{:ctx ctx
:arg arg
:parent parent})
Expand All @@ -100,11 +99,19 @@
:arg
:userId) "1"))))
(testing "arg/parent가 default True로 kebab-case 설정이 잘 동작한다"
(let [ctx {:identity {:id "1"}}
arg {:intArg 1
:strArg "str"}
parent {}
_ (test-resolver ctx arg parent)]
(let [arg-in-resolver (atom {})
_ (gosura-resolver2/defresolver test-resolver-1
{:auth [user-auth auth-column-name]}
[ctx arg parent]
(reset! arg-in-resolver arg)
{:ctx ctx
:arg arg
:parent parent})
ctx {:identity {:id "1"}}
arg {:intArg 1
:strArg "str"}
parent {}
_ (test-resolver-1 ctx arg parent)]
(is (= @arg-in-resolver {:int-arg 1
:str-arg "str"
:user-id "1"}))))
Expand Down Expand Up @@ -148,7 +155,6 @@
{:auth [user-auth auth-column-name]
:filters {:country-code get-country-code}}
[ctx arg parent]
(reset! arg-in-resolver arg)
{:ctx ctx
:arg arg
:parent parent})
Expand Down Expand Up @@ -206,31 +212,60 @@
(is (= (-> result
:arg) {:testCol "1"}))))
(testing "에러가 던져졌을 때 GraphQL errors를 반환한다"
(let [_ (gosura-resolver2/defresolver test-resolver-7
[_ctx _arg _parent]
(throw (ex-info "something wrong!" {})))
ctx {}
arg {}
parent {}
resolved (test-resolver-7 ctx arg parent)
message (get-in resolved [:resolved-value :data :message])
info (get-in resolved [:resolved-value :data :info])
type' (get-in resolved [:resolved-value :data :type])
(let [_ (gosura-resolver2/defresolver test-resolver-7
[_ctx _arg _parent]
(throw (ex-info "something wrong!" {})))
ctx {}
arg {}
parent {}
resolved (test-resolver-7 ctx arg parent)
message (get-in resolved [:resolved-value :data :message])
info (get-in resolved [:resolved-value :data :info])
type' (get-in resolved [:resolved-value :data :type])
stacktrace (get-in resolved [:resolved-value :data :stacktrace])]
(are [expected result] (= expected result)
"something wrong!" message
"clojure.lang.ExceptionInfo: something wrong! {}" info
(some? type') true
(some? stacktrace) true)))
(testing "catch-exceptions? 설정이 false일 때 에러가 던져지면 그대로 throw한다"
(let [_ (gosura-resolver2/defresolver test-resolver-8
{:catch-exceptions? false}
[_ctx _arg _parent]
(throw (ex-info "something wrong!" {})))
(let [_ (gosura-resolver2/defresolver test-resolver-8
{:catch-exceptions? false}
[_ctx _arg _parent]
(throw (ex-info "something wrong!" {})))
ctx {}
arg {}
parent {}]
(is (thrown? ExceptionInfo (test-resolver-8 ctx arg parent))))))
(is (thrown? ExceptionInfo (test-resolver-8 ctx arg parent)))))
(testing "async? 설정이 false 일 때, 원래 동작을 잘 보장한다"
(let [_ (gosura-resolver2/defresolver test-resolver-9
{:async? false}
[ctx arg parent]
{:ctx ctx
:arg arg
:parent parent})
ctx {:identity {:id "1"}}
arg {:intArg 1
:strArg "str"}
parent {}
result (test-resolver-9 ctx arg parent)]
(is (= result {:ctx {:identity {:id "1"}}
:arg {:intArg 1
:strArg "str"}
:parent {}}))))
(testing "async? 설정이 true 일 때, Promise를 잘 반환한다"
(let [_ (gosura-resolver2/defresolver test-resolver-10
{:async? true}
[ctx arg parent]
{:ctx ctx
:arg arg
:parent parent})
ctx {:identity {:id "1"}}
arg {:intArg 1
:strArg "str"}
parent {}
resolved (test-resolver-10 ctx arg parent)]
(is (satisfies? resolve/ResolverResultPromise resolved)))))

(comment
(run-tests))