[scala] Extract the async execution logic in a trait for reusability