Compare commits
5 Commits
da02f37069
...
4081600dce
Author | SHA1 | Date | |
---|---|---|---|
4081600dce | |||
356e799c68 | |||
259d559b71 | |||
0c5162b326 | |||
598642a0db |
@ -329,7 +329,7 @@ GEM
|
|||||||
rswag-ui (2.16.0)
|
rswag-ui (2.16.0)
|
||||||
actionpack (>= 5.2, < 8.1)
|
actionpack (>= 5.2, < 8.1)
|
||||||
railties (>= 5.2, < 8.1)
|
railties (>= 5.2, < 8.1)
|
||||||
rubocop (1.71.0)
|
rubocop (1.70.0)
|
||||||
json (~> 2.3)
|
json (~> 2.3)
|
||||||
language_server-protocol (>= 3.17.0)
|
language_server-protocol (>= 3.17.0)
|
||||||
parallel (~> 1.10)
|
parallel (~> 1.10)
|
||||||
@ -578,7 +578,7 @@ CHECKSUMS
|
|||||||
rswag-api (2.16.0) sha256=b653f7bd92e98be18b01ab4525d88950d7b0960e293a99f856b9efcee3ae6074
|
rswag-api (2.16.0) sha256=b653f7bd92e98be18b01ab4525d88950d7b0960e293a99f856b9efcee3ae6074
|
||||||
rswag-specs (2.16.0) sha256=8ba26085c408b0bd2ed21dc8015c80f417c7d34c63720ab7133c2549b5bd2a91
|
rswag-specs (2.16.0) sha256=8ba26085c408b0bd2ed21dc8015c80f417c7d34c63720ab7133c2549b5bd2a91
|
||||||
rswag-ui (2.16.0) sha256=a1f49e927dceda92e6e6e7c1000f1e217ee66c565f69e28131dc98b33cd3a04f
|
rswag-ui (2.16.0) sha256=a1f49e927dceda92e6e6e7c1000f1e217ee66c565f69e28131dc98b33cd3a04f
|
||||||
rubocop (1.71.0) sha256=e19679efd447346ac476122313d3788ae23c38214790bcf660e984c747608bf0
|
rubocop (1.70.0) sha256=96751f8440b36a0ac6e9a8ab596900803118d83d6b83f2037bf8b3d7a5bc440e
|
||||||
rubocop-ast (1.37.0) sha256=9513ac88aaf113d04b52912533ffe46475de1362d4aa41141b51b2455827c080
|
rubocop-ast (1.37.0) sha256=9513ac88aaf113d04b52912533ffe46475de1362d4aa41141b51b2455827c080
|
||||||
rubocop-factory_bot (2.26.1) sha256=8de13cd4edcee5ca800f255188167ecef8dbfc3d1fae9f15734e9d2e755392aa
|
rubocop-factory_bot (2.26.1) sha256=8de13cd4edcee5ca800f255188167ecef8dbfc3d1fae9f15734e9d2e755392aa
|
||||||
rubocop-rails (2.29.0) sha256=35bffd140c80671453aafac0e2d5ab5b3dd65736a3fc8f3936ccca226b89c234
|
rubocop-rails (2.29.0) sha256=35bffd140c80671453aafac0e2d5ab5b3dd65736a3fc8f3936ccca226b89c234
|
||||||
|
@ -57,16 +57,17 @@ The backend service will seed the database with fake data. It's worth noting tha
|
|||||||
|
|
||||||
The backend, frontend and workers have hot-reloading enabled, so changes made to the codebase should be reflected in the application on the next request.
|
The backend, frontend and workers have hot-reloading enabled, so changes made to the codebase should be reflected in the application on the next request.
|
||||||
|
|
||||||
Once all containers have started, visit http://libre-wedding-planner.app.localhost/default/dashboard to load the application.
|
Once all containers have started, visit:
|
||||||
|
|
||||||
|
- http://libre-wedding-planner.app.localhost/default to load the application.
|
||||||
|
- http://libre-wedding-planner.app.localhost/letter_opener/ to get a list of emails generated by the application.
|
||||||
|
- http://pghero.libre-wedding-planner.app.localhost to load the [pghero](https://github.com/ankane/pghero) tool.
|
||||||
|
|
||||||
## Multitenancy
|
## Multitenancy
|
||||||
|
|
||||||
LibreWeddingPlanner is designed to manage multiple weddings in a single host. All URLs (in the API and the frontend) are scoped under a slug that is unique per wedding. The slug is made of lowercase letters, numbers, and dashes (-).
|
LibreWeddingPlanner is designed to manage multiple weddings in a single host. All URLs (in the API and the frontend) are scoped under a slug that is unique per wedding. The slug is made of lowercase letters, numbers, and dashes (-).
|
||||||
|
|
||||||
The development environment is seeded with a wedding whose slug is `default`.
|
The development environment is seeded with a wedding whose slug is `default`.
|
||||||
## Email delivery
|
|
||||||
|
|
||||||
In the development environment, real emails will not be sent. You can visit http://libre-wedding-planner.app.localhost/letter_opener/ to get a list of emails generated by the application.
|
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ class AffinityGroupsHierarchy < Array
|
|||||||
hydrate(group)
|
hydrate(group)
|
||||||
end
|
end
|
||||||
|
|
||||||
discomforts
|
load_discomforts
|
||||||
freeze
|
freeze
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -58,9 +58,9 @@ class AffinityGroupsHierarchy < Array
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def discomforts
|
def load_discomforts
|
||||||
@discomforts ||= GroupAffinity.pluck(:group_a_id, :group_b_id,
|
@load_discomforts ||= GroupAffinity.pluck(:group_a_id, :group_b_id,
|
||||||
:discomfort).each_with_object({}) do |(id_a, id_b, discomfort), acc|
|
:discomfort).each_with_object({}) do |(id_a, id_b, discomfort), acc|
|
||||||
acc[uuid_to_int(id_a) + uuid_to_int(id_b)] = discomfort
|
acc[uuid_to_int(id_a) + uuid_to_int(id_b)] = discomfort
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
5
db/migrate/20250122202836_enable_pg_stat_statements.rb
Normal file
5
db/migrate/20250122202836_enable_pg_stat_statements.rb
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
class EnablePgStatStatements < ActiveRecord::Migration[8.0]
|
||||||
|
def change
|
||||||
|
enable_extension 'pg_stat_statements'
|
||||||
|
end
|
||||||
|
end
|
21
db/migrate/20250122204932_create_pghero_stats_tables.rb
Normal file
21
db/migrate/20250122204932_create_pghero_stats_tables.rb
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
class CreatePgheroStatsTables < ActiveRecord::Migration[8.0]
|
||||||
|
def up
|
||||||
|
execute <<~SQL
|
||||||
|
CREATE TABLE "pghero_query_stats" (
|
||||||
|
"id" bigserial primary key,
|
||||||
|
"database" text,
|
||||||
|
"user" text,
|
||||||
|
"query" text,
|
||||||
|
"query_hash" bigint,
|
||||||
|
"total_time" float,
|
||||||
|
"calls" bigint,
|
||||||
|
"captured_at" timestamp
|
||||||
|
);
|
||||||
|
CREATE INDEX ON "pghero_query_stats" ("database", "captured_at");
|
||||||
|
SQL
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
drop_table :pghero_query_stats, if_exists: true, force: :cascade
|
||||||
|
end
|
||||||
|
end
|
18
db/schema.rb
generated
18
db/schema.rb
generated
@ -1,7 +1,3 @@
|
|||||||
# Copyright (C) 2024 Manuel Bustillo
|
|
||||||
|
|
||||||
# Copyright (C) 2024-2025 LibreWeddingPlanner contributors
|
|
||||||
|
|
||||||
# This file is auto-generated from the current state of the database. Instead
|
# This file is auto-generated from the current state of the database. Instead
|
||||||
# of editing this file, please use the migrations feature of Active Record to
|
# of editing this file, please use the migrations feature of Active Record to
|
||||||
# incrementally modify your database, and then regenerate this schema definition.
|
# incrementally modify your database, and then regenerate this schema definition.
|
||||||
@ -14,9 +10,10 @@
|
|||||||
#
|
#
|
||||||
# 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_22_204932) 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"
|
||||||
|
enable_extension "pg_stat_statements"
|
||||||
|
|
||||||
# Custom types defined in this database.
|
# Custom types defined in this database.
|
||||||
# Note that some types may not work with other database engines. Be careful if changing database.
|
# Note that some types may not work with other database engines. Be careful if changing database.
|
||||||
@ -71,6 +68,17 @@ ActiveRecord::Schema[8.0].define(version: 2024_12_16_231415) do
|
|||||||
t.index ["wedding_id"], name: "index_guests_on_wedding_id"
|
t.index ["wedding_id"], name: "index_guests_on_wedding_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "pghero_query_stats", force: :cascade do |t|
|
||||||
|
t.text "database"
|
||||||
|
t.text "user"
|
||||||
|
t.text "query"
|
||||||
|
t.bigint "query_hash"
|
||||||
|
t.float "total_time"
|
||||||
|
t.bigint "calls"
|
||||||
|
t.datetime "captured_at", precision: nil
|
||||||
|
t.index ["database", "captured_at"], name: "pghero_query_stats_database_captured_at_idx"
|
||||||
|
end
|
||||||
|
|
||||||
create_table "seats", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
create_table "seats", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||||
t.uuid "guest_id", null: false
|
t.uuid "guest_id", null: false
|
||||||
t.uuid "tables_arrangement_id", null: false
|
t.uuid "tables_arrangement_id", null: false
|
||||||
|
@ -74,10 +74,19 @@ services:
|
|||||||
POSTGRES_USER: postgres
|
POSTGRES_USER: postgres
|
||||||
POSTGRES_PASSWORD: postgres
|
POSTGRES_PASSWORD: postgres
|
||||||
POSTGRES_DB: postgres
|
POSTGRES_DB: postgres
|
||||||
|
command: postgres -c shared_preload_libraries='pg_stat_statements' -c pg_stat_statements.track=all
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test: ['CMD-SHELL', 'pg_isready -U postgres']
|
test: ['CMD-SHELL', 'pg_isready -U postgres']
|
||||||
interval: 10s
|
interval: 10s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 5
|
retries: 5
|
||||||
|
pghero:
|
||||||
|
image: ankane/pghero
|
||||||
|
ports:
|
||||||
|
- 8080
|
||||||
|
environment:
|
||||||
|
DATABASE_URL: postgres://postgres:postgres@db:5432/postgres
|
||||||
|
depends_on:
|
||||||
|
db:
|
||||||
|
condition: service_healthy
|
||||||
|
|
@ -23,3 +23,12 @@ server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name pghero.libre-wedding-planner.app.localhost;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://pghero:8080;
|
||||||
|
proxy_set_header Host $http_host;
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user