thread_api.cljc 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344
  1. (ns frontend.common.thread-api
  2. "Macro for defining thread apis, which is invokeable by other threads"
  3. #?(:cljs (:require-macros [frontend.common.thread-api]))
  4. #?(:cljs (:require [logseq.db :as ldb]
  5. [promesa.core :as p])))
  6. #?(:cljs
  7. (def *thread-apis (volatile! {})))
  8. #_:clj-kondo/ignore
  9. (defmacro defkeyword [& _args])
  10. (defmacro def-thread-api
  11. "Define a api invokeable by other threads.
  12. e.g. (def-thread-api :thread-api/a-api [arg1 arg2] body)"
  13. [qualified-keyword-name params & body]
  14. (assert (= "thread-api" (namespace qualified-keyword-name)) qualified-keyword-name)
  15. (assert (vector? params) params)
  16. `(vswap! *thread-apis assoc
  17. ~qualified-keyword-name
  18. (fn ~(symbol (str "thread-api--" (name qualified-keyword-name))) ~params ~@body)))
  19. #?(:cljs (def *profile (volatile! {})))
  20. #?(:cljs
  21. (defn remote-function
  22. "Return a promise whose value is transit-str."
  23. [qualified-kw-str direct-pass? args-transit-str-or-args-array]
  24. (let [qkw (keyword qualified-kw-str)]
  25. (vswap! *profile update qkw inc)
  26. (if-let [f (@*thread-apis qkw)]
  27. (let [result (if (= qkw :thread-api/set-infer-worker-proxy)
  28. (f args-transit-str-or-args-array)
  29. (apply f (cond-> args-transit-str-or-args-array
  30. (not direct-pass?) ldb/read-transit-str)))
  31. result-promise
  32. (if (fn? result) ;; missionary task is a fn
  33. (js/Promise. result)
  34. result)]
  35. (p/let [result' result-promise]
  36. (if direct-pass?
  37. result'
  38. (ldb/write-transit-str result'))))
  39. (throw (ex-info (str "not found thread-api: " qualified-kw-str) {}))))))