ArsenyYankovsky / typeorm-aurora-data-api-driver

A bridge between TypeORM and Aurora Data API
MIT License
175 stars 38 forks source link

AlreadyHasActiveConnectionError: Cannot create a new connection named "default", because connection with such name already exist and it now has an active connection session #112

Open Sharvin26 opened 3 years ago

Sharvin26 commented 3 years ago

Package versions and database engine type:

Describe the bug Hello, thank you for creating this amazing driver. It's a lot helpful.

I am refering this issue for maintaing connection with Aurora Serverless and lambda.

I am using serverless framework as infrastucture as a code tool. The issue I am facing is when I make a first API call everything works properly but on second API call I get the following error:

AlreadyHasActiveConnectionError: Cannot create a new connection named "default", because connection with such name already exist and it now has an active connection session.
    at AlreadyHasActiveConnectionError.TypeORMError [as constructor]

To Reproduce The following is my db.ts where I have written all the logic for maintaing connection with reference to above issue.

import "reflect-metadata";
import { Todo } from "src/entity/Todo";
import {
  Connection,
  ConnectionOptions,
  createConnection,
  EntityTarget,
} from "typeorm";

let cachedConnection: Connection;

const getConnection = async () => {
  if (cachedConnection) {
    return cachedConnection;
  }

  const secretArn: string = process.env.AWS_SECRET_ARN;
  const resourceArn: string = process.env.AWS_RESOURCE_ARN;
  const region: string = process.env.AWS_REGION;

  const connectionOptions: ConnectionOptions = {
    type: "aurora-data-api-pg",
    database: "todoapp",
    secretArn,
    resourceArn,
    region,
  };

  cachedConnection = await createConnection({
    ...connectionOptions,
    entities: [Todo],
  });

  return cachedConnection;
};

export const getData = async (Model: EntityTarget<unknown>) => {
  try {
    const connection = await getConnection();
    const modelRepository = connection.getRepository(Model);
    const data = await modelRepository.find();
    return data;
  } catch (error) {
    throw error;
  }
};

export const addData = async (Model: EntityTarget<unknown>, data: unknown) => {
  try {
    const connection = await getConnection();
    const modelRepository = connection.getRepository(Model);
    await modelRepository.save(data);
  } catch (error) {
    throw error;
  }
};

I am just calling this getData and addData methods from my lambda functions as follows:

function1:

await addData(Todo, data);

function2:

const todos = await getData(Todo); 

Note: I am using serverless-offline plugin to run the code offline. ( Not sure if this may be causing the issue )

What I have seen is that cachedConnection becomes null on second different API call however it shouldn't.

Can you please check what I am doing wrong and how can I resolve this issue?

chadfaurie commented 3 years ago

You can use connection = getConnection(); to return the default connection and check if it already exists

I did this incase it threw and error and works fine in Lambda

let connection: Connection;

try {
  connection = getConnection();
} catch (ex) { }