-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Wire up a database #8
Changes from 4 commits
3bd0dc1
4d4b491
75e799c
07c0a7a
76cf4b2
43d637e
ec4dfd5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
CI=0 | ||
DATABASE_URL="postgresql://daedalus-web-app-user:changeme@localhost:5432/daedalus-web-app" |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,15 +27,31 @@ npm run test:e2e | |
|
||
The tests under e2e, which are run by playwright, are for testing the full-stack (client app and server app) in a browser environment. Since the server-rendered page may be different from the client-rendered page, for example, when some elements are configured to only render on the client side, relevant tests should wait for the elements to be present. | ||
|
||
## Setup | ||
## Local development | ||
|
||
### Setup | ||
|
||
Make sure to install the dependencies: | ||
Use Node 20. | ||
Have Docker installed. | ||
Copy `.env.example` to `.env`. | ||
Build and run the database container: | ||
|
||
```bash | ||
./db/scripts/build | ||
./db/scripts/run | ||
``` | ||
|
||
Install the JS dependencies: | ||
|
||
```bash | ||
npm install | ||
``` | ||
|
||
## Local development | ||
Prisma ORM can only query the database once you 'generate' the Prisma Client, which generates into `node_modules/.prisma/client`. This should happen when you install the JS dependencies and whenever you run a migration, but if the Prisma client gets out of sync or doesn't generate, you can manually generate it: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ..and this generates the client based on schema.prisma? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updating the README to make this clear |
||
|
||
```bash | ||
npx prisma generate | ||
``` | ||
|
||
Start the development server on `http://localhost:3000`: | ||
|
||
|
@@ -51,6 +67,20 @@ npm run dev -- --host | |
|
||
The QR code shown will allow you to quickly access the app. | ||
|
||
### DB | ||
|
||
To create migrations to the database, first update the Prisma schema at ./prisma/schema.prisma as required, then run the below to generate the corresponding SQL migration and to apply it to the database: | ||
|
||
```bash | ||
npx prisma migrate dev | ||
``` | ||
|
||
The same command is also used to apply migrations that already exist in ./prisma/migrations but which have not been applied to the database. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, so we're going to keep this as a manual development process? When you need to update the schema, you'll update both the .schema file, and generate the SQL migrations, and commit both to git? ..and as well as generating the migrations this command also applies them to the running database (defined in .env) - running in the container. So we'll run ths same thing as part of deployment (?) to update the db? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, we just need to run https://www.prisma.io/docs/orm/prisma-client/deployment/deploy-database-changes-with-prisma-migrate There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it makes most sense to try that out when we have some environments up, with databases running, which we can see whether or not they correctly get migrated. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note to self for when I'm working on this: It might be the case that we need to explicitly re-generate the prisma client (using prisma generate) after running There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I now have a 'Add prisma migrations to deploy workflow' ticket. |
||
|
||
#### For your IDE | ||
|
||
In VSCode, you can use the extension with ID 'Prisma.prisma' to get syntax highlighting etc. | ||
|
||
## Linting and formatting | ||
|
||
Linting and formatting are handled jointly by [@nuxt/eslint](https://eslint.nuxt.com/packages/module) (an "all-in-one" ESLint "integration" for Nuxt) and by the more frequently-updated, conventionally- and widely-used [@antfu/eslint-config](https://github.com/antfu/eslint-config) (antfu works at NuxtLabs, and the package is given as an example in the `@nuxt/eslint` docs). The former handles linting only, while the latter also handles formatting, based on ESLint Stylistic. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
FROM postgres:14.12 | ||
COPY bin /daedalus-web-app-bin | ||
ENV PATH="/daedalus-web-app-bin:$PATH" | ||
ENV POSTGRES_DB=daedalus-web-app | ||
ENV POSTGRES_USER=daedalus-web-app-user | ||
ENV POSTGRES_PASSWORD=changeme | ||
# This is needed to override the loss of data that happens if you | ||
# don't mount a persistent volume at the mount point. | ||
ENV PGDATA=/pgdata | ||
|
||
COPY conf /etc/daedalus-web-app | ||
|
||
RUN cat /etc/daedalus-web-app/postgresql.conf /etc/daedalus-web-app/postgresql.test.conf.in > \ | ||
/etc/daedalus-web-app/postgresql.test.conf | ||
RUN cat /etc/daedalus-web-app/postgresql.conf /etc/daedalus-web-app/postgresql.production.conf.in > \ | ||
/etc/daedalus-web-app/postgresql.production.conf | ||
RUN chown -R postgres:postgres /etc/daedalus-web-app | ||
|
||
# Ensure docker-entrypoint.sh is in the PATH | ||
ENV PATH="/usr/local/bin:$PATH" | ||
RUN docker-entrypoint.sh --version | ||
|
||
# Ensure the start script is executable | ||
RUN chmod +x /daedalus-web-app-bin/start-with-config.sh | ||
|
||
ENTRYPOINT ["/daedalus-web-app-bin/start-with-config.sh"] | ||
CMD ["/etc/daedalus-web-app/postgresql.conf"] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
Build docker image for postgres database: | ||
|
||
``` | ||
./db/scripts/build | ||
``` | ||
|
||
Run docker container for postgres database: | ||
|
||
``` | ||
./db/scripts/run | ||
``` | ||
|
||
Run an SQL query: | ||
|
||
``` | ||
./db/scripts/runQuery "SELECT id FROM scenario" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice! |
||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#!/usr/bin/env bash | ||
|
||
# Copied from https://github.com/mrc-ide/packit/blob/main/db/bin/start-with-config.sh | ||
|
||
set -ex | ||
CONFIG_FILE=$1 | ||
shift | ||
exec docker-entrypoint.sh $* -c config_file=$CONFIG_FILE |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# TYPE DATABASE USER ADDRESS METHOD | ||
local all all trust | ||
host all all all md5 | ||
host replication all all md5 | ||
|
||
# Copied from https://github.com/mrc-ide/packit/blob/main/db/conf/pg_hba.conf |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Copied from https://github.com/mrc-ide/packit/blob/main/db/conf/postgresql.conf | ||
|
||
# These are the non-commented values from postgresql.default.conf | ||
# *except* for the hba_file one. | ||
listen_addresses = '*' | ||
hba_file = '/etc/daedalus-web-app/pg_hba.conf' | ||
max_connections = 100 | ||
shared_buffers = 128MB | ||
dynamic_shared_memory_type = posix | ||
log_timezone = 'UTC' | ||
datestyle = 'iso, mdy' | ||
timezone = 'UTC' | ||
lc_messages = 'en_US.utf8' | ||
lc_monetary = 'en_US.utf8' | ||
lc_numeric = 'en_US.utf8' | ||
lc_time = 'en_US.utf8' | ||
default_text_search_config = 'pg_catalog.english' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
# ------------------------------------- | ||
# PostgreSQL/hint configuration file | ||
# ------------------------------------- | ||
|
||
# Copied from https://github.com/mrc-ide/packit/blob/main/db/conf/postgresql.production.conf.in | ||
|
||
# This file has been stripped down to the options that we are actually | ||
# setting to make it easier to work with. | ||
# Options are documented online here: | ||
# https://www.postgresql.org/docs/9.6/static/runtime-config.html | ||
|
||
#------------------------------------------------------------------------------ | ||
# FILE LOCATIONS | ||
#------------------------------------------------------------------------------ | ||
|
||
|
||
#------------------------------------------------------------------------------ | ||
# CONNECTIONS AND AUTHENTICATION | ||
#------------------------------------------------------------------------------ | ||
|
||
listen_addresses = '*' | ||
max_connections = 100 | ||
|
||
#------------------------------------------------------------------------------ | ||
# RESOURCE USAGE (except WAL) | ||
#------------------------------------------------------------------------------ | ||
|
||
shared_buffers = 8GB | ||
work_mem = 64MB | ||
maintenance_work_mem = 1GB | ||
|
||
dynamic_shared_memory_type = posix | ||
|
||
#------------------------------------------------------------------------------ | ||
# WRITE AHEAD LOG | ||
#------------------------------------------------------------------------------ | ||
|
||
wal_level = replica | ||
max_wal_size = 1GB | ||
checkpoint_completion_target = 0.9 | ||
checkpoint_flush_after = 256kB | ||
|
||
#------------------------------------------------------------------------------ | ||
# REPLICATION | ||
#------------------------------------------------------------------------------ | ||
|
||
# This needs to be 3 * max_replication_slots + 1 because each | ||
# replication instance might use three connections | ||
max_wal_senders = 7 # max number of walsender processes | ||
max_replication_slots = 2 # max number of replication slots | ||
|
||
#------------------------------------------------------------------------------ | ||
# QUERY TUNING | ||
#------------------------------------------------------------------------------ | ||
|
||
effective_cache_size = 16GB | ||
|
||
#------------------------------------------------------------------------------ | ||
# ERROR REPORTING AND LOGGING | ||
#------------------------------------------------------------------------------ | ||
|
||
log_timezone = 'UTC' | ||
|
||
#------------------------------------------------------------------------------ | ||
# RUNTIME STATISTICS | ||
#------------------------------------------------------------------------------ | ||
|
||
#------------------------------------------------------------------------------ | ||
# AUTOVACUUM PARAMETERS | ||
#------------------------------------------------------------------------------ | ||
|
||
#------------------------------------------------------------------------------ | ||
# CLIENT CONNECTION DEFAULTS | ||
#------------------------------------------------------------------------------ | ||
|
||
datestyle = 'iso, mdy' | ||
timezone = 'UTC' | ||
|
||
# These settings are initialized by initdb, but they can be changed. | ||
lc_messages = 'en_US.utf8' # locale for system error message | ||
# strings | ||
lc_monetary = 'en_US.utf8' # locale for monetary formatting | ||
lc_numeric = 'en_US.utf8' # locale for number formatting | ||
lc_time = 'en_US.utf8' # locale for time formatting | ||
|
||
# default configuration for text search | ||
default_text_search_config = 'pg_catalog.english' | ||
|
||
#------------------------------------------------------------------------------ | ||
# LOCK MANAGEMENT | ||
#------------------------------------------------------------------------------ | ||
|
||
#------------------------------------------------------------------------------ | ||
# VERSION/PLATFORM COMPATIBILITY | ||
#------------------------------------------------------------------------------ | ||
|
||
#------------------------------------------------------------------------------ | ||
# ERROR HANDLING | ||
#------------------------------------------------------------------------------ | ||
|
||
#------------------------------------------------------------------------------ | ||
# CONFIG FILE INCLUDES | ||
#------------------------------------------------------------------------------ | ||
|
||
#------------------------------------------------------------------------------ | ||
# CUSTOMIZED OPTIONS | ||
#------------------------------------------------------------------------------ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Copied from db/conf/postgresql.test.conf.in | ||
# ---------------------------------------------------------------------------- | ||
# Test database config begins here. | ||
# Values here override those earlier in the file | ||
# ---------------------------------------------------------------------------- | ||
shared_buffers = 128MB | ||
fsync = off | ||
synchronous_commit = off | ||
full_page_writes = off | ||
checkpoint_timeout = 45min | ||
max_wal_size = 4GB |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#!/usr/bin/env bash | ||
set -e | ||
HERE=$(dirname $0) | ||
. $HERE/common | ||
|
||
PACKAGE_ROOT=$(realpath $HERE/..) | ||
|
||
docker build \ | ||
-t "$TAG_SHA" \ | ||
-t "$TAG_BRANCH" \ | ||
$PACKAGE_ROOT |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#!/usr/bin/env bash | ||
set -ex | ||
|
||
if [[ -v "GITHUB_SHA" ]]; then | ||
GIT_ID=${GITHUB_SHA:0:7} | ||
else | ||
GIT_ID=$(git rev-parse --short=7 HEAD) | ||
fi | ||
|
||
if [[ -v "BRANCH_NAME" ]]; then | ||
GIT_BRANCH=${BRANCH_NAME} | ||
else | ||
GIT_BRANCH=$(git symbolic-ref --short HEAD) | ||
fi | ||
|
||
ORG=jameel-institute | ||
IMAGE_NAME=daedalus-web-app-db | ||
TAG_SHA="${ORG}/${IMAGE_NAME}:${GIT_ID}" | ||
TAG_BRANCH="${ORG}/${IMAGE_NAME}:${GIT_BRANCH}" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#!/usr/bin/env bash | ||
set -e | ||
|
||
HERE=$(dirname $0) | ||
. $HERE/common | ||
|
||
docker run --rm -d \ | ||
--network=bridge \ | ||
--name daedalus-web-app-db \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Personally I'll find remembering to omit 'app' more confusing, since I'm generically calling this app 'daedalus-web-app' everywhere, e.g. the github repo, package name. (Didn't want to fully commit to the provisional name 'Daedalus Explore'!) There will be at least this many Daedalusy 'packages' (broadly defined) to keep track of, so explicit naming should help us steer clear of conflation:
|
||
-p 5432:5432 \ | ||
"$TAG_BRANCH" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
#!/bin/bash | ||
set -e | ||
|
||
# Check if the SQL query is passed as an argument | ||
if [ -z "$1" ]; then | ||
echo "Usage: $0 \"SQL_QUERY\"" | ||
exit 1 | ||
fi | ||
|
||
# Assign the SQL query to a variable | ||
SQL_QUERY="$1" | ||
|
||
# Define the Docker container name, PostgreSQL user, and database | ||
DOCKER_CONTAINER="daedalus-web-app-db" | ||
PG_USER="daedalus-web-app-user" | ||
PG_DATABASE="daedalus-web-app" | ||
|
||
# Execute the SQL query using docker exec and psql | ||
docker exec $DOCKER_CONTAINER psql -U $PG_USER -d $PG_DATABASE -c "$SQL_QUERY" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
// Although the Prisma nuxt module didn't work (see https://github.com/prisma/nuxt-prisma/issues/22) | ||
// we still need to use the related setup code that creates a global instance of the Prisma Client, | ||
// so this file is a linted version of https://www.prisma.io/docs/orm/more/help-and-troubleshooting/help-articles/prisma-nuxt-module#option-b-libprismats | ||
|
||
import process from "node:process"; | ||
import { PrismaClient } from "@prisma/client"; | ||
|
||
function prismaClientSingleton() { | ||
return new PrismaClient(); | ||
} | ||
|
||
declare const globalThis: { | ||
prismaGlobal: ReturnType<typeof prismaClientSingleton> | ||
// eslint-disable-next-line no-restricted-globals | ||
} & typeof global; | ||
|
||
const prisma = globalThis.prismaGlobal ?? prismaClientSingleton(); | ||
|
||
export default prisma; | ||
|
||
if (process.env.NODE_ENV !== "production") | ||
globalThis.prismaGlobal = prisma; | ||
Comment on lines
+21
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the Prisma Client is the thing that will be used to query the db? I'm not clear on why a distinction is made for production mode? It looks like in this case the client is expected to already exist? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't explain what the production condition is for. The origin of the code is (as commented at top of file) (a linted version of) https://www.prisma.io/docs/orm/more/help-and-troubleshooting/help-articles/prisma-nuxt-module#option-b-libprismats |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since you're going to have to do this a lot during development, I think it would be better to make this a single script call - you might as well put that in a
run-dependencies
now since you know you're going to have to include the api soon too. It should apply the db migrations you need to.Do we need to distinguish .env from .env.example here? Can't we just make .env the settings that will work for local development and then in the deployment tool we'll make sure we overwrite with whatever settings we need for the environments we're deploying?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To streamline setting up .env, in the next PR I'm updating the README to make copying and npm installing a single action: