Giter VIP home page Giter VIP logo

Comments (15)

pavel-xendit avatar pavel-xendit commented on June 12, 2024 1

@odavid @mohsinamjad
Any thoughts on how to make runIntransactions work?

from typeorm-transactional-cls-hooked.

mohsinamjad avatar mohsinamjad commented on June 12, 2024 1

For multi tenant your connection name will be dynamic like in my case I set tenant ID as connection name, and you can't use same connection name is e.g default.
You have to use this.connectio.name for it.

from typeorm-transactional-cls-hooked.

odavid avatar odavid commented on June 12, 2024

Thanks!
I have not tested this can of setup, however, I believe you need to define the connectionName within the decorator.
You can use function that returns the connectionName, but it is a must, if it is not default

See https://github.com/odavid/typeorm-transactional-cls-hooked#using-transactional-decorator

Hope it helps...

from typeorm-transactional-cls-hooked.

gcherem avatar gcherem commented on June 12, 2024

Thanks @odavid for your reply. Unfortunately I have no idea how to get the connection name within the decorator, since I have no access to the request in that context (I think), The connection name is the tenant name that I retrieve from the JWT in the Authorization header. Any idea? Could you please provide an example or direct me to a sample? Thanks in advance.

from typeorm-transactional-cls-hooked.

odavid avatar odavid commented on June 12, 2024

Hi @gcherem, I think that once this PR will be merged, you will be able to use the
runInTransaction function instead of the decorator

from typeorm-transactional-cls-hooked.

naorye avatar naorye commented on June 12, 2024

I don't think this is related to multi tenant. I am using nestjs and it doesn't work as well.

from typeorm-transactional-cls-hooked.

alanscordoba avatar alanscordoba commented on June 12, 2024

Gracias @odavid por tu respuesta. Desafortunadamente, no tengo idea de cómo obtener el nombre de la conexión dentro del decorador, ya que no tengo acceso a la solicitud en ese contexto (creo). El nombre de la conexión es el nombre del inquilino que recupero del JWT en el encabezado de Autorización. ¿Alguna idea? ¿Podría darme un ejemplo o dirigirme a una muestra? Gracias por adelantado.

Hello, I am stuck in this same situation. Some help?

from typeorm-transactional-cls-hooked.

mohsinamjad avatar mohsinamjad commented on June 12, 2024

I'm using multi tenant too just as op said,
I need some help to resolve dynamic connections?

from typeorm-transactional-cls-hooked.

alanscordoba avatar alanscordoba commented on June 12, 2024

I can't get everything to run within the same transaction.

I have the following code:

export class TestService {
  repository: any;
  constructor(
  @Inject(TENANT_CONNECTION) private connection)
  {
    this.repository = connection.getRepository(Test)
  }`

 @Transactional()
  async agregar(tableNew: Test): Promise<Number> {
    const tableSave = this.repository.create(tableNew)
    await this.repository.save(tableSave)
    if(tableSave.default){
      await this.repository.update(
            {default:true,id:Not(tableSave.id)},
            {default:false}
      )
    }
    return tableSave.id 
}

The following is executed in the database:

query: START TRANSACTION
query: SELECT `Test`.`id` AS `Test_id`,`Test`.`default` AS `Test_default` FROM `test` `Test` WHERE `Test`.`id` IN (?) -- PARAMETERS: [0]
query: START TRANSACTION
query: INSERT INTO `test`(`id`,`default`) VALUES (?,?) -- PARAMETERS: [0,1]
query: COMMIT
query: UPDATE `test` SET `default` = ? WHERE (`default` = ? AND `id` != ?) -- PARAMETERS: [0,true,41]
query: COMMIT

As you can see, 2 transactions are executed, I need it to be only one

from typeorm-transactional-cls-hooked.

mohsinamjad avatar mohsinamjad commented on June 12, 2024

it's working for me now
here is the code snippet for multi tenant

  return runInTransaction(
      async () => {
       // async operations
      },
      { connectionName: this.connection.name },
    );

from typeorm-transactional-cls-hooked.

pavel-xendit avatar pavel-xendit commented on June 12, 2024

@mohsinamjad
This is not working for me.
I tried to put logic inside runInTransaction but still, the transaction is happening for each case. I want to have one transaction for all DB transactions.

from typeorm-transactional-cls-hooked.

mohsinamjad avatar mohsinamjad commented on June 12, 2024

@pavel-xendit
weird, why the heck it's working for me then, I've tested on simple use-case though
Are you giving connectionName in the second param of runInTransacion?

my package info

"typeorm": "0.2.34",
"typeorm-transactional-cls-hooked": "0.1.21",

from typeorm-transactional-cls-hooked.

pavel-xendit avatar pavel-xendit commented on June 12, 2024

@mohsinamjad
How can I get connectionName? I passed default as connectionName.

from typeorm-transactional-cls-hooked.

mopcweb avatar mopcweb commented on June 12, 2024

it is possible to use async-hooks or cls-hooked or some other similar package for creating request scoped context.
after that it is quite easy to use it in Transactional callback to get necessary connection

from typeorm-transactional-cls-hooked.

barokurniawan avatar barokurniawan commented on June 12, 2024

I believe that there is no definitive solution to this problem.

In my case, I used middleware to initialize the database connection and store it in a global variable so the user can re-use it, but that caused the transactional issue since addTransactionalDataSource should be only called when init the app .

So I came out with a solution to sync all tenant data to a JSON file (only the scheme name) and read the file data on app init so I can register all schemes with addTransactionalDataSource.

Some sample

import { TypeOrmModule } from "@nestjs/typeorm";
import { DataSource } from "typeorm";
import { addTransactionalDataSource } from "typeorm-transactional";
import * as con  from "./connections";

export const DatabaseConfig = TypeOrmModule.forRootAsync({
    useFactory() {
        return {
            type: 'postgres',
            host: process.env.DB_HOST,
            port: +process.env.DB_PORT,
            username: process.env.DB_USER,
            password: process.env.DB_PASSWORD,
            database: process.env.DB_NAME,
            entities: ["dist/**/*.entity{.ts,.js}"],
            migrations: ["dist/src/database/migrations/*{.ts,.js}"],
            logging: true,
            synchronize: false,
            migrationsRun: true,
            migrationsTransactionMode: 'all',
            useUTC: true
        };
    },
    async dataSourceFactory(options) {
        if (!options) {
            throw new Error('Invalid options passed');
        }

        let mainDs: DataSource;
       
        const tenants = ['public'];
        for (const schema of tenants) {
            const source = new DataSource({
                ...options,
                schema: schema,
            } as any);
            const ds = addTransactionalDataSource({name: schema, dataSource: source});
            con.connectionMap.set(schema, ds);

            if(schema == "public") {
                mainDs = ds;
            }
        }

        return mainDs;
    },
});

Just imagine this part const tenants = ['public']; are a list you get from a JSON file, con.connectionMap is a const connectionMap = new Map<string, DataSource>();.

The downside is that I have to restart the app every time a new tenant arrives, and hope someone jumps in and gives a pro solution.

from typeorm-transactional-cls-hooked.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.