Aller au contenu principal

Stockage Aurora DSQL

L’implémentation du stockage Aurora DSQL fournit un stockage basé sur Amazon Aurora DSQL avec authentification IAM.

Aurora DSQL ne prend pas en charge les extensions PostgreSQL (CREATE EXTENSION), notamment pgvector. Pour le stockage vectoriel, utilisez une base vectorielle distincte telle que @mastra/s3vectors.

Installation
Lien direct vers Installation

npm install @mastra/dsql@beta

Prérequis
Lien direct vers Prérequis

  • Cluster Amazon Aurora DSQL
  • Identifiants AWS donnant accès au cluster DSQL (authentification IAM)

Utilisation
Lien direct vers Utilisation

import { DSQLStore } from '@mastra/dsql'

const storage = new DSQLStore({
id: 'my-dsql-store',
host: 'abc123.dsql.us-east-1.on.aws',
// region is auto-detected from host, or specify explicitly:
// region: 'us-east-1',
// user: 'admin', // default
// database: 'postgres', // default
})

// Initialize the store (creates tables if needed)
await storage.init()

Paramètres
Lien direct vers Paramètres

id:

string
Identifiant unique de cette instance de stockage

host:

string
Point de terminaison du cluster DSQL (par exemple, abc123.dsql.us-east-1.on.aws)

pool?:

pg.Pool
Instance pg.Pool préconfigurée. Utilisez-la pour contrôler directement le pool de connexions. Incompatible avec la configuration host.

user?:

string
Utilisateur de la base de données. Le rôle d’administration d’Aurora DSQL est 'admin'.

database?:

string
Nom de la base de données. Aurora DSQL expose une seule base nommée 'postgres' par cluster.

region?:

string
Région AWS. Extraite de host si elle n’est pas fournie.

schemaName?:

string
Nom du schéma PostgreSQL dans lequel les tables et index Mastra sont créés.

customCredentialsProvider?:

AwsCredentialIdentityProvider
Provider d’identifiants AWS personnalisé pour l’authentification IAM.

max?:

number
Nombre maximal de connexions dans le pool.

min?:

number
Nombre minimal de connexions dans le pool.

idleTimeoutMillis?:

number
Ferme les connexions inactives après ce nombre de millisecondes.

maxLifetimeSeconds?:

number
Durée de vie maximale d’une connexion, en secondes. Doit être inférieure à 3600 en raison de la limite de connexion de 60 minutes d’Aurora DSQL.

connectionTimeoutMillis?:

number
Délai d’expiration de l’acquisition d’une connexion, en millisecondes.

allowExitOnIdle?:

boolean
Autorise le processus à se terminer lorsque toutes les connexions sont inactives.

Exemples de construction
Lien direct vers Exemples de construction

Vous pouvez instancier DSQLStore de différentes manières :

import { DSQLStore } from '@mastra/dsql'

// Basic configuration (region auto-detected from host)
const store1 = new DSQLStore({
id: 'my-dsql-store',
host: 'abc123.dsql.us-east-1.on.aws',
})

// With explicit region and schema
const store2 = new DSQLStore({
id: 'my-dsql-store',
host: 'abc123.dsql.us-east-1.on.aws',
region: 'us-east-1',
schemaName: 'my_app',
})

// With custom credentials provider
import { fromNodeProviderChain } from '@aws-sdk/credential-providers'

const store3 = new DSQLStore({
id: 'my-dsql-store',
host: 'abc123.dsql.us-east-1.on.aws',
customCredentialsProvider: fromNodeProviderChain(),
})

// With connection pool settings
const store4 = new DSQLStore({
id: 'my-dsql-store',
host: 'abc123.dsql.us-east-1.on.aws',
max: 20,
min: 2,
idleTimeoutMillis: 300000,
maxLifetimeSeconds: 3000,
connectionTimeoutMillis: 10000,
})

// Using a pre-configured pg.Pool
import { Pool } from 'pg'
import { AuroraDSQLClient } from '@aws/aurora-dsql-node-postgres-connector'

const pool = new Pool({
host: 'abc123.dsql.us-east-1.on.aws',
Client: AuroraDSQLClient,
region: 'us-east-1',
})

const store5 = new DSQLStore({
id: 'my-dsql-store',
pool,
})

Remarques supplémentaires
Lien direct vers Remarques supplémentaires

Gestion du schéma
Lien direct vers Gestion du schéma

L’implémentation du stockage gère automatiquement la création et la mise à jour du schéma. Elle crée les tables suivantes :

  • mastra_workflow_snapshot : stocke l’état et les données d’exécution des Workflows
  • mastra_threads : stocke les fils de conversation
  • mastra_messages : stocke les messages individuels
  • mastra_ai_spans : stocke les données de spans pour l’observabilité
  • mastra_scorers : stocke les données de scoring et d’évaluation
  • mastra_resources : stocke les données de mémoire de travail des ressources
  • mastra_agents : stocke les données des Agents

Initialisation
Lien direct vers Initialisation

Lorsque vous transmettez le stockage à la classe Mastra, init() est appelée automatiquement avant toute opération de stockage :

import { Mastra } from '@mastra/core'
import { DSQLStore } from '@mastra/dsql'

const storage = new DSQLStore({
id: 'my-dsql-store',
host: 'abc123.dsql.us-east-1.on.aws',
})

const mastra = new Mastra({
storage, // init() is called automatically
})

Si vous utilisez directement le stockage sans Mastra, vous devez appeler explicitement init() pour créer les tables :

import { DSQLStore } from '@mastra/dsql'

const storage = new DSQLStore({
id: 'my-dsql-store',
host: 'abc123.dsql.us-east-1.on.aws',
})

// Required when using storage directly
await storage.init()

// Access domain-specific stores via getStore()
const memoryStore = await storage.getStore('memory')
const thread = await memoryStore?.getThreadById({ threadId: '...' })
attention

Si init() n’est pas appelée, les tables ne seront pas créées et les opérations de stockage échoueront silencieusement ou déclencheront des erreurs.

Accès direct à la base de données et au pool
Lien direct vers Accès direct à la base de données et au pool

DSQLStore expose le client de base de données sous-jacent et l’instance pg.Pool comme champs publics :

storage.db // Database client for executing queries
storage.pool // Underlying pg.Pool instance

Il prend en charge les requêtes directes et la gestion personnalisée des transactions. Lorsque vous utilisez ces champs :

  • Vous êtes responsable de la bonne gestion des connexions et des transactions.
  • La fermeture du stockage (storage.close()) détruira le pool de connexions s’il a été créé par le stockage.
  • L’accès direct contourne toute logique ou validation supplémentaire fournie par les méthodes de DSQLStore.

Cette approche est destinée aux scénarios avancés qui nécessitent un accès de bas niveau.

Particularités d’Aurora DSQL
Lien direct vers Particularités d’Aurora DSQL

Authentification IAM uniquement
Lien direct vers Authentification IAM uniquement

Les connexions sont authentifiées avec IAM. Aucun mot de passe de base de données n’est requis. @mastra/dsql utilise @aws/aurora-dsql-node-postgres-connector pour générer des tokens d’authentification de courte durée. Vous pouvez fournir un Provider d’identifiants personnalisé via customCredentialsProvider.

Base de données unique et isolation par schéma
Lien direct vers Base de données unique et isolation par schéma

Chaque cluster expose une seule base de données postgres. La séparation logique s’effectue au moyen de schémas. L’option schemaName détermine l’emplacement de création des tables Mastra.

Aucune extension PostgreSQL
Lien direct vers Aucune extension PostgreSQL

CREATE EXTENSION n’est pas pris en charge. Cela inclut pgvector, PostGIS et d’autres extensions. Pour le stockage vectoriel, utilisez une base distincte telle que @mastra/s3vectors avec DSQLStore.

JSON stocké sous forme de texte
Lien direct vers JSON stocké sous forme de texte

JSON/JSONB sont disponibles comme types de requête, mais pas comme types de colonne. @mastra/dsql stocke les champs structurés (métadonnées, contenu, etc.) dans des colonnes TEXT et les convertit en JSON lors des requêtes.

Contraintes de schéma et DDL
Lien direct vers Contraintes de schéma et DDL

Certaines fonctionnalités PostgreSQL ne sont pas disponibles :

  • Contraintes de clé étrangère
  • TRUNCATE
  • CREATE INDEX synchrone

Les index sont créés de manière asynchrone avec CREATE INDEX ASYNC. init() et les API auxiliaires d’index du stockage respectent ces contraintes.

Transactions et accès concurrent optimiste
Lien direct vers Transactions et accès concurrent optimiste

Aurora DSQL utilise le contrôle de concurrence optimiste (OCC) et peut renvoyer des erreurs OCC réessayables en cas de contention. La durée et la taille des transactions sont limitées. Les opérations groupées volumineuses doivent être divisées en lots plus petits au niveau de l’application.

Durée de vie des connexions
Lien direct vers Durée de vie des connexions

Les connexions individuelles sont limitées à environ 60 minutes. La valeur par défaut maxLifetimeSeconds: 3300 garantit leur renouvellement avant cette limite.

Exemple d’utilisation
Lien direct vers Exemple d’utilisation

Ajouter une Memory à un Agent
Lien direct vers Ajouter une Memory à un Agent

Pour ajouter une Memory Aurora DSQL à un Agent, utilisez la classe Memory et créez une nouvelle clé storage avec DSQLStore. host doit pointer vers le point de terminaison de votre cluster Aurora DSQL.

src/mastra/agents/example-dsql-agent.ts
import { Memory } from '@mastra/memory'
import { Agent } from '@mastra/core/agent'
import { DSQLStore } from '@mastra/dsql'

export const dsqlAgent = new Agent({
id: 'dsql-agent',
name: 'DSQL Agent',
instructions:
'You are an AI agent with the ability to automatically recall memories from previous interactions.',
model: 'openai/gpt-5.6-sol',
memory: new Memory({
storage: new DSQLStore({
id: 'dsql-agent-storage',
host: process.env.DSQL_HOST!,
}),
options: {
generateTitle: true, // Explicitly enable automatic title generation
},
}),
})

Utiliser l’Agent
Lien direct vers Utiliser l’Agent

Utilisez memoryOptions pour délimiter le rappel de cette requête. Définissez lastMessages: 5 afin de limiter le rappel fondé sur la récence, puis utilisez semanticRecall pour récupérer les topK: 3 messages les plus pertinents, ainsi que messageRange: 2 messages voisins fournissant du contexte autour de chaque correspondance.

src/test-dsql-agent.ts
import 'dotenv/config'

import { mastra } from './mastra'

const threadId = '123'
const resourceId = 'user-456'

const agent = mastra.getAgent('dsql-agent')

const message = await agent.stream('My name is Mastra', {
memory: {
thread: threadId,
resource: resourceId,
},
})

await message.textStream.pipeTo(new WritableStream())

const stream = await agent.stream("What's my name?", {
memory: {
thread: threadId,
resource: resourceId,
},
memoryOptions: {
lastMessages: 5,
semanticRecall: {
topK: 3,
messageRange: 2,
},
},
})

for await (const chunk of stream.textStream) {
process.stdout.write(chunk)
}

Gestion des index
Lien direct vers Gestion des index

Le stockage Aurora DSQL fournit des fonctionnalités de gestion des index pour optimiser les performances des requêtes.

Index de performance automatiques
Lien direct vers Index de performance automatiques

Lors de l’initialisation, le stockage Aurora DSQL crée automatiquement des index composites pour les modèles de requête courants :

  • mastra_threads_resourceid_createdat_idx: (resourceId, createdAt)
  • mastra_messages_thread_id_createdat_idx: (thread_id, createdAt)
  • mastra_ai_spans_traceid_startedat_idx: (traceId, startedAt)
  • mastra_ai_spans_parentspanid_startedat_idx: (parentSpanId, startedAt)
  • mastra_ai_spans_name_idx: (name)
  • mastra_ai_spans_spantype_startedat_idx: (spanType, startedAt)
  • mastra_scores_trace_id_span_id_created_at_idx: (traceId, spanId, createdAt)

Aurora DSQL crée ces index de manière asynchrone avec CREATE INDEX ASYNC. Leur création étant asynchrone, les nouveaux index peuvent ne pas être immédiatement disponibles après init(). Le stockage continuera de fonctionner sans eux, mais les requêtes pourront être plus lentes jusqu’à la fin de leur création.

Créer des index personnalisés
Lien direct vers Créer des index personnalisés

Créez des index supplémentaires afin d’optimiser certains modèles de requête :

await storage.createIndex({
name: 'idx_threads_resource',
table: 'mastra_threads',
columns: ['resourceId'],
})

await storage.createIndex({
name: 'idx_messages_composite',
table: 'mastra_messages',
columns: ['thread_id', 'createdAt'],
})

Aurora DSQL n’autorise pas ASC/DESC dans CREATE INDEX ASYNC. Si vous les incluez, ils seront automatiquement supprimés.

Options des index
Lien direct vers Options des index

name:

string
Nom unique de l’index

table:

string
Nom de la table (par exemple, 'mastra_threads')

columns:

string[]
Tableau de noms de colonnes. Les modificateurs ASC/DESC sont automatiquement supprimés pour assurer la compatibilité avec Aurora DSQL.

unique?:

boolean
Crée un index unique.

concurrent?:

boolean
Ignoré dans Aurora DSQL. Les index sont toujours créés de manière asynchrone.

where?:

string
Condition d’index partiel.

method?:

string
Ignoré dans Aurora DSQL. Seuls les index btree sont pris en charge.

opclass?:

string
Ignoré dans Aurora DSQL.

storage?:

Record<string, any>
Ignoré dans Aurora DSQL.

tablespace?:

string
Ignoré dans Aurora DSQL. Les tablespaces ne sont pas pris en charge.

Gérer les index
Lien direct vers Gérer les index

Répertoriez et surveillez les index existants :

// List all indexes
const allIndexes = await storage.listIndexes()
console.log(allIndexes)
// [
// {
// name: 'mastra_threads_pkey',
// table: 'mastra_threads',
// columns: ['id'],
// unique: true,
// size: '16 KB',
// definition: 'CREATE UNIQUE INDEX...'
// },
// ...
// ]

// List indexes for a specific table
const threadIndexes = await storage.listIndexes('mastra_threads')

// Get detailed statistics for an index
const stats = await storage.describeIndex('idx_threads_resource')
console.log(stats)
// {
// name: 'idx_threads_resource',
// table: 'mastra_threads',
// columns: ['resourceId'],
// unique: false,
// size: '128 KB',
// definition: 'CREATE INDEX idx_threads_resource...',
// method: 'btree',
// scans: 1542,
// tuples_read: 45230,
// tuples_fetched: 12050
// }

// Drop an index
await storage.dropIndex('idx_threads_status')

Index propres au schéma
Lien direct vers Index propres au schéma

Lorsque vous utilisez des schémas personnalisés, les index sont créés avec des préfixes de schéma :

const storage = new DSQLStore({
id: 'my-dsql-store',
host: 'abc123.dsql.us-east-1.on.aws',
schemaName: 'custom_schema',
})

// Creates index as: custom_schema_idx_threads_status
await storage.createIndex({
name: 'idx_threads_status',
table: 'mastra_threads',
columns: ['status'],
})