Skip to content

Conversation

@hacksparrow
Copy link
Contributor

@hacksparrow hacksparrow commented Sep 20, 2019

Migrates LB4 models mounted on LB4 an app.

Fixes #2825.

Checklist

👉 Read and sign the CLA (Contributor License Agreement) 👈

  • npm test passes on your machine
  • New tests added or existing tests modified to cover all changes
  • Code conforms with the style guide
  • API Documentation in code was updated
  • Documentation in /docs/site was updated
  • Affected artifact templates in packages/cli were updated
  • Affected example projects in examples/* were updated

👉 Check out how to submit a PR 👈

bajtos
bajtos previously requested changes Sep 23, 2019
Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find the proposed approach problematic because it introduces unwanted coupling between repository and booter-lb3app. LB3 applications are not a business of @loopback/repository.
The code iterating over datasources in the LB3 app belongs to packages/booter-lb3app.

@hacksparrow hacksparrow force-pushed the fix/lb3-migration branch 3 times, most recently from 5997fee to 6d8bb99 Compare September 24, 2019 14:18
@hacksparrow hacksparrow changed the title [WIP] fix: migrate LB3 models mounted on LB4 app fix: migrate LB3 models mounted on LB4 app Sep 24, 2019
@hacksparrow hacksparrow marked this pull request as ready for review September 24, 2019 14:24
@hacksparrow hacksparrow requested a review from bajtos September 24, 2019 14:25
Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The patch looks reasonable now 👍

I am little bit concerned that we are testing this feature in isolation, there is no test to verify that npm run migrate is actually going to pick up datasources contributed by the LB3 app. Did you verify this scenario manually? Is there any reasonable way how to automate such test?

const ds = dataSources[key];
processedDs.push(ds.name);
this.app
.bind(`datasources.lb3-${ds.name}`)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to discuss the binding naming convention with @raymondfeng and possibly with the wider community @strongloop/loopback-next .

Aspects to consider:

  • There should be very low probability of a naming conflict between a key generated for a LB3 datasource and a key created by LB4 API app.dataSource.
  • The key should make it obvious what's the datasource name and that this datasource is coming from a LB3 app.

I think the current proposal datasources.lb3-${ds.name} is reasonable 👍

Few other options to consider:

  • lb3-datasources.${ds.name} (e.g. lb3-datasources.db)
  • datasources.\$lb3\$${ds.name} (e.g. datasources.$lb3$db)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am good with either
datasources.lb3-${ds.name} (pro: the prefix is consistent with other datasources)
or
lb3-datasources.${ds.name} (pro: we can apply the same naming convention for other lb3 artifacts like models)

@bajtos bajtos dismissed their stale review September 24, 2019 14:49

The patch has been reworked since my review.

@hacksparrow
Copy link
Contributor Author

Did you verify this scenario manually?

Yes, in a standalone app.

Is there any reasonable way how to automate such test?

Will work on this next and propose something.

@dhmlau
Copy link
Member

dhmlau commented Sep 24, 2019

@hacksparrow, there's a decrease in the test coverage. Could you please look into it? Thanks.

@hacksparrow
Copy link
Contributor Author

@dhmlau the decrease is not in the related package (booter-lb3app). What do we do?

@raymondfeng @bajtos

@raymondfeng
Copy link
Contributor

@hacksparrow I don't see obvious cause of coverage to worry about in this case.

Copy link
Contributor

@jannyHou jannyHou left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The changes LGTM 👏

@hacksparrow
Copy link
Contributor Author

@bajtos I have been considering some ways for verifying datasources contributed by LB3 are picked up, but they all involve app.findByTag('datasource'), which is already covered by the unit test in the PR.

An approach which is more appropriate to the reported issue (Database migrations for mounted LoopBack 3 Models) would be an integration test case, which verifies the state of the models in the database with no knowledge of the datasources used. But this will require a more elaborate setup (will need an SQL database) and dependencies. Is it worth it?

In my opinion, the unit test should suffice because the implementation of migration is done by enumerating the datasources bound to the app. If we can verify that a datasource is bound to the app, we can be sure all models attached to it will be migrated if the corresponding connector supports migration.

@bajtos
Copy link
Member

bajtos commented Sep 26, 2019

An approach which is more appropriate to the reported issue (Database migrations for mounted LoopBack 3 Models) would be an integration test case, which verifies the state of the models in the database with no knowledge of the datasources used. But this will require a more elaborate setup (will need an SQL database) and dependencies. Is it worth it?

In my opinion, the unit test should suffice because the implementation of migration is done by enumerating the datasources bound to the app. If we can verify that a datasource is bound to the app, we can be sure all models attached to it will be migrated if the corresponding connector supports migration.

Fair enough. We can introduce an integration or end-to-end test later in the future, if needed. 👍

For posterity, I think it should be possible to write a test that does not require the real database, the test needs to replace the real automigrate or autoupdate method on a LB3 datasource with a sinon stub, and then verify the stub was called from app.migrateSchema.

Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost there!

@derdeka
Copy link
Contributor

derdeka commented Sep 26, 2019

Is it possible to disable this feature by options somehow (migration of lb3 models)? What happens if lb3 models and lb4 models have the same names or use the same database tables? Not all users might want to mix up lb3 and lb4 applications in that way.

@hacksparrow
Copy link
Contributor Author

@derdeka mounting LB3 app on a LB4 requires multiple steps to be followed. If one does not want their LB3 models to be mounted, those models should be removed from the LB3 app while the LB3 app being set up to be mounted in the LB4 app.

@hacksparrow
Copy link
Contributor Author

@bajtos thanks for the nice suggestions, I have made the changes accordingly.


import {BootBindings, Booter} from '@loopback/boot';
import {CoreBindings, inject} from '@loopback/core';
import {DataSource} from '@loopback/repository';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I commented before, @loopback/repository is not in regular/peer dependencies of booter-lb3app, therefore it may not be available at runtime, when this booter is installed in a LB project.

Also the DataSource type is not the right one to use, it described LB4 objects but your code is using LB3 instances! The correct type is juggler.DataSource.

Please remove this import and find a different solution how to describe the shape (interface) of LB3 datasource objects.

@bajtos
Copy link
Member

bajtos commented Sep 27, 2019

@derdeka

Is it possible to disable this feature by options somehow (migration of lb3 models)? What happens if lb3 models and lb4 models have the same names or use the same database tables? Not all users might want to mix up lb3 and lb4 applications in that way.

Thank you for raising this concern!

I see only one scenario where import of LB3 & LB4 models can create conflict, and that's when there is a model with the same name attached to a datasource configured to use the same database, and thus share the same table. Additionally, the LB3 and LB4 models must defined differently.

It makes me wonder, what is the intent of application developer in such case. If the model definition is different between LB3 and LB4 applications, isn't this going to create inconsistencies in data? E.g. LB3 endpoints writing table rows in different format than expected by the LB4 model.

Setting that aside, I think it makes sense to give developers more control over which models are migrated. I don't think the decision should be based on LB3 or LB4, I'd prefer a more generic solution allowing developers to specify which datasources to migrate or even which models to migrate.

It turns out this is already supported via SchemaMigrationOptions and its models field. My recommendation is to overwrite migrateSchema in your application class and supply the list of models to migrate.

class MyApplication extends BootMixin(
  RepositoryMixin(RestApplication)
) {
  // ...

  migrateSchema(options: SchemaMigrationOptions = {}): Promise<void> {
    if (!options.models) {
      options = {...options, models: [/* put your model names here */]};
    }
    return super.migrateSchema(options);
  }
}

I think this is not ideal, let's discuss how to improve it here: #3819

@hacksparrow hacksparrow force-pushed the fix/lb3-migration branch 2 times, most recently from f812a00 to e811b0e Compare September 27, 2019 07:46
Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👏

@bajtos
Copy link
Member

bajtos commented Sep 27, 2019

Please consider adding a short paragraph to Mounting the LoopBack 3 Application in a LoopBack 4 Project and mention that npm run migrate will migrate all models from the LB3 application too.

Copy link
Contributor

@nabdelgadir nabdelgadir left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you also update the lb3 application example and remove these lines?

@hacksparrow hacksparrow force-pushed the fix/lb3-migration branch 2 times, most recently from 110fae0 to 485d739 Compare September 27, 2019 14:31
Migrates LB4 models mounted on LB4 an app.
@hacksparrow hacksparrow merged commit 7d36f6d into master Sep 27, 2019
@hacksparrow hacksparrow deleted the fix/lb3-migration branch September 27, 2019 15:15
@emonddr
Copy link
Contributor

emonddr commented Sep 27, 2019

Great stuff @hacksparrow :)

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

Successfully merging this pull request may close these issues.

Database migrations for mounted LoopBack 3 Models

10 participants