Redo simulations lifecycle (#222)
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Run unit tests / rubocop (push) Successful in 27s
				
			
		
			
				
	
				Run unit tests / check-licenses (push) Successful in 32s
				
			
		
			
				
	
				Run unit tests / copyright_notice (push) Successful in 36s
				
			
		
			
				
	
				Run unit tests / unit_tests (push) Successful in 1m22s
				
			
		
			
				
	
				Run unit tests / build-static-assets (push) Successful in 10m9s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Run unit tests / rubocop (push) Successful in 27s
				
			Run unit tests / check-licenses (push) Successful in 32s
				
			Run unit tests / copyright_notice (push) Successful in 36s
				
			Run unit tests / unit_tests (push) Successful in 1m22s
				
			Run unit tests / build-static-assets (push) Successful in 10m9s
				
			## Why The current way of creating and deleting simulations doesn't scale for big instances. We cannot generate 50 simulations every time a guest confirms attendance, and we should not delete existing valuable simulations. For example, if a guest confirms attendance and declines right after, previously generated simulations should still be valid. ## What In this PR we are introducing a series of changes that make simulations management easier: 1. We're removing the automatic creation of simulations. 2. Simulations are not removed anymore, neither manually nor automatically. 3. A new endpoint has been defined to create simulations on demand. 4. A digest property has been defined to determine whether a simulation is still valid (meaning there have not been any change in the list of guests involved). Reviewed-on: #222 Co-authored-by: Manuel Bustillo <bustikiller@bustikiller.com> Co-committed-by: Manuel Bustillo <bustikiller@bustikiller.com>
This commit is contained in:
		
							parent
							
								
									f414acb2d5
								
							
						
					
					
						commit
						2147d7ad5e
					
				| @ -4,7 +4,15 @@ | |||||||
| 
 | 
 | ||||||
| class TablesArrangementsController < ApplicationController | class TablesArrangementsController < ApplicationController | ||||||
|   def index |   def index | ||||||
|     render json: TablesArrangement.order(discomfort: :asc).limit(3).as_json(only: %i[id name discomfort]) |     current_digest = Tables::Distribution.digest(current_tenant) | ||||||
|  | 
 | ||||||
|  |     render json: TablesArrangement | ||||||
|  |       .order(valid: :desc) | ||||||
|  |       .order(discomfort: :asc) | ||||||
|  |       .select(:id, :name, :discomfort) | ||||||
|  |       .select("digest = '#{current_digest}'::uuid as valid") | ||||||
|  |       .limit(20) | ||||||
|  |       .as_json(only: %i[id name discomfort valid]) | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   def show |   def show | ||||||
| @ -16,6 +24,12 @@ class TablesArrangementsController < ApplicationController | |||||||
|          .then { |result| render json: { id: params[:id], tables: result } } |          .then { |result| render json: { id: params[:id], tables: result } } | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  |   def create | ||||||
|  |     TableSimulatorJob.perform_later(current_tenant.id) | ||||||
|  | 
 | ||||||
|  |     render json: {}, status: :created | ||||||
|  |   end | ||||||
|  | 
 | ||||||
|   private |   private | ||||||
| 
 | 
 | ||||||
|   def format(number:, guests:) |   def format(number:, guests:) | ||||||
|  | |||||||
| @ -41,16 +41,5 @@ class Guest < ApplicationRecord | |||||||
| 
 | 
 | ||||||
|   scope :potential, -> { where.not(status: %i[declined considered]) } |   scope :potential, -> { where.not(status: %i[declined considered]) } | ||||||
| 
 | 
 | ||||||
|   after_destroy :recalculate_simulations |  | ||||||
|   after_save :recalculate_simulations, if: :saved_change_to_status? |  | ||||||
| 
 |  | ||||||
|   has_many :seats, dependent: :delete_all |   has_many :seats, dependent: :delete_all | ||||||
| 
 |  | ||||||
|   private |  | ||||||
| 
 |  | ||||||
|   def recalculate_simulations |  | ||||||
|     TablesArrangement.delete_all |  | ||||||
| 
 |  | ||||||
|     ActiveJob.perform_all_later(50.times.map { TableSimulatorJob.new(wedding_id) }) |  | ||||||
|   end |  | ||||||
| end | end | ||||||
|  | |||||||
| @ -7,6 +7,7 @@ | |||||||
| # Table name: tables_arrangements | # Table name: tables_arrangements | ||||||
| # | # | ||||||
| #  id         :uuid             not null, primary key | #  id         :uuid             not null, primary key | ||||||
|  | #  digest     :uuid             not null | ||||||
| #  discomfort :integer | #  discomfort :integer | ||||||
| #  name       :string           not null | #  name       :string           not null | ||||||
| #  created_at :datetime         not null | #  created_at :datetime         not null | ||||||
|  | |||||||
| @ -19,4 +19,6 @@ class Wedding < ApplicationRecord | |||||||
|   SLUG_REGEX = /[a-z\d-]+/ |   SLUG_REGEX = /[a-z\d-]+/ | ||||||
| 
 | 
 | ||||||
|   validates :slug, presence: true, uniqueness: true, format: { with: /\A#{SLUG_REGEX}\z/ } |   validates :slug, presence: true, uniqueness: true, format: { with: /\A#{SLUG_REGEX}\z/ } | ||||||
|  | 
 | ||||||
|  |   has_many :guests, dependent: :delete_all | ||||||
| end | end | ||||||
|  | |||||||
| @ -6,7 +6,13 @@ require_relative '../../extensions/tree_node_extension' | |||||||
| 
 | 
 | ||||||
| module Tables | module Tables | ||||||
|   class Distribution |   class Distribution | ||||||
|     attr_accessor :tables, :min_per_table, :max_per_table |     class << self | ||||||
|  |       def digest(wedding) | ||||||
|  |         Digest::UUID.uuid_v5(wedding.id, wedding.guests.potential.order(:id).pluck(:id).join) | ||||||
|  |       end | ||||||
|  |     end | ||||||
|  | 
 | ||||||
|  |     attr_accessor :tables, :min_per_table, :max_per_table, :hierarchy | ||||||
| 
 | 
 | ||||||
|     def initialize(min_per_table:, max_per_table:) |     def initialize(min_per_table:, max_per_table:) | ||||||
|       @min_per_table = min_per_table |       @min_per_table = min_per_table | ||||||
| @ -54,7 +60,10 @@ module Tables | |||||||
| 
 | 
 | ||||||
|         Seat.insert_all!(records_to_store) |         Seat.insert_all!(records_to_store) | ||||||
| 
 | 
 | ||||||
|         arrangement.update!(discomfort:) |         arrangement.update!( | ||||||
|  |           discomfort:, | ||||||
|  |           digest: self.class.digest(tables.first.first.wedding) | ||||||
|  |         ) | ||||||
|       end |       end | ||||||
|     end |     end | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -37,7 +37,7 @@ Rails.application.routes.draw do | |||||||
|     resources :expenses, only: %i[index create update destroy] do |     resources :expenses, only: %i[index create update destroy] do | ||||||
|       get :summary, on: :collection |       get :summary, on: :collection | ||||||
|     end |     end | ||||||
|     resources :tables_arrangements, only: %i[index show] |     resources :tables_arrangements, only: %i[index show create] | ||||||
|     resources :summary, only: :index |     resources :summary, only: :index | ||||||
| 
 | 
 | ||||||
|     root to: redirect("/%{slug}") |     root to: redirect("/%{slug}") | ||||||
|  | |||||||
| @ -0,0 +1,5 @@ | |||||||
|  | class AddGuestsDigestColumnToTablesArrangements < ActiveRecord::Migration[8.0] | ||||||
|  |   def change | ||||||
|  |     add_column :tables_arrangements, :digest, :uuid, null: false, default: 'gen_random_uuid()' | ||||||
|  |   end | ||||||
|  | end | ||||||
							
								
								
									
										3
									
								
								db/schema.rb
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										3
									
								
								db/schema.rb
									
									
									
										generated
									
									
									
								
							| @ -10,7 +10,7 @@ | |||||||
| # | # | ||||||
| # It's strongly recommended that you check this file into your version control system. | # It's strongly recommended that you check this file into your version control system. | ||||||
| 
 | 
 | ||||||
| ActiveRecord::Schema[8.0].define(version: 2024_12_16_231415) do | ActiveRecord::Schema[8.0].define(version: 2025_01_26_091823) do | ||||||
|   # These are extensions that must be enabled in order to support this database |   # These are extensions that must be enabled in order to support this database | ||||||
|   enable_extension "pg_catalog.plpgsql" |   enable_extension "pg_catalog.plpgsql" | ||||||
| 
 | 
 | ||||||
| @ -206,6 +206,7 @@ ActiveRecord::Schema[8.0].define(version: 2024_12_16_231415) do | |||||||
|     t.datetime "updated_at", null: false |     t.datetime "updated_at", null: false | ||||||
|     t.string "name", null: false |     t.string "name", null: false | ||||||
|     t.uuid "wedding_id", null: false |     t.uuid "wedding_id", null: false | ||||||
|  |     t.uuid "digest", default: -> { "gen_random_uuid()" }, null: false | ||||||
|     t.index ["wedding_id"], name: "index_tables_arrangements_on_wedding_id" |     t.index ["wedding_id"], name: "index_tables_arrangements_on_wedding_id" | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -18,13 +18,27 @@ RSpec.describe 'tables_arrangements' do | |||||||
|                  properties: { |                  properties: { | ||||||
|                    id: { type: :string, format: :uuid }, |                    id: { type: :string, format: :uuid }, | ||||||
|                    name: { type: :string }, |                    name: { type: :string }, | ||||||
|                    discomfort: { type: :integer } |                    discomfort: { type: :integer }, | ||||||
|  |                    valid: { type: :boolean } | ||||||
|                  } |                  } | ||||||
|                } |                } | ||||||
|         xit |         xit | ||||||
|       end |       end | ||||||
|       regular_api_responses |       regular_api_responses | ||||||
|     end |     end | ||||||
|  | 
 | ||||||
|  |     post('create tables arrangement') do | ||||||
|  |       tags 'Tables Arrangements' | ||||||
|  |       produces 'application/json' | ||||||
|  |       parameter Swagger::Schema::SLUG | ||||||
|  |       response(201, 'successful') do | ||||||
|  |         schema type: :object, | ||||||
|  |                required: [], | ||||||
|  |                properties: {} | ||||||
|  |         xit | ||||||
|  |       end | ||||||
|  |       regular_api_responses | ||||||
|  |     end | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   path '/{slug}/tables_arrangements/{id}' do |   path '/{slug}/tables_arrangements/{id}' do | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user