Base de données relationnelle TypeScript
Ce générateur crée un nouveau projet de base de données relationnelle soutenu par Amazon Aurora (PostgreSQL ou MySQL) et Prisma ORM. Il génère le code d’application et l’infrastructure nécessaires pour provisionner et gérer une base de données en utilisant AWS CDK ou Terraform, avec une définition de schéma déclarative, un déploiement automatique des migrations et un client ORM type-safe.
Utilisation
Section intitulée « Utilisation »Générer une base de données relationnelle
Section intitulée « Générer une base de données relationnelle »Vous pouvez générer un nouveau projet de base de données relationnelle de deux manières :
pnpm nx g @aws/nx-plugin:ts#rdbyarn nx g @aws/nx-plugin:ts#rdbnpx nx g @aws/nx-plugin:ts#rdbbunx nx g @aws/nx-plugin:ts#rdbVous pouvez également effectuer une simulation pour voir quels fichiers seraient modifiés
pnpm nx g @aws/nx-plugin:ts#rdb --dry-runyarn nx g @aws/nx-plugin:ts#rdb --dry-runnpx nx g @aws/nx-plugin:ts#rdb --dry-runbunx nx g @aws/nx-plugin:ts#rdb --dry-run- Installez le Nx Console VSCode Plugin si ce n'est pas déjà fait
- Ouvrez la console Nx dans VSCode
- Cliquez sur
Generate (UI)dans la section "Common Nx Commands" - Recherchez
@aws/nx-plugin - ts#rdb - Remplissez les paramètres requis
- Cliquez sur
Generate
| Paramètre | Type | Par défaut | Description |
|---|---|---|---|
| name Requis | string | - | Nom du projet de base de données à générer |
| directory | string | packages | Le répertoire dans lequel stocker l'application. |
| subDirectory | string | - | Le sous-répertoire dans lequel le projet est placé. Par défaut, il s'agit du nom du projet. |
| infra | aurora | none | aurora | Service de base de données relationnelle à provisionner. |
| engine | postgres | mysql | postgres | Moteur de base de données à utiliser avec le service sélectionné. |
| databaseUser | string | dbadmin | Nom d'utilisateur administrateur de la base de données. Par défaut 'dbadmin'. |
| databaseName | string | - | Nom initial de la base de données. Par défaut, le nom du projet. |
| framework | prisma | prisma | Framework ORM à utiliser pour le projet généré. |
| iac | inherit | cdk | terraform | inherit | Le fournisseur IaC préféré. Par défaut, celui-ci est hérité de votre sélection initiale. |
| preferInstallDependencies | boolean | true | Indique s'il faut privilégier l'installation des dépendances après l'exécution du générateur. Définir sur false pour différer l'installation lors de l'exécution de plusieurs générateurs en lot (une installation s'exécute quand même si nécessaire pour que les générateurs suivants puissent calculer le graphe de projet Nx) ; installer une seule fois à la fin. |
Sortie du générateur
Section intitulée « Sortie du générateur »Le générateur créera la structure de projet suivante dans le répertoire <directory>/<name> :
Répertoireprisma
Répertoiremodels
- example.prisma Example model definition
- schema.prisma Main Prisma schema (references models)
Répertoiresrc
- index.ts Project entry point
- prisma.ts Prisma runtime client wrapper
- utils.ts Runtime config and secret helpers
- create-db-user-handler.ts Lambda handler used to create the application database user during deployment
- migration-handler.ts Lambda handler used to run database migrations during deployment
- .gitignore Git ignore entries including generated Prisma client output
- config.json Local development connection details and runtime config key
- Dockerfile Container image definition for the migration handler
- package.json Project manifest defining the project’s package name and dependencies
- project.json Project configuration and build targets
- prisma.config.ts Configuration for Prisma CLI
Les scripts de développement local sont partagés entre tous les projets de base de données et générés dans packages/common/scripts/ :
Répertoirepackages/common/scripts/src/rdb
- pull-image.ts Pulls the database container image
- start-container.ts Starts a local database container
- wait-for-postgres-db.ts Waits for the local database to be ready (PostgreSQL)
- wait-for-mysql-db.ts Waits for the local database to be ready (MySQL)
Infrastructure
Section intitulée « Infrastructure »Étant donné que ce générateur fournit de l’infrastructure en tant que code basée sur votre iac choisi, il créera un projet dans packages/common qui inclut les constructs CDK ou modules Terraform pertinents.
Le projet d’infrastructure en tant que code commun est structuré comme suit :
Répertoirepackages/common/constructs
Répertoiresrc
Répertoireapp/ Constructs pour l’infrastructure spécifique à un projet/générateur
- …
Répertoirecore/ Constructs génériques qui sont réutilisés par les constructs dans
app- …
- index.ts Entry point exporting constructs from
app
- project.json Project build targets and configuration
Répertoirepackages/common/terraform
Répertoiresrc
Répertoireapp/ Terraform modules for infrastructure specific to a project/generator
- …
Répertoirecore/ Generic modules which are reused by modules in
app- …
- project.json Project build targets and configuration
Répertoirepackages/common/constructs/src
Répertoireapp
Répertoiredbs
- <name>.ts Infrastructure spécifique à votre base de données
Répertoirecore
Répertoirerdb
- aurora.ts Construct Aurora générique pour base de données
Répertoirepackages/common/terraform/src
Répertoireapp
Répertoiredbs
Répertoire<name>
- <name>.tf Module spécifique à votre base de données
Répertoirecore
Répertoirerdb
Répertoireaurora
- aurora.tf Module Aurora générique
Architecture
Section intitulée « Architecture »La base de données déployée a l’architecture suivante. Par défaut, un Amazon RDS Proxy se trouve devant le cluster Aurora pour mettre en commun les connexions et pour activer l’authentification IAM — voir Désactiver RDS Proxy pour l’alternative. L’architecture est la même que vous sélectionniez le moteur PostgreSQL ou MySQL ; seule la variante du moteur Aurora diffère.
Développement local
Section intitulée « Développement local »Modélisation des données
Section intitulée « Modélisation des données »Le projet généré utilise Prisma ORM pour définir votre schéma de base de données et générer un client type-safe. Le flux de travail est axé sur le modèle : ajoutez ou mettez à jour les fichiers de modèle Prisma dans le répertoire prisma/models/ de votre projet de base de données, puis générez une migration à partir de ces modifications de modèle.
Exemple de modèle User :
model User { id Int @id @default(autoincrement()) firstName String lastName String}Pour plus de détails, consultez le guide officiel de modélisation des données Prisma.
Génération du client de base de données
Section intitulée « Génération du client de base de données »Le générateur configure automatiquement la cible generate pour créer un client Prisma TypeScript type-safe chaque fois que vous construisez le projet. Le client est écrit dans generated/prisma (ajouté à .gitignore).
Vous pouvez également générer manuellement le client à tout moment :
pnpm nx run <your-db-project-name>:generateyarn nx run <your-db-project-name>:generatenpx nx run <your-db-project-name>:generatebunx nx run <your-db-project-name>:generateUtilisez la cible prisma pour exécuter les commandes Prisma CLI depuis la racine de l’espace de travail :
pnpm nx run <project>:prisma generateyarn nx run <project>:prisma generatenpx nx run <project>:prisma generatebunx nx run <project>:prisma generateLe wrapper d’exécution dans src/prisma.ts exporte :
getPrisma()- charge les paramètres de connexion à la base de données depuis AWS AppConfig et crée un client Prisma utilisant l’authentification IAM
Le client automatiquement :
- Récupère la configuration de la base de données depuis AWS AppConfig en utilisant la variable d’environnement
RUNTIME_CONFIG_APP_ID - Génère des jetons d’authentification temporaires via AWS RDS Signer pour l’authentification IAM
- Gère les connexions SSL/TLS avec validation de certificat
- Gère le pooling de connexions via des pools de connexion de base de données persistants
Création de migrations
Section intitulée « Création de migrations »Après avoir ajouté ou mis à jour des modèles dans prisma/models/, utilisez migrate dev pour générer les fichiers de migration et les appliquer à votre base de données locale en même temps.
La cible prisma générée démarre automatiquement un conteneur de base de données local avant l’exécution :
pnpm nx run <project>:prisma migrate devyarn nx run <project>:prisma migrate devnpx nx run <project>:prisma migrate devbunx nx run <project>:prisma migrate devSi vous souhaitez uniquement générer les fichiers de migration sans les appliquer à la base de données locale, ajoutez --create-only :
pnpm nx run <project>:prisma migrate dev --create-onlyyarn nx run <project>:prisma migrate dev --create-onlynpx nx run <project>:prisma migrate dev --create-onlybunx nx run <project>:prisma migrate dev --create-onlyCela génère un nouveau dossier de migration dans prisma/migrations chaque fois que votre schéma change :
Répertoireprisma
Répertoiremigrations
Répertoire20260405013911_initial_migrations
- migration.sql
- migration_lock.toml
- schema.prisma
Lorsque vous déployez la stack AWS, l’infrastructure générée applique automatiquement les migrations générées à la base de données déployée.
Application de migrations existantes
Section intitulée « Application de migrations existantes »Lorsque vous récupérez des fichiers de migration créés par d’autres développeurs, utilisez migrate deploy pour appliquer ces migrations existantes à votre base de données locale.
pnpm nx run <project>:prisma migrate deployyarn nx run <project>:prisma migrate deploynpx nx run <project>:prisma migrate deploybunx nx run <project>:prisma migrate deployDans ce flux de développement local, migrate deploy applique les fichiers de migration à votre base de données locale ; il ne déploie pas la base de données sur AWS.
Exécution de commandes Prisma
Section intitulée « Exécution de commandes Prisma »La cible prisma générée expose la CLI Prisma, vous pouvez donc l’utiliser pour exécuter n’importe quelle commande prise en charge par Prisma contre la base de données locale. Consultez la référence CLI Prisma pour les commandes disponibles.
pnpm nx run <project>:prisma <prisma-command>yarn nx run <project>:prisma <prisma-command>npx nx run <project>:prisma <prisma-command>bunx nx run <project>:prisma <prisma-command>Utilisation de Prisma Studio
Section intitulée « Utilisation de Prisma Studio »Prisma Studio est un éditeur visuel pour votre base de données locale. Utilisez-le pour parcourir les tables, inspecter et modifier les enregistrements, filtrer les données, suivre les relations et exécuter du SQL brut via la console SQL intégrée. Il est utile pour vérifier les migrations et alimenter les données de test pendant le développement. Lancez-le avec :
pnpm nx run <project>:prisma studioyarn nx run <project>:prisma studionpx nx run <project>:prisma studiobunx nx run <project>:prisma studioArrêt de la base de données locale
Section intitulée « Arrêt de la base de données locale »L’arrêt de dev (par exemple avec Ctrl+C) supprime automatiquement le conteneur de base de données local, mais préserve le volume nommé afin que vos données persistent entre les redémarrages.
Connexion à la base de données
Section intitulée « Connexion à la base de données »Dans n’importe quel projet TypeScript, importez getPrisma depuis votre package de base de données et appelez-le pour obtenir un client Prisma type-safe :
import { getPrisma } from '@my-scope/db';
const prisma = await getPrisma();const users = await prisma.user.findMany({ orderBy: { id: 'asc' } });getPrisma() retourne un client initialisé de manière paresseuse et mis en cache. Les appels suivants dans le même contexte d’exécution Lambda réutilisent le pool de connexions existant plutôt que d’en ouvrir un nouveau.
Le client Prisma expose des modèles entièrement typés dérivés de votre schéma prisma/models/, vous offrant une sécurité de type de bout en bout depuis la base de données jusqu’à votre réponse API.
getPrisma() récupère les paramètres de connexion à la base de données depuis AWS AppConfig au moment de l’exécution.
Déploiement de votre base de données
Section intitulée « Déploiement de votre base de données »Le générateur de base de données relationnelle crée une infrastructure CDK ou Terraform en fonction de votre iac sélectionné.
Le construct CDK est créé dans common/constructs. Exemple d’utilisation :
import { MyDatabase } from '@my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props); ... const db = new MyDatabase(this, 'Db', { vpc, vpcSubnets: { subnetType: SubnetType.PRIVATE_ISOLATED, } }); }}Cela provisionne un cluster Aurora avec RDS Proxy, des identifiants administrateur, un utilisateur de base de données d’application, l’enregistrement de configuration d’exécution et un gestionnaire de migration.
L’infrastructure générée crée deux utilisateurs de base de données :
- Utilisateur administrateur - Créé lors du provisionnement du cluster avec des identifiants stockés dans AWS Secrets Manager
- Utilisateur d’application - Créé via une ressource personnalisée Lambda avec authentification IAM activée et privilèges DML (SELECT, INSERT, UPDATE, DELETE) sur la base de données d’application
Le module Terraform est créé dans common/terraform. Exemple d’utilisation :
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database"
# Database subnets have no internet route; Lambda subnets need NAT egress. vpc_id = aws_vpc.main.id database_subnet_ids = aws_subnet.database[*].id lambda_subnet_ids = aws_subnet.private[*].id
tags = local.common_tags}Cela provisionne un cluster Aurora avec RDS Proxy, des identifiants administrateur, une Lambda create-db-user, l’enregistrement de configuration d’exécution, une Lambda de migration et des ressources de registre de conteneurs.
Le module de base de données enregistre ses détails de connexion sous l’espace de noms de configuration d’exécution database, que l’application AppConfig de configuration d’exécution partagée expose par défaut.
L’infrastructure générée crée deux utilisateurs de base de données :
- Utilisateur administrateur - Créé lors du provisionnement du cluster avec des identifiants stockés dans AWS Secrets Manager
- Utilisateur d’application - Créé via une fonction Lambda avec authentification IAM activée et privilèges DML (SELECT, INSERT, UPDATE, DELETE) sur la base de données d’application
L’utilisateur d’application est automatiquement créé avec un nom aléatoire et une authentification IAM. Le client de base de données généré est déjà configuré pour s’authentifier en tant que cet utilisateur en utilisant des jetons RDS de courte durée, de sorte que votre code d’application ne gère jamais les mots de passe de base de données.
Votre VPC doit inclure des sous-réseaux publics, des sous-réseaux privés avec sortie et des sous-réseaux privés isolés. La base de données peut s’exécuter dans des sous-réseaux privés isolés, tandis que les fonctions Lambda d’application doivent s’exécuter dans des sous-réseaux privés avec sortie afin qu’elles puissent atteindre les services AWS tels que AppConfig.
Exemple de configuration VPC
const vpc = new Vpc(this, 'Vpc', { subnetConfiguration: [ { name: 'public', subnetType: SubnetType.PUBLIC, }, { name: 'private_with_egress', subnetType: SubnetType.PRIVATE_WITH_EGRESS, }, { name: 'private_isolated', subnetType: SubnetType.PRIVATE_ISOLATED, }, ],});data "aws_availability_zones" "available" { state = "available"}
resource "aws_vpc" "main" { cidr_block = "10.0.0.0/16" enable_dns_hostnames = true enable_dns_support = true}
# Isolated subnets for the database: no route to the internetresource "aws_subnet" "database" { count = 2 vpc_id = aws_vpc.main.id cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index) availability_zone = data.aws_availability_zones.available.names[count.index]}
# Private subnets with NAT egress for Lambda functions and runtimes,# so they can reach AWS services such as AppConfigresource "aws_subnet" "private" { count = 2 vpc_id = aws_vpc.main.id cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, count.index + 2) availability_zone = data.aws_availability_zones.available.names[count.index]}
# Public subnet hosting the NAT gatewayresource "aws_subnet" "public" { vpc_id = aws_vpc.main.id cidr_block = cidrsubnet(aws_vpc.main.cidr_block, 8, 4) availability_zone = data.aws_availability_zones.available.names[0]}
resource "aws_internet_gateway" "main" { vpc_id = aws_vpc.main.id}
resource "aws_route_table" "public" { vpc_id = aws_vpc.main.id
route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.main.id }}
resource "aws_route_table_association" "public" { subnet_id = aws_subnet.public.id route_table_id = aws_route_table.public.id}
resource "aws_eip" "nat" { domain = "vpc"}
resource "aws_nat_gateway" "main" { allocation_id = aws_eip.nat.id subnet_id = aws_subnet.public.id depends_on = [aws_internet_gateway.main]}
resource "aws_route_table" "private" { vpc_id = aws_vpc.main.id
route { cidr_block = "0.0.0.0/0" nat_gateway_id = aws_nat_gateway.main.id }}
resource "aws_route_table_association" "private" { count = 2 subnet_id = aws_subnet.private[count.index].id route_table_id = aws_route_table.private.id}Utilisez le générateur connection pour connecter un projet à cette base de données — consultez le guide de connexion pour le type de calcul pertinent (par exemple FastAPI, serveur MCP, agent) pour le câblage d’infrastructure requis pour l’atteindre.
Analyse d’image
Section intitulée « Analyse d’image »L’image Docker construite pour ce projet peut être analysée pour détecter les vulnérabilités à l’aide de Trivy, exécuté depuis l’image Trivy hébergée sur ECR.
Une cible trivy est ajoutée à votre projet qui analyse l’image construite et se termine avec un code non nul si une vulnérabilité de gravité HIGH ou CRITICAL est trouvée. Le Dockerfile généré utilise une image de base sans vulnérabilité corrigeable connue de ces gravités au moment de la génération, et met à niveau les outils fournis (tels que npm) pour maintenir cet état.
L’analyse utilise le même moteur de conteneur que votre construction d’image (docker ou finch), donc aucun outillage supplémentaire n’est requis. Étant donné que l’analyse n’est réexécutée que lorsque l’image change, une image inchangée n’est pas réanalysée. Le script racine trivy fourni analyse chaque image dans l’espace de travail :
pnpm trivyyarn trivynpm run trivybun trivySuppression des résultats Trivy
Section intitulée « Suppression des résultats Trivy »Il peut y avoir des cas où vous souhaitez supprimer une vulnérabilité spécifique, par exemple lorsqu’aucun correctif n’est encore disponible et que vous avez évalué le risque comme acceptable.
Ajoutez l’ID de vulnérabilité (un par ligne) au fichier .trivyignore à la racine de votre projet (c’est-à-dire à côté de votre project.json) :
# node-tar arbitrary file write - not exploitable in our usageCVE-2024-XXXXXPour plus de détails sur le filtrage des résultats, consultez la documentation de filtrage Trivy.
Configuration RDS Proxy
Section intitulée « Configuration RDS Proxy »L’infrastructure générée inclut un RDS Proxy par défaut, qui se situe entre votre application et le cluster Aurora. RDS Proxy offre plusieurs avantages :
- Pooling de connexions - Maintient un pool de connexions à la base de données qui peuvent être partagées entre les instances d’application, réduisant ainsi la surcharge liée à l’établissement de nouvelles connexions
- Résilience des connexions - Gère automatiquement les basculements et les reconnexions lors des remplacements d’instances Aurora ou de la maintenance
- Authentification IAM - Prend en charge l’authentification de base de données basée sur IAM, éliminant le besoin de gérer les identifiants de base de données dans le code de votre application
- Sécurité améliorée - Applique le chiffrement TLS pour toutes les connexions
Désactiver RDS Proxy
Section intitulée « Désactiver RDS Proxy »Vous pouvez désactiver le proxy RDS comme suit :
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... enableRdsProxy: false,});Lorsque RDS Proxy est désactivé, votre application se connecte directement au point de terminaison du cluster Aurora.
Par défaut, RDS Proxy est activé. Vous pouvez le désactiver si nécessaire :
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... enable_rds_proxy = false}Lorsque RDS Proxy est désactivé, votre application se connecte directement au point de terminaison du cluster Aurora.
Exigences SSL lors de la connexion sans RDS Proxy
Section intitulée « Exigences SSL lors de la connexion sans RDS Proxy »Lors de la connexion directe au cluster Aurora (sans RDS Proxy), le runtime qui appelle getPrisma() doit faire confiance au bundle CA Amazon RDS. Le client Prisma généré active la vérification de certificat ; la manière dont vous rendez le bundle CA disponible dépend du runtime qui se connecte à la base de données.
Pour Amazon RDS, utilisez le bundle CA global depuis :
https://truststore.pki.rds.amazonaws.com/global/global-bundle.pemImages de conteneur d’exécution
Section intitulée « Images de conteneur d’exécution »Si vous préparez votre propre image de conteneur pour le runtime, téléchargez le bundle CA RDS dans votre Dockerfile et ajoutez-le au magasin de confiance du système d’exploitation.
RUN curl -fsSL "https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem" \ -o /etc/pki/ca-trust/source/anchors/rds-bundle.pem && \ update-ca-trustRUN apt-get update && apt-get install -y --no-install-recommends curl ca-certificates && \ rm -rf /var/lib/apt/lists/* && \ curl -fsSL "https://truststore.pki.rds.amazonaws.com/global/global-bundle.pem" \ -o /usr/local/share/ca-certificates/rds-bundle.crt && \ update-ca-certificatesFonctions Lambda zippées
Section intitulée « Fonctions Lambda zippées »Pour les fonctions Lambda zippées utilisant les runtimes Node.js 20 ou ultérieurs, chargez le bundle CA Amazon RDS en définissant NODE_EXTRA_CA_CERTS :
const api = new Api(this, 'Api', { integrations: Api.defaultIntegrations(this) .withDefaultOptions({ environment: { NODE_EXTRA_CA_CERTS: '/var/runtime/ca-cert.pem', }, }) .build(),});module "api" { source = "..." ...
environment_variables = { NODE_EXTRA_CA_CERTS = "/var/runtime/ca-cert.pem" }}Pour plus de détails, consultez les exigences SSL/TLS pour les connexions Amazon RDS d’AWS Lambda. Lors de l’utilisation de RDS Proxy, vous n’avez pas besoin de configurer le bundle CA RDS dans le runtime qui se connecte à la base de données.
Instances de cluster
Section intitulée « Instances de cluster »Configurez les instances d’écriture et de lecture pour votre cluster Aurora.
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... writer: ClusterInstance.serverlessV2('writer'), readers: [ClusterInstance.serverlessV2('reader')],});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... instance_count = 2 # 1 writer + 1 reader}Capacité Serverless
Section intitulée « Capacité Serverless »Contrôlez les limites de mise à l’échelle d’Aurora Serverless v2 pour correspondre à votre charge de travail.
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... serverlessV2MinCapacity: 0.5, serverlessV2MaxCapacity: 8,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... serverless_min_capacity = 0.5 serverless_max_capacity = 8}Version du moteur
Section intitulée « Version du moteur »Épinglez une version spécifique du moteur Aurora.
Par défaut, l’image de conteneur de base de données locale générée correspond à la version par défaut du moteur Aurora. Si vous modifiez la version du moteur Aurora, il est recommandé d’utiliser également une version d’image de conteneur locale correspondante pour une compatibilité maximale. Consultez les notes de version AWS pour les versions Aurora PostgreSQL et les versions Aurora MySQL pour identifier la version de base de données communautaire correspondante.
L’image de base de données locale est configurée dans le champ localDev.image du fichier config.json généré à la racine de votre projet de base de données. Mettez à jour cette valeur lorsque vous changez de version de moteur.
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... engineVersion: AuroraPostgresEngineVersion.VER_17_7,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... engine_version = "17.7"}import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... engineVersion: AuroraMysqlEngineVersion.VER_3_12_0,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... engine_version = "8.0.mysql_aurora.3.12.0"}Protection contre la suppression
Section intitulée « Protection contre la suppression »Le cluster Aurora est protégé par deux garde-fous indépendants, de sorte que la désactivation de l’un seul ne peut pas supprimer vos données :
deletionProtection, appliqué par RDS.RemovalPolicy.RETAIN, appliqué par CloudFormation, qui laisse le cluster en place lorsqu’il est retiré de la stack.
deletion_protection, appliqué par RDS.lifecycle { prevent_destroy = true }sur le cluster danscommon/terraform/src/core/rdb/aurora/aurora.tf, appliqué par Terraform, qui fait échouer tout plan qui détruirait le cluster.
Suppression de la base de données
Section intitulée « Suppression de la base de données »Vous pouvez désactiver la protection pour les environnements où la suppression de la base de données est attendue, comme les stacks de développement ou de prévisualisation éphémères.
import { RemovalPolicy } from 'aws-cdk-lib';import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... deletionProtection: false, removalPolicy: RemovalPolicy.DESTROY,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... deletion_protection = false skip_final_snapshot = true}prevent_destroy doit être un littéral — Terraform ne permet pas de référencer une variable — il ne peut donc pas être désactivé depuis main.tf. Supprimez également le bloc lifecycle du cluster dans common/terraform/src/core/rdb/aurora/aurora.tf :
resource "aws_rds_cluster" "database" { # ...
lifecycle { prevent_destroy = true }}Politique de suppression
Section intitulée « Politique de suppression »Le construct CDK conserve le cluster Aurora par défaut (removalPolicy: RemovalPolicy.RETAIN). Modifiez ceci lorsque vous souhaitez que la suppression de la stack CDK crée un snapshot ou détruise le cluster à la place.
Lors de l’utilisation de RemovalPolicy.DESTROY, la protection contre la suppression doit également être désactivée avant que le cluster puisse être supprimé.
import { RemovalPolicy } from 'aws-cdk-lib';import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... removalPolicy: RemovalPolicy.SNAPSHOT,});Pour un environnement éphémère où la base de données doit être supprimée avec la stack :
import { RemovalPolicy } from 'aws-cdk-lib';import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... deletionProtection: false, removalPolicy: RemovalPolicy.DESTROY,});Terraform n’utilise pas les politiques de suppression CDK. Par défaut, le module crée un snapshot final lors de la suppression (skip_final_snapshot = false). Pour ignorer le snapshot final dans un environnement éphémère :
module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... deletion_protection = false skip_final_snapshot = true}Journalisation et surveillance
Section intitulée « Journalisation et surveillance »Le journal postgresql est exporté pour Aurora PostgreSQL, avec une journalisation limitée aux instructions DDL uniquement (log_statement=ddl) afin que les valeurs des paramètres des instructions ne soient jamais enregistrées — tant que chaque instruction est envoyée séparément. log_statement=ddl enregistre l’intégralité du texte brut d’un lot multi-instructions (par exemple, un seul appel psql -c "a;b;c") tel quel si une instruction du lot est DDL, y compris toutes les valeurs DML dans ce même lot.
Les journaux audit et error sont exportés pour Aurora MySQL — general et slowquery sont délibérément exclus car ils enregistrent le texte complet des instructions, y compris les valeurs DML. Advanced Auditing est limité aux connexions et au DDL (server_audit_events=CONNECT,QUERY_DDL), de sorte que les valeurs des paramètres d’instruction ne sont jamais enregistrées.
Performance Insights est activé par défaut sur l’instance writer Aurora (chiffré avec la clé KMS du cluster). Les journaux du moteur Aurora sont également exportés vers CloudWatch Logs par défaut, configurés pour exposer l’activité au niveau du schéma sans divulguer les données de ligne.
Désactivez l’export des journaux par base de données si ce n’est pas nécessaire :
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... enableCloudwatchLogs: false, enablePerformanceInsights: false,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... enable_cloudwatch_logs = false # disable if not required enable_performance_insights = false # disable if not required}Rotation de clé de chiffrement
Section intitulée « Rotation de clé de chiffrement »La clé KMS utilisée pour chiffrer le cluster Aurora et son secret d’identifiants a la rotation automatique des clés activée par défaut. Désactivez-la si votre politique de sécurité gère la rotation en externe.
import { MyDatabase } from '@my-scope/common-constructs';
const db = new MyDatabase(this, 'Db', { ... enableKeyRotation: false,});module "my_database" { source = "../../common/terraform/src/app/dbs/my-database" ... enable_key_rotation = false}Limitations
Section intitulée « Limitations »MySQL : Mode de streaming API Gateway
Section intitulée « MySQL : Mode de streaming API Gateway »Lors de l’utilisation d’Aurora MySQL avec les réponses en streaming API Gateway (par exemple avec le httpBatchStreamLink de tRPC), le client MySQL Prisma conserve la boucle d’événements Node.js après la fin d’une requête, empêchant le Lambda de vider le flux et de terminer la requête.
Pour contourner ce problème, déconnectez explicitement le client dans un bloc finally après chaque requête afin que la boucle d’événements soit libre de se terminer et que la réponse en streaming puisse se terminer.
Option 1 : par procédure
export const listExampleTable = publicProcedure .output(z.array(ExampleTableSchema)) .query(async () => { const prisma = await getPrisma(); try { return await prisma.exampleTable.findMany(); } finally { await prisma.$disconnect(); } });Option 2 : middleware tRPC
Si vous utilisez le modèle de middleware, ajoutez l’appel $disconnect() au middleware afin que toutes les procédures construites dessus soient automatiquement couvertes :
import { getPrisma } from '@my-scope/db';import { initTRPC } from '@trpc/server';
export interface IDbContext { db: Awaited<ReturnType<typeof getPrisma>>;}
export const createDbPlugin = () => { const t = initTRPC.context<IDbContext>().create(); return t.procedure.use(async (opts) => { const db = await getPrisma(); try { return await opts.next({ ctx: { ...opts.ctx, db, }, }); } finally { await db.$disconnect(); } });};MySQL : Expiration du jeton IAM
Section intitulée « MySQL : Expiration du jeton IAM »Les jetons d’authentification IAM RDS expirent après 15 minutes. Le client MySQL Prisma capture le jeton IAM comme une valeur statique au moment où getPrisma() est appelé. Une connexion ouverte existante n’est pas affectée, mais si une nouvelle connexion doit être établie après l’expiration du jeton, l’authentification échouera. L’adaptateur PostgreSQL évite cela en actualisant le jeton dynamiquement chaque fois que le pool ouvre une nouvelle connexion, mais l’adaptateur MySQL n’a pas de mécanisme équivalent.
Pour les tâches de longue durée telles que les travaux par lots ou les migrations de données, appelez getPrisma() au début de chaque unité de travail plutôt qu’une seule fois pour l’ensemble de l’opération. Parce que getPrisma() crée toujours un nouveau client et récupère un nouveau jeton IAM pour MySQL, cela garantit que chaque connexion s’authentifie avec un jeton valide.
Connexions
Section intitulée « Connexions »Utilisez le générateur connection pour intégrer ce projet avec d’autres dans votre espace de travail. Les connexions suivantes impliquent ce projet :