Faraday: POST ๋ฐฉ์‹์œผ๋กœ ์žฌ์‹œ๋„๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•

์— ๋งŒ๋“  2018๋…„ 03์›” 12์ผ  ยท  3์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: lostisland/faraday

๊ธฐ๋ณธ ์ •๋ณด

  • ํŒจ๋Ÿฌ๋ฐ์ด ๋ฒ„์ „:
    ํŒจ๋Ÿฌ๋ฐ์ด (0.11.0)
    ํŒจ๋Ÿฌ๋ฐ์ด_๋ฏธ๋“ค์›จ์–ด(0.11.0.1)
    faraday_middleware-aws-signers-v4(0.1.5)

  • ๋ฃจ๋น„ ๋ฒ„์ „:
    ๋ฃจ๋น„ 2.3.0p0 (2015-12-25 ๊ฐœ์ •ํŒ 53290) [x86_64-darwin15]

๋ฌธ์ œ ์„ค๋ช…

์ผ๋ถ€ API์— ์•ก์„ธ์Šคํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์žˆ๊ณ  get ๋ฉ”์„œ๋“œ์™€ ํ•จ๊ป˜ ํŒจ๋Ÿฌ๋ฐ์ด ์—ฐ๊ฒฐ์„ ์‚ฌ์šฉํ•˜๊ณ  ์žฌ์‹œ๋„๋ฅผ ์„ค์ •ํ•˜๊ณ  ๋ชจ๋“  ๊ฒƒ์ด ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๊ณ  ๋ฉ”์„œ๋“œ๋ฅผ ๊ฒŒ์‹œ ๋กœ ๋ณ€๊ฒฝํ•œ ๋‹ค์Œ ์žฌ์‹œ๋„๊ฐ€ ์ž‘๋™์„ ๋ฉˆ์ท„์Šต๋‹ˆ๋‹ค. ๊ตฌ๊ธ€๋ง์„ ํ•ด๋ณด๋‹ˆ ๊ฒŒ์‹œ๋ฌผ ์ด ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์„ ์ดํ•ดํ–ˆ์Šต๋‹ˆ๋‹ค. ์— ํฌํ•จ

IDEMPOTENT_METHODS = [:delete, :get, :head, :options, :put]

์ฐธ์กฐ: https://github.com/lostisland/faraday/pull/437/files
POST๋ฅผ ๋‹ค์‹œ ์‹œ๋„ํ•˜๊ณ  ์‹ถ์ง€๋งŒ ๋ฌธ์„œ dor retry_if ๋ฅผ ์ฐพ์ง€ ๋ชปํ•œ ๊ฒฝ์šฐ retry_if ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ๋‚ด ์—ฐ๊ฒฐ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    def my_connection(my_api_endpoint)
      Faraday.new(url: my_api_endpoint) do |faraday|
        faraday.request  :retry, max: 5, exceptions:
          [BadRequest, NotFound, ServerError, Faraday::Error::ConnectionFailed]
         faraday.response :logger
         faraday.adapter  Faraday.default_adapter
         faraday.options[:open_timeout] = 10
      end
    end

๋‹ค์Œ๊ณผ ๊ฐ™์ด ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

  res = my_connection(my_api_endpoint).post do |req|
    req.headers['Content-Type'] = 'application/json'
    req.options.timeout = 25
    req.body = body.to_json
  end

์–ด๋–ค ๋„์›€์ด๋ผ๋„ ๋งค์šฐ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

@yusefu ํ”ผ๋“œ๋ฐฑ์— ๊ฐ์‚ฌ๋“œ๋ฆฌ๋ฉฐ TypeError์— ๋Œ€ํ•ด ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค.
๋ฌธ์ œ๋Š” @connections ๊ฐ€ ๋ฐฐ์—ด์ด ์•„๋‹ˆ๋ผ ํ•ด์‹œ์—ฌ์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

<strong i="9">@connections</strong> ||= {}

์–ด์จŒ๋“  ์ด์ œ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์–ด ๊ธฐ์ฉ๋‹ˆ๋‹ค ๐Ÿ‘!

๋ชจ๋“  3 ๋Œ“๊ธ€

์•ˆ๋…•ํ•˜์„ธ์š” @yusefu , ๋ฌธ์„œ ๋ถ€์กฑ์— ๋Œ€ํ•ด ์‚ฌ๊ณผ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ v1.0์—์„œ ํ•ด๊ฒฐํ•˜๋ ค๊ณ  ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
๊ทธ๋™์•ˆ ๋ฌธ์ œ๋ฅผ ๋„์™€๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ retry_if ๋Š” max: 5, exceptions: [BadRequest, NotFound, ServerError, Faraday::Error::ConnectionFailed] ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ •ํ™•ํžˆ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ์˜ต์…˜์ž…๋‹ˆ๋‹ค. ์œ ์ผํ•œ ์ฐจ์ด์ ์€ retry_if ๋Š” ํ•จ์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(๋žŒ๋‹ค ๋˜๋Š” proc.
๊ทธ๊ฒƒ๋“ค์— ์ต์ˆ™ํ•˜์ง€ ์•Š๋‹ค๋ฉด Proc.new { ... } ๋˜๋Š” ์—ฌ๋Ÿฌ ์ค„ Proc.new do ... end ๋กœ ์ธ์Šคํ„ด์Šคํ™”ํ•  ์ˆ˜ ์žˆ๋Š” proc ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ retry_if ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ฒฝ์šฐ ์˜ˆ์ œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

def my_connection(my_api_endpoint)
  # This is optional, I've added the <strong i="17">@connections</strong> memoized variable to avoid
  # re-creating the connection every time. Not sure it's applicable to your case
  # but consider it as it might improve performances
  <strong i="18">@connections</strong> ||= []
  @connections[my_api_endpoint] ||= Faraday.new(url: my_api_endpoint) do |faraday|
    faraday.request  :retry, max: 5, exceptions:
      [BadRequest, NotFound, ServerError, Faraday::Error::ConnectionFailed],
      retry_if: Proc.new do |env, exception|
        # your implementation goes here...
      end
     faraday.response :logger
     faraday.adapter  Faraday.default_adapter
     faraday.options[:open_timeout] = 10
  end
end

๊ทธ๋Ÿฌ๋‚˜ ์œ ์ผํ•œ ๋ชฉํ‘œ๊ฐ€ ์žฌ์‹œ๋„ ๋ฐฉ๋ฒ• ๋ชฉ๋ก์— :post๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด๋ผ๋ฉด ๋งํฌํ•œ ํ•ด๋‹น PR์— ์ถ”๊ฐ€๋œ methods ์˜ต์…˜์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

def my_connection(my_api_endpoint)
  # This is optional, I've added the <strong i="23">@connections</strong> memoized variable to avoid
  # re-creating the connection every time. Not sure it's applicable to your case
  # but consider it as it might improve performances
  <strong i="24">@connections</strong> ||= []
  @connections[my_api_endpoint] ||= Faraday.new(url: my_api_endpoint) do |faraday|
    faraday.request  :retry, max: 5, exceptions:
      [BadRequest, NotFound, ServerError, Faraday::Error::ConnectionFailed],
      methods: Faraday::Request::Retry::IDEMPOTENT_METHODS + [:post]
     faraday.response :logger
     faraday.adapter  Faraday.default_adapter
     faraday.options[:open_timeout] = 10
  end
end

๋„์›€์ด ๋˜์…จ๋‹ค๋ฉด ์•Œ๋ ค์ฃผ์„ธ์š” ๐Ÿ˜„

์—ฐ๊ฒฐ ์ธ์Šคํ„ด์Šค์—์„œ TypeError๊ฐ€ ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.

expected MyAPI::BadRequest, got #<TypeError: {:req=>{}, :res=>nil, :headers=>nil, :reason_phrase=>nil}> with backtrace:

๊ทธ๋Ÿฌ๋‚˜ IDEMPOTENT_METHODS์— ๊ฒŒ์‹œ๋ฌผ ์„ ๊ฐ„๋‹จํžˆ ์ถ”๊ฐ€ํ•˜๋ฉด ์ด์ œ ์žฌ์‹œ๋„ ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
@iMacTia ๐Ÿ™ ์ •๋ง ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค.

@yusefu ํ”ผ๋“œ๋ฐฑ์— ๊ฐ์‚ฌ๋“œ๋ฆฌ๋ฉฐ TypeError์— ๋Œ€ํ•ด ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค.
๋ฌธ์ œ๋Š” @connections ๊ฐ€ ๋ฐฐ์—ด์ด ์•„๋‹ˆ๋ผ ํ•ด์‹œ์—ฌ์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

<strong i="9">@connections</strong> ||= {}

์–ด์จŒ๋“  ์ด์ œ ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋˜์–ด ๊ธฐ์ฉ๋‹ˆ๋‹ค ๐Ÿ‘!

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰