Hopp til hovedinnhold

Database

ChurchApps API-et bruker en database-per-modul-arkitektur. Hver av de seks datamodulene har sin egen MySQL-database med en uavhengig tilkoblingspool, noe som gir tydelige datagrenser samtidig som alt holdes innenfor én enkelt distribusjon.

Før du begynner

Arkitekturoversikt​

Api
├── membership_db ← Personer, grupper, tillatelser
├── attendance_db ← Gudstjenester, sesjoner, oppføringer
├── content_db ← Sider, seksjoner, elementer
├── giving_db ← Donasjoner, fond, betalinger
├── messaging_db ← Samtaler, varsler
└── doing_db ← Oppgaver, planer, tildelinger

Sentrale designvalg​

  • Én database per modul -- Hver modul opprettholder sin egen MySQL-database med en dedikert tilkoblingspool (administrert av KyselyPool). Dette holder modulene frikoblet og muliggjør uavhengig skjemautvikling.
  • Eksklusivt eierskap -- En moduls tabeller leses og skrives kun av modulens egen kode. Når en annen modul trenger dataene, kaller den den eiende modulens gateway i stedet for å spørre tabellene direkte -- se Kommunikasjon på tvers av moduler.
  • Repository-mønster uten ORM -- All datatilgang går gjennom repository-klasser som bygger typet SQL med Kysely-spørringsbyggeren mot modulens skjema. Dette gir full kontroll over spørringsytelse og -atferd.
  • Multi-tenant per design -- Hver spørring er avgrenset av churchId. Alle tabeller inkluderer en churchId-kolonne, og repository-laget håndhever tenant-isolasjon automatisk.

Tilkoblingsstrenger​

Hver moduls databasetilkobling konfigureres i .env ved hjelp av standard MySQL-tilkoblingsstrengformat:

mysql://user:password@host:port/database

For eksempel kan et lokalt utviklingsoppsett se slik ut:

Hver modul leser tilkoblingen sin fra en miljøvariabel kalt <MODULE>_CONNECTION_STRING:

MEMBERSHIP_CONNECTION_STRING=mysql://root:password@localhost:3306/churchapps_membership
ATTENDANCE_CONNECTION_STRING=mysql://root:password@localhost:3306/churchapps_attendance
CONTENT_CONNECTION_STRING=mysql://root:password@localhost:3306/churchapps_content
GIVING_CONNECTION_STRING=mysql://root:password@localhost:3306/churchapps_giving
MESSAGING_CONNECTION_STRING=mysql://root:password@localhost:3306/churchapps_messaging
DOING_CONNECTION_STRING=mysql://root:password@localhost:3306/churchapps_doing
Info

I produksjon lagres tilkoblingsstrenger i AWS SSM Parameter Store og leses av Environment-klassen ved oppstart.

Skjemaskript​

Tabellskjemaer defineres som Kysely-migrasjoner i tools/migrations/-katalogen, organisert etter modul:

tools/migrations/
├── membership/
├── attendance/
├── content/
├── giving/
├── messaging/
└── doing/

Migrasjoner definerer tabellopprettelse, indekser og skjemaendringer. tools/dbScripts/-katalogen inneholder demo- og frødata som kan lastes oppå skjemaet.

Databaseinitialisering​

Initialiser alle databaser​

npm run initdb

Dette oppretter alle seks databasene og kjører migrasjonene for hver av dem.

Initialiser en enkelt modul​

npm run initdb -- --module=membership
Tips

Når du jobber med en spesifikk modul, kan du re-initialisere bare den modulens database uten å påvirke de andre.

Datatilgangsmønster​

Repositories bygger spørringer med Kysely-spørringsbyggeren mot modulens typede databaseskjema, hentet gjennom modulens getDb()-funksjon. En typisk repository-metode ser slik ut:

public async loadAll(churchId: string) {
return getDb().selectFrom("people").selectAll()
.where("churchId", "=", churchId)
.execute();
}

Repositories hentes via RepoManager:

const repos = await RepoManager.getRepos<Repos>("membership");
const people = await repos.person.loadAll(churchId);
Advarsel

Inkluder alltid churchId i spørringene dine for å opprettholde multi-tenant-isolasjon. Aldri spør på tvers av tenanter med mindre du har en spesifikk, autorisert grunn til å gjøre det.

Referanser på tvers av moduler​

Fordi hver moduls data ligger i en separat database, finnes det ingen fremmednøkler eller SQL-joins på tvers av modulgrenser. En oppføring som relaterer seg til en annen moduls data, lagrer den oppføringens id -- for eksempel har en donasjon i giving-databasen personId til en person i membership-databasen -- og all sammensetning på tvers av moduler skjer i applikasjonskoden.

Denne begrensningen er det som gjør modulgrensene reelle: hvert skjema kan utvikle seg uavhengig, en moduls database kan flyttes til sin egen server, og en modul kan til og med skilles ut som en frittstående tjeneste uten å måtte løse opp delte tabeller eller spørringer på tvers av databaser.

Relaterte artikler​