From 4cc093fe92f600e2f85292925111133d2fba3586 Mon Sep 17 00:00:00 2001 From: Andrey Paderin Date: Fri, 27 Dec 2024 04:27:39 +0300 Subject: [PATCH 1/2] hw3 --- .../app/controllers/orders_controller.rb | 24 ++++++++++++++++- day_2/tn_rails_concurrent/app/models/order.rb | 2 +- .../20241226023934_add_index_to_orders.rb | 6 +++++ ...41226024546_add_orders_count_to_product.rb | 5 ++++ .../20241227012439_add_fn_index_to_orders.rb | 6 +++++ day_2/tn_rails_concurrent/db/structure.sql | 27 ++++++++++++++++++- 6 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 day_2/tn_rails_concurrent/db/migrate/20241226023934_add_index_to_orders.rb create mode 100644 day_2/tn_rails_concurrent/db/migrate/20241226024546_add_orders_count_to_product.rb create mode 100644 day_2/tn_rails_concurrent/db/migrate/20241227012439_add_fn_index_to_orders.rb diff --git a/day_2/tn_rails_concurrent/app/controllers/orders_controller.rb b/day_2/tn_rails_concurrent/app/controllers/orders_controller.rb index 80cd997..85ecae4 100644 --- a/day_2/tn_rails_concurrent/app/controllers/orders_controller.rb +++ b/day_2/tn_rails_concurrent/app/controllers/orders_controller.rb @@ -1,6 +1,28 @@ +# frozen_string_literal: true class OrdersController < ApplicationController def top_products_report - top_products = Order.all + top_products = Order + .with( + daily_orders: Order + .select('product_id, DATE(created_at) AS order_date, SUM(quantity) AS total_quantity') + .group('product_id, DATE(created_at)'), + ) + .from('daily_orders AS d') + .joins(<<~SQL.squish) + LEFT JOIN products AS p ON d.product_id = p.id + AND d.total_quantity = p.orders_count + SQL + .select('d.order_date, d.product_id, d.total_quantity') + .order(total_quantity: :desc ) + .limit(10) + .map do |row| + { + date: row.order_date, + product_id: row.product_id, + total_quantity: row.total_quantity, + } + end + render json: top_products end end diff --git a/day_2/tn_rails_concurrent/app/models/order.rb b/day_2/tn_rails_concurrent/app/models/order.rb index efe9965..3b2f06c 100644 --- a/day_2/tn_rails_concurrent/app/models/order.rb +++ b/day_2/tn_rails_concurrent/app/models/order.rb @@ -10,7 +10,7 @@ # updated_at :datetime not null # class Order < ApplicationRecord - belongs_to :product + belongs_to :product, counter_cache: true scope :pending, -> { where(current_status: :pending) } scope :processed, -> { where(current_status: :processed) } diff --git a/day_2/tn_rails_concurrent/db/migrate/20241226023934_add_index_to_orders.rb b/day_2/tn_rails_concurrent/db/migrate/20241226023934_add_index_to_orders.rb new file mode 100644 index 0000000..ac2f559 --- /dev/null +++ b/day_2/tn_rails_concurrent/db/migrate/20241226023934_add_index_to_orders.rb @@ -0,0 +1,6 @@ +class AddIndexToOrders < ActiveRecord::Migration[7.1] + disable_ddl_transaction! + def change + add_index :orders, :product_id, algorithm: :concurrently + end +end diff --git a/day_2/tn_rails_concurrent/db/migrate/20241226024546_add_orders_count_to_product.rb b/day_2/tn_rails_concurrent/db/migrate/20241226024546_add_orders_count_to_product.rb new file mode 100644 index 0000000..1735703 --- /dev/null +++ b/day_2/tn_rails_concurrent/db/migrate/20241226024546_add_orders_count_to_product.rb @@ -0,0 +1,5 @@ +class AddOrdersCountToProduct < ActiveRecord::Migration[7.1] + def change + add_column :products, :orders_count, :integer, default: 0, null: false + end +end diff --git a/day_2/tn_rails_concurrent/db/migrate/20241227012439_add_fn_index_to_orders.rb b/day_2/tn_rails_concurrent/db/migrate/20241227012439_add_fn_index_to_orders.rb new file mode 100644 index 0000000..dc19d00 --- /dev/null +++ b/day_2/tn_rails_concurrent/db/migrate/20241227012439_add_fn_index_to_orders.rb @@ -0,0 +1,6 @@ +class AddFnIndexToOrders < ActiveRecord::Migration[7.1] + disable_ddl_transaction! + def change + add_index :orders, 'DATE(created_at)', name: 'index_orders_on_created_at_date', algorithm: :concurrently + end +end diff --git a/day_2/tn_rails_concurrent/db/structure.sql b/day_2/tn_rails_concurrent/db/structure.sql index 3e25355..0fea3ec 100644 --- a/day_2/tn_rails_concurrent/db/structure.sql +++ b/day_2/tn_rails_concurrent/db/structure.sql @@ -9,6 +9,13 @@ SET xmloption = content; SET client_min_messages = warning; SET row_security = off; +-- +-- Name: public; Type: SCHEMA; Schema: -; Owner: - +-- + +-- *not* creating schema, since initdb creates it + + -- -- Name: order_status; Type: TYPE; Schema: public; Owner: - -- @@ -79,7 +86,8 @@ CREATE TABLE public.products ( stock integer, price numeric, created_at timestamp(6) without time zone NOT NULL, - updated_at timestamp(6) without time zone NOT NULL + updated_at timestamp(6) without time zone NOT NULL, + orders_count integer DEFAULT 0 NOT NULL ); @@ -157,6 +165,20 @@ ALTER TABLE ONLY public.schema_migrations ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version); +-- +-- Name: index_orders_on_created_at_date; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_orders_on_created_at_date ON public.orders USING btree (date(created_at)); + + +-- +-- Name: index_orders_on_product_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_orders_on_product_id ON public.orders USING btree (product_id); + + -- -- PostgreSQL database dump complete -- @@ -164,6 +186,9 @@ ALTER TABLE ONLY public.schema_migrations SET search_path TO "$user", public; INSERT INTO "schema_migrations" (version) VALUES +('20241227012439'), +('20241226024546'), +('20241226023934'), ('20241216120643'), ('20241216120641'); From 493e7bcaddc285dec873095e321be09eb4b85168 Mon Sep 17 00:00:00 2001 From: Andrey Paderin Date: Wed, 12 Aug 2026 23:01:53 +0300 Subject: [PATCH 2/2] chore: day_2 workshop tweaks (compose, seeds, rake task) Co-Authored-By: Claude Fable 5 --- day_2/tn_rails_concurrent/Gemfile | 5 ++++- day_2/tn_rails_concurrent/Gemfile.lock | 11 ++++++++++- day_2/tn_rails_concurrent/config/database.yml | 4 ++++ day_2/tn_rails_concurrent/db/seeds.rb | 10 +++++----- day_2/tn_rails_concurrent/docker-compose.yml | 2 ++ .../lib/tasks/task_to_be_optimized.rake | 2 +- 6 files changed, 26 insertions(+), 8 deletions(-) diff --git a/day_2/tn_rails_concurrent/Gemfile b/day_2/tn_rails_concurrent/Gemfile index b6d6d35..aeaa177 100644 --- a/day_2/tn_rails_concurrent/Gemfile +++ b/day_2/tn_rails_concurrent/Gemfile @@ -1,6 +1,7 @@ source "https://rubygems.org" -ruby "3.2.2" +# ruby "3.4.0.preview1" +ruby "3.2.6" gem "rails", "~> 7.1.4" gem "sprockets-rails" @@ -15,6 +16,8 @@ gem "bootsnap", require: false group :development, :test do gem "debug", platforms: %i[ mri windows ] + gem 'pry' + gem 'pry-rails' end group :development do diff --git a/day_2/tn_rails_concurrent/Gemfile.lock b/day_2/tn_rails_concurrent/Gemfile.lock index 1d38d4b..afe91f1 100644 --- a/day_2/tn_rails_concurrent/Gemfile.lock +++ b/day_2/tn_rails_concurrent/Gemfile.lock @@ -90,6 +90,7 @@ GEM bootsnap (1.18.4) msgpack (~> 1.2) builder (3.3.0) + coderay (1.1.3) concurrent-ruby (1.3.4) connection_pool (2.4.1) crass (1.0.6) @@ -121,6 +122,7 @@ GEM net-pop net-smtp marcel (1.0.4) + method_source (1.1.0) mini_mime (1.1.5) mini_portile2 (2.8.8) minitest (5.25.4) @@ -145,6 +147,11 @@ GEM racc (~> 1.4) parallel (1.26.3) pg (1.5.8) + pry (0.15.2) + coderay (~> 1.1) + method_source (~> 1.0) + pry-rails (0.3.11) + pry (>= 0.13.0) psych (5.2.1) date stringio @@ -240,6 +247,8 @@ DEPENDENCIES importmap-rails parallel (~> 1.26.3) pg + pry + pry-rails puma (>= 5.0) rails (~> 7.1.4) sidekiq (~> 7.3.6) @@ -250,7 +259,7 @@ DEPENDENCIES web-console RUBY VERSION - ruby 3.2.2p53 + ruby 3.2.6p234 BUNDLED WITH 2.4.22 diff --git a/day_2/tn_rails_concurrent/config/database.yml b/day_2/tn_rails_concurrent/config/database.yml index 8d45976..5f53277 100644 --- a/day_2/tn_rails_concurrent/config/database.yml +++ b/day_2/tn_rails_concurrent/config/database.yml @@ -1,6 +1,10 @@ default: &default adapter: postgresql encoding: unicode + # host: localhost + # port: 5431 + # username: postgres + # password: password wait_timeout: 900 # 15 minutes. timeout: 10000 # 5 seconds. pool: <%= ENV.fetch("RAILS_MAX_THREADS", 5).to_i + 10 + ENV.fetch("SIDEKIQ_CONCURENNCY", 2).to_i %> diff --git a/day_2/tn_rails_concurrent/db/seeds.rb b/day_2/tn_rails_concurrent/db/seeds.rb index 0de8a9b..b573b4d 100644 --- a/day_2/tn_rails_concurrent/db/seeds.rb +++ b/day_2/tn_rails_concurrent/db/seeds.rb @@ -1,7 +1,7 @@ -Order.destroy_all -puts "Orders destroyed" -Product.destroy_all -puts "Products destroyed" +# Order.destroy_all +# puts "Orders destroyed" +# Product.destroy_all +# puts "Products destroyed" Product.insert_all(Array.new(100) { { name: "Product #{rand(1..1000)}", stock: rand(1..50), price: rand(10..100) } }) puts "Products created: #{Product.count}" @@ -10,7 +10,7 @@ statuses = ["pending", "processed", "cancelled"] dates = (1..30).map { |n| n.days.ago } ActiveRecord::Base.record_timestamps = false -Order.insert_all(Array.new(20_000) { +Order.insert_all(Array.new(200_000) { { product_id: product_ids.sample, quantity: rand(1..10), current_status: statuses.sample, diff --git a/day_2/tn_rails_concurrent/docker-compose.yml b/day_2/tn_rails_concurrent/docker-compose.yml index 553298e..57a7b8c 100644 --- a/day_2/tn_rails_concurrent/docker-compose.yml +++ b/day_2/tn_rails_concurrent/docker-compose.yml @@ -15,3 +15,5 @@ services: environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: password + ports: + - 5432:5432 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..f67fb4e 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 @@ -38,7 +38,7 @@ namespace :orders do end def send_to_external_service - uri = URI.parse("https://yandex.ru") + uri = URI.parse("https://yandex.ru/") sleep 0.1 http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true if uri.scheme == 'https'