-
-
Save seryh/c0fa5e6743726efc1b8d47c163987f7d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(ns skooma.rpc | |
(:require-macros [cljs.core.async.macros :refer [go go-loop]]) | |
(:require [cljs.core.async :refer [<! >! chan pub sub put!]] | |
[cljs.core :refer [random-uuid]] | |
[clojure.string :as string] | |
[cljs-http.client :as http] | |
[cljs-http.util :as http-util])) | |
(defrecord context [rpc-url def-params]) | |
(def ^:private error-chan (chan)) | |
(def ^:private our-error-pub (pub error-chan :msg-type)) | |
(def ^:private rpc-template {:jsonrpc "2.0" | |
:method nil | |
:params nil | |
:id nil}) | |
(def default-context (atom (map->context {:rpc-url "/rpc" | |
:def-params {:userID 1863 | |
:currency "RUB" | |
:lang "ru"}}))) | |
(defn uuid-string | |
[] (str (.-uuid (random-uuid)))) | |
(defn http-error? [http-response] | |
(not (boolean (http/unexceptional-status? (:status http-response))))) | |
(defn rpc-error? [http-response] | |
(boolean (-> http-response :body :error))) | |
(defn error-response? [http-response] | |
(or (http-error? http-response) | |
(rpc-error? http-response))) | |
(defn when-result [http-response]) | |
(defn sub-from-error | |
"Подписаться на события об RPC ошибках" | |
[f] | |
(let [c (chan)] | |
(sub our-error-pub :error c) | |
(go-loop [] | |
(let [{:keys [msg-type http-response]} (<! c)] | |
(f http-response) | |
(recur))) c)) | |
(defmulti post | |
"return channel with body http response" | |
(fn ([context method params] | |
[(type context) (type method) (type params)]))) | |
(defmethod post [js/String PersistentArrayMap nil] [method params _] | |
(post @default-context method params)) | |
(defmethod post [context js/String PersistentArrayMap] [context method params] | |
(let [params (merge (:def-params context) params) | |
req (merge rpc-template {:id (uuid-string) | |
:method method | |
:params params}) | |
resp-chan (chan) | |
proxy-chan (http/post (:rpc-url context) {:json-params req})] | |
(go (let [http-response (<! proxy-chan)] | |
(when (error-response? http-response) | |
(>! error-chan {:msg-type :error :http-response (-> http-response :body)})) | |
(>! resp-chan (-> http-response :body)))) | |
resp-chan)) | |
(defmulti posts | |
"return channel with hashmap http responses" | |
(fn ([first & body] | |
(if (= context (type first)) | |
context | |
:default)))) | |
(defmethod posts :default [& body] | |
(apply posts (cons @default-context body))) | |
(defmethod posts context [context & body] | |
(let [resp-chan (chan) | |
req-map (apply hash-map body) | |
reqs-maker (fn [coll key item] | |
(let [id (uuid-string) | |
params (merge (:def-params context) (:params item)) | |
req (merge rpc-template {:id id | |
:method (:method item) | |
:params params})] | |
(merge coll {:req-list (conj (:req-list coll) req) | |
:keys (merge (:keys coll) {id key})}))) | |
data (reduce-kv reqs-maker {:keys {} :req-list []} req-map) | |
proxy-chan (http/post (:rpc-url context) {:json-params (:req-list data)})] | |
(go (let [http-response (<! proxy-chan) | |
resp-maker (fn [coll item] | |
(when (boolean (:error item)) | |
(>! error-chan {:msg-type :error :http-response item})) | |
(let [id (:id item) | |
id-keys (:keys data) | |
key (id-keys id)] | |
(merge coll {key item})))] | |
(if (http-error? http-response) | |
(>! error-chan {:msg-type :error :http-response (-> http-response :body)}) | |
(let [response (reduce resp-maker {} (-> http-response :body))] | |
(>! resp-chan response))))) resp-chan)) | |
(comment | |
(let [res-chan (post "AutoFind" {:term "новосибирск"})] | |
(go (println (<! res-chan)))) | |
(let [res-chan (posts | |
:res-1 {:method "AutoFind" :params {:term "sdfgsdgf"}} | |
:res-2 {:method "AutoFind" :params {:term "sdfgsdfgsd"}})] | |
(go (println (<! res-chan)))) | |
;; => {:res-1 {:jsonrpc 2.0, :result {:ItemCount 0, :Result [[]]}, :id 253d1114-b1f6-48c2-974d-30012c5ccee4}, :res-2 {:jsonrpc 2.0, :result {:ItemCount 0, :Result [[]]}, :id a081cc78-607f-4db2-958d-a4af2ae68cbc}} | |
) | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment