packages/blueprints/gen-ai-chatbot/static-assets/chatbot-genai-cdk/lib/constructs/database.ts (59 lines of code) (raw):
import { CfnOutput, RemovalPolicy, Stack } from "aws-cdk-lib";
import {
AttributeType,
BillingMode,
Table,
TableEncryption,
StreamViewType,
} from "aws-cdk-lib/aws-dynamodb";
import { AccountPrincipal, Role } from "aws-cdk-lib/aws-iam";
import { Construct } from "constructs";
export interface DatabaseProps {
pointInTimeRecovery?: boolean;
}
export class Database extends Construct {
readonly table: Table;
readonly tableAccessRole: Role;
readonly websocketSessionTable: Table;
constructor(scope: Construct, id: string, props?: DatabaseProps) {
super(scope, id);
const table = new Table(this, "ConversationTable", {
// PK: UserId
partitionKey: { name: "PK", type: AttributeType.STRING },
// SK: ConversationId | BotId
sortKey: { name: "SK", type: AttributeType.STRING },
billingMode: BillingMode.PAY_PER_REQUEST,
removalPolicy: RemovalPolicy.DESTROY,
stream: StreamViewType.NEW_IMAGE,
pointInTimeRecovery: props?.pointInTimeRecovery,
encryption: TableEncryption.AWS_MANAGED,
});
table.addGlobalSecondaryIndex({
// Used to fetch conversation or bot by id
indexName: "SKIndex",
partitionKey: { name: "SK", type: AttributeType.STRING },
});
table.addGlobalSecondaryIndex({
// Used to fetch public bots
indexName: "PublicBotIdIndex",
partitionKey: { name: "PublicBotId", type: AttributeType.STRING },
// TODO: add `nonKeyAttributes` for efficiency
// For now we project all attributes to keep future compatibility
});
table.addLocalSecondaryIndex({
// Used to fetch all bots for a user. Sorted by bot used time
indexName: "LastBotUsedIndex",
sortKey: { name: "LastBotUsed", type: AttributeType.NUMBER },
// TODO: add `nonKeyAttributes` for efficiency
// For now we project all attributes to keep future compatibility
});
const tableAccessRole = new Role(this, "TableAccessRole", {
assumedBy: new AccountPrincipal(Stack.of(this).account),
});
table.grantReadWriteData(tableAccessRole);
// Websocket session table.
// This table is used to concatenate user input exceeding 32KB which is the limit of API Gateway.
const websocketSessionTable = new Table(this, "WebsocketSessionTable", {
partitionKey: { name: "ConnectionId", type: AttributeType.STRING },
sortKey: { name: "MessagePartId", type: AttributeType.NUMBER },
billingMode: BillingMode.PAY_PER_REQUEST,
removalPolicy: RemovalPolicy.DESTROY,
timeToLiveAttribute: "expire",
});
this.table = table;
this.tableAccessRole = tableAccessRole;
this.websocketSessionTable = websocketSessionTable;
new CfnOutput(this, "ConversationTableName", {
value: table.tableName,
});
}
}