使用依赖注入的无服务器数据库设置



所以,我正在使用express和TypeORM的无服务器lambda

我有问题实例数据库,然后在存储库类中使用它来检索数据。

// handler.ts
require('source-map-support/register');
import App from './features/app';
import LeadsController from './features/leads/leads.controller';
import { Container } from 'typedi';
import 'source-map-support/register';
import serverlessExpress from '@vendia/serverless-express';
import { Context } from 'aws-lambda';
const setup = async (event: any, context: Context) => {
const app = new App([Container.get(LeadsController)], 3000);
await app.init();
return serverlessExpress({ app: app.app })(event, context, () => {
console.log('callback');
});
};
const handler = (event: any, context: Context) => {
return setup(event, context);
};
exports.handler = handler;
// app.ts
import express, { Router } from 'express';
import bodyParser from 'body-parser';
import 'reflect-metadata';
import { Database } from '../common/database/db';
class App {
public app: express.Application;
public port: number;
constructor(controllers: any[], port: number) {
this.app = express();
this.port = port;
this.initializeMiddlewares();
this.initializeControllers(controllers);
this.endMiddlewares();
}
async init() {
const database = new Database(); // HERE IS WHERE MY PROBLEM IS, I CAN'T FIND ANOTHER WAY TO INIT THE DATABASE
await database.connect();
}
private initializeMiddlewares() {
this.app.use(bodyParser.json());
}
private initializeControllers(controllers: any[]) {
const router: Router[] = [];
controllers.forEach((controller) => {
router.push(controller.router);
});
this.app.use('/api', router);
}
private endMiddlewares() {
// @todo: set up error handler;
}
}
export default App;
// repository.ts
import { Service } from 'typedi';
import { Database } from '../../common/database/db';
import { Lead } from './leads.entity';
@Service()
export class LeadsRepository {
private repository;
constructor(private readonly db: Database) {
console.log(db); // AND HERE IS MY OTHER PROBLEM
this.repository = this.db.dataSource.getRepository(Lead);
}
async findAll() {
return await this.repository.find();
}
}
// db.ts
import { DataSource } from 'typeorm';
import { Lead } from '../../features/leads/leads.entity';
import { Interest } from '../../features/interests/interests.entity';
import { MysqlConnectionOptions } from 'typeorm/driver/mysql/MysqlConnectionOptions';
import { Service } from 'typedi';
/**
* Database manager class
*/
@Service()
export class Database {
dataSource: DataSource;
constructor() {}
async connect() {
const connectionOptions: MysqlConnectionOptions = {
type: 'mysql',
host: 'localhost',
port: 33061,
username: 'root',
password: 'root',
database: 'leads-interests',
synchronize: true,
dropSchema: true,
logging: 'all',
entities: [Lead, Interest],
subscribers: [],
migrations: [__dirname + '/migration.{ts,js}'],
migrationsTableName: '_migration'
};
this.dataSource = new DataSource(connectionOptions);
await this.dataSource.initialize();
console.log('Connected');
}
}

经过大量的思考和学习依赖注入,我得出的结论是,我的问题是在哪里我实例数据库放在第一位,但我不知道我应该在哪里做,因为它是一个异步调用,我不想每次都要创建新的实例,我必须检索或插入数据。

是否有人有另一个解决方案或更好的代码架构,我可以使用?

最后,我需要的是始终使用相同的数据库实例

我看到应用程序的构造函数在它的依赖项中有控制器(这又依赖于存储库,然后是数据库?),在数据库连接函数完成它的任务之前,控制器已经从容器中解析出来了。

要解决这个问题,尝试先在setup函数中实例化数据库,并显式地在容器中设置数据库,如下所示:

const setup = async (event: any, context: Context) => {
const database = new Database();
await database.connect();
Container.set(Database,database); //import Container from 'typedi'
const app = new App([Container.get(LeadsController)], 3000);
await app.init();
return serverlessExpress({ app: app.app })(event, context, () => {
console.log('callback');
});
};

或者更好的是,在setup函数上初始化数据源,并为它创建一个自定义标识符,然后使用存储库中的注入令牌注入数据源。

一般来说,我不建议在无服务器功能上执行依赖注入,因为它会增加冷启动时间,你应该尝试在无服务器环境中优化应用程序的启动时间。

最新更新