Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple connections with @nestjs/config dependency #684

Closed
sergiopedrerobenedi opened this issue Jul 8, 2020 · 22 comments
Closed

Multiple connections with @nestjs/config dependency #684

sergiopedrerobenedi opened this issue Jul 8, 2020 · 22 comments

Comments

@sergiopedrerobenedi
Copy link

sergiopedrerobenedi commented Jul 8, 2020

Hi @willsoto.

Your module is really awesome!
But i have this problem:

I don't know how to implement multiple database connections with your module.
I need to use NestJS ConfigService for two database connections like this:

@Module(
  {
    imports: [ConfigModule.forFeature(firstDatabaseConfig),
      ObjectionModule.registerAsync({ imports: [ConfigModule],
        useFactory(config: ConfigService) {
          return {
            config: {
              ...config.get<knex.Config>('first-database-config'),
            },
          };
        },
        inject: [ConfigService] }), ObjectionModule.forFeature([FirstModel])], 
    controllers: [],
    exports: [ObjectionModule]},
)
export class FirstDatabaseModule {}
@Module(
  {
    imports: [ConfigModule.forFeature(secondDatabaseConfig),
      ObjectionModule.registerAsync({ imports: [ConfigModule],
        useFactory(config: ConfigService) {
          return {

            config: {
              ...config.get<knex.Config>('second-database-config'),

            },
          };
        },
        inject: [ConfigService] }), ObjectionModule.forFeature([SecondModel])], 
    controllers: [],
    exports: [ObjectionModule],

  },
)
export class FirstDatabaseModule {}

But when i make queries through each model, always works with first database configuration.

Could you help me?
Thanks!

@sergiopedrerobenedi sergiopedrerobenedi changed the title Multiple connections with ConfigModule Multiple connections with @nestjs/config dependency Jul 8, 2020
@willsoto
Copy link
Owner

willsoto commented Jul 9, 2020

@sergiopedrerobenedi What are your base classes? Do FirstModel and SecondModel share the same base class? Remember that objection binds itself to knex via Model.knex(connection). And based on your code snippet both of your modules are being bound to the same base class (since by default I use objection's default Model if none is provided).

Can we start there and see if that fixes it?

@sergiopedrerobenedi
Copy link
Author

sergiopedrerobenedi commented Jul 9, 2020

Hi @willsoto , I setted different BaseClass to the different database connections, like you said.
I have a service, and I inject the two different models here.
When i query with the first model, it is running perfect. But when i query with the second model i have the next error:

[Nest] 62558   - 2020-07-09 14:13:28   [RpcExceptionsHandler] no database connection available for a query. You need to bind the model class or the query to a knex instance. +7003ms
Error: no database connection available for a query. You need to bind the model class or the query to a knex instance.

@willsoto
Copy link
Owner

willsoto commented Jul 9, 2020

Did you correctly register each base class with this module?

@sergiopedrerobenedi
Copy link
Author

Yes , i did.
Like this?

import { Model } from 'objection';

export class BaseA extends Model {}
import { Model } from 'objection';

export class BaseB extends Model {}

And then in the modules

@Module(
  {
    imports: [ConfigModule.forFeature(firstDatabaseConfig),
      ObjectionModule.registerAsync({ imports: [ConfigModule],
        useFactory(config: ConfigService) {
          return {
            Model:BaseA,
            config: {
              ...config.get<knex.Config>('first-database-config'),
            },
          };
        },
        inject: [ConfigService] }), ObjectionModule.forFeature([FirstModel])], 
    controllers: [],
    exports: [ObjectionModule]},
)
export class FirstDatabaseModule {}

@Module(
  {
    imports: [ConfigModule.forFeature(secondDatabaseConfig),
      ObjectionModule.registerAsync({ imports: [ConfigModule],
        useFactory(config: ConfigService) {
          return {
            Model: BaseB
            config: {
              ...config.get<knex.Config>('second-database-config'),

            },
          };
        },
        inject: [ConfigService] }), ObjectionModule.forFeature([SecondModel])], 
    controllers: [],
    exports: [ObjectionModule],

  },
)
export class FirstDatabaseModule {}

@willsoto
Copy link
Owner

willsoto commented Jul 9, 2020

Yeah that looks right. I think I have an idea of what is going on here. I don't think registering the same module twice will have any effect. I'll have to add a way to support multiple connections.

I can make register and registerAsync accept an array of configurations. You will still have to have two base classes (that is just how objection works) but that should solve your use case. Give me a day or two to work on this.

@sergiopedrerobenedi
Copy link
Author

It sounds really nice!
I look forward to hearing from you.
Thank you @willsoto

@willsoto
Copy link
Owner

Published under v3.0.0

@willsoto
Copy link
Owner

willsoto commented Jul 10, 2020

Documentation: https://github.com/willsoto/nestjs-objection#multiple-connections

Please let me know if you have any issues.

@sergiopedrerobenedi
Copy link
Author

Hello @willsoto !
It works fine but only one question.
When I import ObjectionModule into my DatabaseModule in the registerAsync function , VsCode tell me that 'name' property (database name property) not exists , but i can compile it and run it with different database instances good.
Thanks!

@willsoto
Copy link
Owner

Can you paste a code snippet please?

@sergiopedrerobenedi
Copy link
Author

@Global()
@Module(
  {
    imports: [ConfigModule.forFeature(firstDatabaseConfig),
      ObjectionModule.registerAsync({
        name: 'connection1',
        imports: [ConfigModule],
        useFactory(config: ConfigService) {
          return {
            Model: BaseModelA,
            config: {
              ...config.get<knex.Config>('first-database-config'),

            },
          };
        },
        inject: [ConfigService],
      }),

Here I have a code error . VS Code says me (relative to name field):

Argument of type '{ name: string; imports: (typeof ConfigModule)[]; useFactory(config: ConfigService<Record<string, any>>): { Model: typeof HistoryBaseModel; config: any; }; inject: (typeof ConfigService)[]; }' is not assignable to parameter of type 'ObjectionModuleAsyncOptions'.
  Object literal may only specify known properties, and 'name' does not exist in type 'ObjectionModuleAsyncOptions'

@willsoto
Copy link
Owner

Does it compile outside of vscode? It could be that vscode's typings are cached

@sergiopedrerobenedi
Copy link
Author

sergiopedrerobenedi commented Jul 10, 2020

Ok, sorry! That was what was happening!
Thanks!

@sergiopedrerobenedi
Copy link
Author

sergiopedrerobenedi commented Jul 10, 2020

And @willsoto in the docs section, in the second database connection config, you wrote ObjectionCoreModule instead of this ObjectionModule

@willsoto
Copy link
Owner

Whoops! Thanks, will fix.

@cdupetit
Copy link

Hello,
In your example, the connection manage only one Model. How can I configure multiple model in one of the two connection ?
Thanks in advance.
Regards

@willsoto
Copy link
Owner

@cdupetit you would need to provide two different base models, each bound to one of the different connections

@cdupetit
Copy link

cdupetit commented May 20, 2021

How can I do that ? I have mulitple models defined like this :

export class ItemModel1 extends objection.Model {
}

export class ItemModel2 extends objection.Model {
}
@Global()
@Module(
  {
    imports: [ConfigModule.forFeature(firstDatabaseConfig),
      ObjectionModule.registerAsync({
        name: 'connection1',
        imports: [ConfigModule],
        useFactory(config: ConfigService) {
          return {
            Model: **[ItemModel1, ItemModel2]**,
            config: {
              ...config.get<knex.Config>('first-database-config'),

            },
          };
        },
        inject: [ConfigService],
      }),

@willsoto
Copy link
Owner

It's here in the example: https://github.com/willsoto/nestjs-objection#multiple-connections

export class BaseModelConnection1 extends objection.Model {}
export class BaseModelConnection2 extends objection.Model {}

@cdupetit
Copy link

Yes but I have mulitple tables (models) in the database.

@willsoto
Copy link
Owner

export class MyModel1 extends BaseModelConnection1 {}
export class MyModel2 extends BaseModelConnection2 {}

https://vincit.github.io/objection.js/recipes/multitenancy-using-multiple-databases.html#model-binding-pattern

@cdupetit
Copy link

Thanks. I will try the binding pattern.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants