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 | ||||
|   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 | ||||
| 
 | ||||
|   def show | ||||
| @ -16,6 +24,12 @@ class TablesArrangementsController < ApplicationController | ||||
|          .then { |result| render json: { id: params[:id], tables: result } } | ||||
|   end | ||||
| 
 | ||||
|   def create | ||||
|     TableSimulatorJob.perform_later(current_tenant.id) | ||||
| 
 | ||||
|     render json: {}, status: :created | ||||
|   end | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def format(number:, guests:) | ||||
|  | ||||
| @ -41,16 +41,5 @@ class Guest < ApplicationRecord | ||||
| 
 | ||||
|   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 | ||||
| 
 | ||||
|   private | ||||
| 
 | ||||
|   def recalculate_simulations | ||||
|     TablesArrangement.delete_all | ||||
| 
 | ||||
|     ActiveJob.perform_all_later(50.times.map { TableSimulatorJob.new(wedding_id) }) | ||||
|   end | ||||
| end | ||||
|  | ||||
| @ -7,6 +7,7 @@ | ||||
| # Table name: tables_arrangements | ||||
| # | ||||
| #  id         :uuid             not null, primary key | ||||
| #  digest     :uuid             not null | ||||
| #  discomfort :integer | ||||
| #  name       :string           not null | ||||
| #  created_at :datetime         not null | ||||
|  | ||||
| @ -19,4 +19,6 @@ class Wedding < ApplicationRecord | ||||
|   SLUG_REGEX = /[a-z\d-]+/ | ||||
| 
 | ||||
|   validates :slug, presence: true, uniqueness: true, format: { with: /\A#{SLUG_REGEX}\z/ } | ||||
| 
 | ||||
|   has_many :guests, dependent: :delete_all | ||||
| end | ||||
|  | ||||
| @ -6,7 +6,13 @@ require_relative '../../extensions/tree_node_extension' | ||||
| 
 | ||||
| module Tables | ||||
|   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:) | ||||
|       @min_per_table = min_per_table | ||||
| @ -54,7 +60,10 @@ module Tables | ||||
| 
 | ||||
|         Seat.insert_all!(records_to_store) | ||||
| 
 | ||||
|         arrangement.update!(discomfort:) | ||||
|         arrangement.update!( | ||||
|           discomfort:, | ||||
|           digest: self.class.digest(tables.first.first.wedding) | ||||
|         ) | ||||
|       end | ||||
|     end | ||||
| 
 | ||||
|  | ||||
| @ -37,7 +37,7 @@ Rails.application.routes.draw do | ||||
|     resources :expenses, only: %i[index create update destroy] do | ||||
|       get :summary, on: :collection | ||||
|     end | ||||
|     resources :tables_arrangements, only: %i[index show] | ||||
|     resources :tables_arrangements, only: %i[index show create] | ||||
|     resources :summary, only: :index | ||||
| 
 | ||||
|     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. | ||||
| 
 | ||||
| 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 | ||||
|   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.string "name", 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" | ||||
|   end | ||||
| 
 | ||||
|  | ||||
| @ -18,13 +18,27 @@ RSpec.describe 'tables_arrangements' do | ||||
|                  properties: { | ||||
|                    id: { type: :string, format: :uuid }, | ||||
|                    name: { type: :string }, | ||||
|                    discomfort: { type: :integer } | ||||
|                    discomfort: { type: :integer }, | ||||
|                    valid: { type: :boolean } | ||||
|                  } | ||||
|                } | ||||
|         xit | ||||
|       end | ||||
|       regular_api_responses | ||||
|     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 | ||||
| 
 | ||||
|   path '/{slug}/tables_arrangements/{id}' do | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user