diff --git a/day_2/tn_rails_concurrent/Gemfile b/day_2/tn_rails_concurrent/Gemfile index b6d6d35..07453d2 100644 --- a/day_2/tn_rails_concurrent/Gemfile +++ b/day_2/tn_rails_concurrent/Gemfile @@ -23,6 +23,7 @@ group :development do end gem "parallel", "~> 1.26.3" +gem "async" gem "sidekiq", "~> 7.3.6" gem "activerecord-import", "~> 2.0" diff --git a/day_2/tn_rails_concurrent/Gemfile.lock b/day_2/tn_rails_concurrent/Gemfile.lock index 1d38d4b..a7cff76 100644 --- a/day_2/tn_rails_concurrent/Gemfile.lock +++ b/day_2/tn_rails_concurrent/Gemfile.lock @@ -83,6 +83,10 @@ GEM annotate (3.2.0) activerecord (>= 3.2, < 8.0) rake (>= 10.4, < 14.0) + async (2.21.1) + console (~> 1.29) + fiber-annotation + io-event (~> 1.6, >= 1.6.5) base64 (0.2.0) benchmark (0.4.0) bigdecimal (3.1.8) @@ -92,6 +96,10 @@ GEM builder (3.3.0) concurrent-ruby (1.3.4) connection_pool (2.4.1) + console (1.29.2) + fiber-annotation + fiber-local (~> 1.1) + json crass (1.0.6) date (3.4.1) debug (1.9.2) @@ -99,6 +107,10 @@ GEM reline (>= 0.3.8) drb (2.2.1) erubi (1.13.0) + fiber-annotation (0.2.0) + fiber-local (1.1.0) + fiber-storage + fiber-storage (1.0.0) globalid (1.2.1) activesupport (>= 6.1) i18n (1.14.6) @@ -108,9 +120,11 @@ GEM activesupport (>= 6.0.0) railties (>= 6.0.0) io-console (0.8.0) + io-event (1.7.5) irb (1.14.2) rdoc (>= 4.0.0) reline (>= 0.4.2) + json (2.9.1) logger (1.6.3) loofah (2.23.1) crass (~> 1.0.2) @@ -235,6 +249,7 @@ PLATFORMS DEPENDENCIES activerecord-import (~> 2.0) annotate + async bootsnap debug importmap-rails diff --git a/day_2/tn_rails_concurrent/lib/tasks/task_to_be_optimized.rake b/day_2/tn_rails_concurrent/lib/tasks/task_to_be_optimized.rake index cefe94c..1cd9a01 100644 --- a/day_2/tn_rails_concurrent/lib/tasks/task_to_be_optimized.rake +++ b/day_2/tn_rails_concurrent/lib/tasks/task_to_be_optimized.rake @@ -9,13 +9,17 @@ namespace :orders do Order.destroy_all # Оптимизировать тут - Array.new(200) { Order.create!(product_id: rand(1..100), quantity: rand(1..10), current_status: :pending) } + Parallel.map(Array.new(200)) do + { product_id: rand(1..100), quantity: rand(1..10), current_status: :pending } + end.tap { Order.insert_all(_1) } time = Benchmark.realtime do puts Order.pending.count # Оптимизировать тут - Order.pending.find_in_batches(batch_size: 50) do |batch| - process_batch_with_http(batch) + Async do + Order.pending.find_in_batches(batch_size: 50) do |batch| + Async { process_batch_with_http(batch) } + end end end @@ -24,16 +28,18 @@ namespace :orders do def process_batch_with_http(batch) batch.each do |order| - # Оптимизировать тут - response = send_to_external_service - if response.code.to_i == 200 - order.process! - puts "Successfully processed Order ##{order.id}" - else - raise "Failed to process Order ##{order.id}: #{response.body}" + Async do + # Оптимизировать тут + response = send_to_external_service + if response.code.to_i == 200 + order.process! + puts "Successfully processed Order ##{order.id}" + else + raise "Failed to process Order ##{order.id}: #{response.body}" + end + rescue StandardError => e + Rails.logger.error("Error processing Order ##{order.id}: #{e.message}") end - rescue StandardError => e - Rails.logger.error("Error processing Order ##{order.id}: #{e.message}") end end @@ -47,3 +53,8 @@ namespace :orders do http.request(request) end end + +# Processed orders in 20.1 seconds with HTTP request (перед оптимизацией) +# Processed orders in 0.11 seconds with HTTP request (async при io bound) +# Processed orders in 0.2 seconds with HTTP request (thread при io bound) +# Processed orders in 0.24 seconds with HTTP request (parallel (для параллельного запуска обработки каждого заказа в батче) + async (для обработки каждого заказа) при io bound)