外部APIとうまく付き合う

1746ab660311d1514a526dfa2f29e616?s=47 makinoshi
February 17, 2018

 外部APIとうまく付き合う

Clojureを使って外部APIを使うコードを設計する、書く方法について

1746ab660311d1514a526dfa2f29e616?s=128

makinoshi

February 17, 2018
Tweet

Transcript

  1. ֎෦"1*ͱ ͏·͘෇͖߹͏ 2018-02-11 clj-ebisu #2 @makinoshi

  2. Me • αΠϘ΢ζελʔτΞοϓεגࣜձࣾ • Like: C++(11~), PostgreSQL(SQL), Clojure, Emacs(Spacemacs), MS

    Sculpt Ergonomic Keyboard • Hobby: ϚϯΨ,͓ञ • ࠷ۙͷΠνΦγ: cljr-create-fn-from-example
  3. ΞδΣϯμ • (֎෦)APIʹΞΫηε͢Δ෦෼ΛͲ͏࡞Δ͔ • ೖྗ͢Δσʔλߏ଄ΛͲ͏ͭ͘Δ͔ • ΧϓηϧԽ͞Εͨ಺෦ॲཧΛͭ͘Δ • ݁ՌΛද͢σʔλߏ଄

  4. ೖྗ͢Δσʔλߏ଄Λ࡞Δ

  5. ྫ) SendGridͷAPI {:headers {"Authorization" "Bearer ...."} :content-type :json :form-params {:subject

    "໊݅" :content [{:type "text/plain" :value "ຊจ"}] :from {:name "MyService" :email "myapp@example.com"} :personalizations [{:to [{:email "a1@example.com" :name "a͞Μ"} {:email "a2@example.com" :name "a͞Μ"}] :custom_args {:id "1"}} {:to [{:email "b@example.com" :name “b͞Μ"}] :custom_args {:id “2"}}]}} • ͜ͷߏ଄Λҙࣝͨ͠ίʔυ͸ॻ͖ͨ͘ͳ͍
  6. Builderύλʔϯ • ֤ϝιουͰҾ਺ΛνΣοΫͭͭ͠σʔλཷ ΊࠐΉ • buildϝιουͰ੔͑ΔɺνΣοΫ͢Δ • ೖग़ྗܗࣜͷมߋΛ಺෦ͰٵऩͰ͖ΔˠAPIͷ มߋ΍࢖͏APIࣗମͷมߋ΋༰қʹͳΔ

  7. ࣮૷ྫ (-> (mail/builder something-component) (mail/with-subject "໊݅") (mail/with-content "ຊจ") (mail/with-recipients [{:email

    "a@example.com" :to-name "a͞Μ" :id 1 :callback “/app/path/1”} {:email "b@example.com" :to-name "b͞Μ" :id 2 :callback “/app/path/2”}]) mail/build) • AWS SDK for Javaͷ࣮૷͕BuilderύλʔϯΛ ͱͯ΋্खʹ࢖͍ͬͯΔͱࢥ͍·͢
  8. ಺෦ॲཧΛΧϓηϧԽ͢Δ

  9. ࢖͏ଆʹ࿙Βͨ͘͠ͳ͍ • ࢖͏ϥΠϒϥϦͷڍಈ • ྫ֎͕ൃੜ͢Δঢ়گͷࠩҟɺ໭Γ஋ͷࠩҟ(map, promise, etc..) • ࣮ߦ਺ •

    rate limit • ಉ࣌઀ଓ਺ • ϦτϥΠ • ෳ਺ͷϦΫΤετ΋୯ҰϦΫΤετͷγʔέϯεͱͯ͠ѻ͍͍ͨ
  10. diehardͱڞʹ • https://github.com/sunng87/diehard • ઃఆϕʔεͰɺretry/circuit breaker/rate limitterΛ؆୯ʹ࣮૷Ͱ͖Δ • JavaͷϥΠϒϥϦɺnet.jodah/failsafeͷϥο ύ

  11. ࣮૷ྫ (diehard.core/defratelimiter rl {:rate 100}) ; per sec (clj-http.client/with-connection-pool {:timeout

    10 :insecure? false :default-per-route 100} (->> coll (map #(future (diehard.core/with-retry {:retry-if (fn [resp exp] (or (>= (:status resp) 500) (instance? IOException exp))) :max-retries 3 :delay-ms 1000} (diehard.core/with-rate-limiter rl (api/call endpoint %))))) (map deref) doll)) • ΊͪΌͪ͘Ό؆୯ • ΋ͬͱهड़ྔগͳ͘ఆٛ͢Δํ๏΋υΩϡϝϯτʹ͋Γ·͢
  12. ໭Γ஋ͷදݱ

  13. ओͳ໰୊͸Τϥʔॲཧ • ѻ͍΍͍͢໭Γ஋ • ୯ͳΔσʔλ • Τϥʔ͔Ͳ͏͔൑ఆ͠΍͍͢ • Τϥʔʹͳͬͨͱ͖ͷҾ਺Λͦͷ··औΓग़ͤΔ •

    ѻ͍ʹ͍͘໭Γ஋ • ྫ֎͕౤͛ΒΕͨΓɺ౤͛ΒΕͳ͔ͬͨΓ • ֎෦ͷϥΠϒϥϦͰఆٛ͞Εͨܕ • promise(ಛʹ֎෦ϥΠϒϥϦͷ) • ඇಉظ͕͍͍͔Ͳ͏͔͸ݺͼग़͠ଆͷࣄ৘ • => GolangελΠϧ or ಠࣗఆٛͷEitherͷͲͪΒ͔͕Αͦ͞͏
  14. ࣮ࡍʹ྆ํ࢖ͬͯΈͨ݁Ռ • GolangελΠϧͷํ͕ॻ͍ͯͯϛε͕গͳͦ͞͏ʹײ͍ͯ͡· ͢ • ѻ͍΍͘͢ɺγϯϓϧʹॻ͚Δ • (group-by #(-> %

    second some?) results) (try (let [resp (clj-http.client/post endpoint params)] [{:resp resp resp :params params} nil]) (catch clojure.lang.ExceptionInfo e [{:params params} (ex-data e)]) (catch java.io.IOException e [{:params params} e]))
  15. ·ͱΊ • ClojureͰ΋σʔλ࡞੒ͷந৅ԽʹBuilder͸໾ ཱͭ • ϥΠϒϥϦͷڍಈ΍APIͰ͋Δ͜ͱࣗମ΋֎͔ ΒӅ͢ˠޙʑ؆୯ʹมߋͰ͖Δ • ໭Γ஋΋ྫ֎Ͱͳ͘σʔλͱͯ͠ѻ͍΍͘͢

  16. ͋Γ͕ͱ͏͍͟͝·ͨ͠ɻ ͥͻ͝ҙݟΛԼ͍͞ɻ