iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
Software Development

在 Ruby on Rails 中導入 Domain-Driven Design 是不是搞錯了什麼?系列 第 21

[DAY21] 非同步的 Boxenn Use Case

在實務中,常常會有花很長執行時間、或需要排程的邏輯,這時候便會需要進行非同步處理。

在 Boxenn Use Case 上擴充 sidekiq worker

sidekiq worker 的介面需要 perform 這個 method,而對於 Boxenn::UseCase 來說,他原本對外就只有 call 這個 public method,因此擴充的方法很簡單,只需要額外定義 perform 讓他呼叫 call 就可以了。

module Worker
  def self.included(base)
    base.send(:include, Sidekiq::Worker)
  end

  def perform(*params)
    result = if params.empty?
               call
             else
               call(serialize(*params))
             end
    return if result.success?

		# error handle
    message = Array(result.failure).map(&:to_s).join(', ')
    Rollbar.error(message, trace: result.trace)
    raise StandardError, message
  end

  private

  def serialize(params)
    params.transform_keys(&:to_sym)
  end
end

使用方法

只需要在原本的 Use Case 多 include 上面所寫的 Worker 就可以使用了。

class YourWorker < Boxenn::UseCase # inherit Boxenn::Usecase
  include Worker # include Worker for asynchronize purpose
	sidekiq_options queue: :default # setting sidekiq options

  def steps(params1:, params2:)
    result = action1(params1: params1, params2: params2)
    Success(result)
  end

  private

  def action1(params1:, params2:)
    # DO SOMETHING
  end
end

# calling use case asynchronize
YourWorker.perform_async(params1: params1, params2: params2)

# calling use case synchronous
YourWorker.new.call(params1: params1, params2: params2)

sidekiq options

Sidekiq Best Practice

  • 參數盡量傳簡單的 identifier (原生 ruby type),而不是整個 object。

    Sidekiq 會把參數會先轉為 json 存進 redis,等到要執行時再序列化為 ruby object,因此如果原本的參數不是原生型態,不但需要更多時間序列化,甚至有可能出現序列化錯誤的問題。

    # BAD
    user = User.find(user_id)
    SomeWorker.perform_async(user)
    
    # GOOD
    SomeWorker.perform_async(user_id)
    
  • 用 perform_async 代替 delay extension,delay extension 主要缺點有兩個:

    1. 傳的參數太複雜時有可能造成 redis timeout,因為 sidekiq 是用 yml 來序列化參數,傳太複雜的 ruby object 會讓 payload 很大。
    2. 會在 class 上額外加 method。

下一篇會介紹如何對 Boxenn::UseCase 進行測試。


上一篇
[DAY20] Domain 間的依賴關係
下一篇
[DAY22] Boxenn Use Case Spec
系列文
在 Ruby on Rails 中導入 Domain-Driven Design 是不是搞錯了什麼?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言