使用事务的 mongoose 文档很简单,但是当在 Nestjs 中遵循它时,它会返回一个错误:
Connection 0 was disconnected when calling `startSession`
MongooseError: Connection 0 was disconnected when calling `startSession`
at NativeConnection.startSession
Run Code Online (Sandbox Code Playgroud)
我的代码:
const transactionSession = await mongoose.startSession();
transactionSession.startTransaction();
try
{
const newSignupBody: CreateUserDto = {password: hashedPassword, email, username};
const user: User = await this.userService.create(newSignupBody);
//save the profile.
const profile: Profile = await this.profileService.create(user['Id'], signupDto);
const result:AuthResponseDto = this.getAuthUserResponse(user, profile);
transactionSession.commitTransaction();
return result;
}
catch(err)
{
transactionSession.abortTransaction();
}
finally
{
transactionSession.endSession();
}
Run Code Online (Sandbox Code Playgroud)
Noo*_*ish 21
我在研究@nestjs/mongoose后找到了解决方案。这里的猫鼬与它没有任何联系。这就是返回错误的原因。
解决方案:
import {InjectConnection} from '@nestjs/mongoose';
import * as mongoose from 'mongoose';
Run Code Online (Sandbox Code Playgroud)
在服务类的构造函数中,我们需要添加服务可以使用的连接参数。
export class AuthService {
constructor(
// other dependencies...
@InjectConnection() private readonly connection: mongoose.Connection){}
Run Code Online (Sandbox Code Playgroud)
代替
const transactionSession = await mongoose.startSession();
transactionSession.startTransaction();
Run Code Online (Sandbox Code Playgroud)
我们现在将使用:
const transactionSession = await this.connection.startSession();
transactionSession.startTransaction();
Run Code Online (Sandbox Code Playgroud)
这样就可以解决startSession()后断线的问题了。
除了 Noobish 提供的答案之外,我还想演示我在项目中使用的可重用函数:
import { ClientSession, Connection } from 'mongoose';
export const transaction = async <T>(connection: Connection, cb: (session: ClientSession) => Promise<T>): Promise<T> => {
const session = await connection.startSession();
try {
session.startTransaction();
const result = await cb(session);
await session.commitTransaction();
return result;
} catch (err) {
await session.abortTransaction();
throw err;
} finally {
await session.endSession();
}
}
Run Code Online (Sandbox Code Playgroud)
然后可以像这样使用它:
@Injectable()
export class MyService {
constructor(
@InjectModel(MyModel.name) private myModel: Model<MyModelDocument>,
@InjectConnection() private connection: Connection,
) {}
async find(id: string): Promise<MyModelDocument> {
return transaction(this.connection, async session => {
return this.myModel
.findOne(id)
.session(session);
});
}
async create(myDto: MyDto): Promise<MyModelDocument> {
return transaction(this.connection, async session => {
const newDoc = new this.myModel(myDto);
return newDoc.save({ session });
});
}
Run Code Online (Sandbox Code Playgroud)
显然,上面的示例仅用于演示目的,其中不需要事务,因为操作已经是原子的。但是,可以使用更复杂的示例来扩展内部回调,其中操作不是原子的,例如:
session在所有这些步骤中仔细指定| 归档时间: |
|
| 查看次数: |
9442 次 |
| 最近记录: |