vapor / fluent

Vapor ORM (queries, models, and relations) for NoSQL and SQL databases
https://docs.vapor.codes/4.0/fluent/overview/
MIT License
1.32k stars 172 forks source link

[suggestion] Move migration functionality to fluent-kit package #702

Closed weenzeel closed 1 year ago

weenzeel commented 3 years ago

I have an app that will be offline first ... but needs to sync data with an online server when in range of a network.

For apps that need to manage data both on the client and the server, it would be really attractive to be able to use Fluent as a way to abstract away different database implementations. And share code between client and server.

Fluent seems to be really nicely decoupled already with dependencies on fluent-kit, fluent-sqllite-driver etc.

But when I looked in to using the sqlite driver on it's own, the migration functionality tripped me up. The migrations are done via a command API in the Vapour main package.

Could the auto migrate functionality be moved in to fluent-kit? So that we could use it programmatically using only the fluent-sqlite-driver on a client device?

Thank u for making Vapor / Fluent available. It looks like a really attractive framework for the server.

0xTim commented 3 years ago

I don't think this is possible unfortunately. Auto migrate and commands rely on knowledge of Vapor (things like it's Command protocol). Fluent-Kit doesn't have any dependencies on Vapor (to allow it to be shared) so it won't be able to see the types. However, since the Migration type it's self lives in FluentKit you can get a database connection and run the migrations yourself (effectively emulating what Vapor does)

weenzeel commented 3 years ago

It makes sense that migrations can be triggered from a Vapor command interface when dealing with servers. When there is a single, centralized database controlled by the DBA/developer, making manual (or automatic on booting the server) migrations makes perfect sense.

But what I'm suggesting is that Fluent takes in to consideration a second use case, where local databases needs to be managed on client devices, separate from the central server database. As I described above there may be cases where we first need to manage data on the client and then on the server and vice versa.

What I'm suggesting is a decoupling of the orchestration of the migration api from the Command protocol. Rather; the migration functionality could be exposed via some simple to use programatic interface in fluent-kit that Vapor/Fluent command calls when servers are migrated or started. This would make it easier for 3rd party client apps to call the same programatic interface without having to replicate the migrate command functionality in Vapor/Fluent.

I understand if this is out of scope for Vapor/Fluent. But empowering clients to share know-how, code and logic between the client and the server would make the framework more attractive to me. Especially since the promise of full stack Swift development is one of the key arguments for using Vapor, compared to other server side frameworks. And since Vapor already provides other abstractions to help Clients integrate with the server I think this could be a nice feature. Especially since SQLite is supported.

But as I say ... I haven't looked at the code that much. There may be a number of things that makes the migration functionality tied to the Vapor/Fluent abstractions.

If you could give me any hints about the dependencies I could try to come up with a pull request.

0xTim commented 3 years ago

So digging through the code, everything you need is in the Migrator class in FluentKit - the only thing Fluent does it provide an event loop and a command to trigger the migrations. The actual logic to run migrations is in FluentKit

0xTim commented 1 year ago

Closing this out as I think it's solved. Feel free to reopen!

Joride commented 1 month ago

I don't think this is possible unfortunately. Auto migrate and commands rely on knowledge of Vapor (things like it's Command protocol). Fluent-Kit doesn't have any dependencies on Vapor (to allow it to be shared) so it won't be able to see the types. However, since the Migration type it's self lives in FluentKit you can get a database connection and run the migrations yourself (effectively emulating what Vapor does)

Reactivating to follow up on this one, as I have recently started to use Vapor, and I am quite enjoying using it! I have a situation where I need to connect to multiple databases, one DB for each client.

So the solution would be the one described here: set up multiple DBs, and based on some factor (header, auth etc), use the proper one.

When setting up multiple DBs, I can imagine things like app.databases.use(...) and app.migrations.add(...) become essentially obsolete, as I would be 'on my own' to manage the DBs? So a couple of questions: if the Application instance is completely unaware of any DB, would that have (negative) consequences? If not using any of the Application's provided DB-support, how would I go about emulating the Vapor way of running migrations? Or what Vapor file would be the one to look at to get an understanding of how that is done and emulate it properly?

0xTim commented 1 month ago

@Joride app.databases.use() takes a DB ID and supports multiple databases. It's the same with app.migrations.add() that has an optional DB ID to tell you where the migration should be added. Application and Request are both aware of the available DBs, when you do app.db or req.db - you can do app.db(dbID) to refer to the DB you want

Joride commented 1 month ago

Oh nice, hat's very convenient indeed! Not sure why I missed that, lack of sleep probably :) . Than's @0xTim , appreciate you clarifying that!