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

Convert from Laminas\Db to Doctrine #2233

Draft
wants to merge 350 commits into
base: dev
Choose a base branch
from

Conversation

demiankatz
Copy link
Member

@demiankatz demiankatz commented Dec 7, 2021

This is work in progress on replacing VuFind's database abstraction layer.

TODO

@demiankatz demiankatz changed the base branch from dev to dev-9.0 December 7, 2021 20:02
@demiankatz
Copy link
Member Author

I spent some more time on proof-of-concept work today. I decided to try revising some of the code in the admin module's tag controller, since that does complex queries and seemed like a potentially interesting starting point. So far, results are promising -- not only is the DQL query language more readable than the Laminas\Db object-oriented query builder, but I also managed to find and fix a bug along the way.

Some notes on today's progress:

1.) We need to have a place to put database-related logic. In the previous code, this was in the row and table classes. In the new code, I propose a set of VuFind\Db\Service classes designed to deal with various types of entities. I've started work on a TagService here, and I've set up the necessary plugin mechanism for interacting with services. This may need more granularity, but we can decide that as we gain more experience working with Doctrine.

2.) For extensibility purposes, we also need a way to abstract entity classes so that they can be overridden. I have created a VuFind\Db\Entity\PluginManager for this purpose, and I defined a marker interface for entities so that the plugin manager can validate what it is creating. Note that overriding entities appears to have one major limitation: annotations are not inherited from parent classes, so any local custom entity needs to fully duplicate its parent's properties and annotations. Perhaps there is a way around this, but given how infrequently I expect people to need to extend/override entities, it may also be a limitation that we can live with.

There is still a massive amount of work that needs to be done here, but I'm encouraged by this start. I will continue to chip away as time permits, and I welcome input or offers of collaboration. Eventually, it may be best to "divide and conquer" on all the conversion work, since there is so much of it.

@demiankatz
Copy link
Member Author

Just a quick update on progress, because I believe this branch is currently in a somewhat broken state:

In order to incorporate Doctrine queries with the Laminas Paginator, I had to add the doctrine/doctrine-orm-module dependency to get an appropriate paginator adapter. In order to install this, I had to upgrade several other dependencies to newer versions, and the upgrade to the latest laminas-cache seems to be causing problems. I worked around this while developing by hacking out the cache logic that was failing, but obviously that needs a proper solution, which I will address in a separate Laminas upgrade PR.

The doctrine/doctrine-orm-module dependency also raises the question of whether we actually need roave/psr-container-doctrine, which may be less desirable if the official Doctrine piece meets our needs. I'll investigate that further when time permits.

Anyway, I've created TODO checkboxes to capture all these balls that are in the air, and I apologize for leaving this in a somewhat broken state, but I didn't want to lose my work in progress, and I'm nearly out of time for today. I'll pick this up again as soon as practical.

@aleksip
Copy link
Contributor

aleksip commented Oct 27, 2022

Hi @demiankatz, this change is very exciting because our Admin Interface has been using doctrine/doctrine-orm-module for a while and it also reads the VuFind database.

I wonder whether it would make sense to develop the new Doctrine based VuFind database layer as a separate module/package, in a similar way that has been discussed in #2272 and #2283 (which I hope to continue working on as soon as time allows)?

In any case it would be great to have this developed in a way that would allow for code reuse, even if only by copying the classes over!

@demiankatz
Copy link
Member Author

Thanks, @aleksip, I'm glad that you're happy with this approach. I'm open to organizing the code any way that is helpful; I think it's just a question of what works best. Perhaps one approach could be to create a VuFindDb module to contain the Entity classes, ConnectionFactory, etc. I'm not sure if the actual Service classes would fit there as well, or if they'd be better off in the main VuFind module due to their potential entanglement with other dependencies. I think I'd have to get deeper into the project to have a stronger opinion about that, but I'm open to input!

In any case, right now, my priority is finishing up all the outstanding work on VuFind 9, so this is more or less on hold, but I'm hoping this will be one of the priority changes for VuFind 10, and I expect I'll be spending a lot of time on it in 2023. I'm definitely happy to discuss/plan in the meantime so we have a clear path forward when it comes time to execute the work. I'm also very open to brainstorming strategies for collaboration if you or anyone on your team might be able to help with the updates, as this is a very big project. I'm hoping that, in addition to updating everything, we can make strides toward introducing better test coverage for core code, since if we do this right, it should make things easier to test than the old database library did.

@aleksip
Copy link
Contributor

aleksip commented Oct 27, 2022

@demiankatz Sounds good! I am currently experimenting with potential vufind-db, vufind-view and vufind-config packages in our Admin Interface, will report on how it goes. 🙂

@demiankatz
Copy link
Member Author

Thanks, @aleksip, that's great! Certainly if you have classes from your admin code that it would make sense to move over here for use in the core, that might save us some time and trouble. I'm not sure if the existing auto-generated Entity classes are actually the best they could be, as most of them have not yet been tested.

Copy link
Member Author

@demiankatz demiankatz left a comment

Choose a reason for hiding this comment

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

@aleksip, thanks for the progress on configuration here -- just leaving a couple of comments/questions related to the latest changes.

module/VuFind/config/module.config.php Show resolved Hide resolved
@@ -338,6 +338,7 @@
'service_manager' => [
'allow_override' => true,
'factories' => [
'Doctrine\ORM\Mapping\Driver\AnnotationDriver' => 'VuFind\Db\AnnotationDriverFactory',
Copy link
Member Author

Choose a reason for hiding this comment

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

@aleksip, I see that you deleted this factory, but the configuration is still here. We should clean something up.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, forgot to remove that line. Should I push the change to your branch or what would be the best way to work on this together?

Copy link
Member Author

Choose a reason for hiding this comment

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

Please feel free to push directly here, as long as the code still works. I'm not going to be working on this much until next year, so I welcome any progress you can make in the meantime, and I don't anticipate that we'll "step on each other," so to speak.

Copy link
Member Author

Choose a reason for hiding this comment

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

Also, if at any point it would be helpful to get a second opinion or anything, or if you would like me to run any tests, just let me know and I'll be happy to help!

Copy link
Contributor

Choose a reason for hiding this comment

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

@demiankatz I meant to push the changes to my repository and then point you there. Not sure how multi-user PRs should work... Should I push future suggested changes to my clone so you can then decide whether to merge to your branch from there?

Copy link
Member Author

Choose a reason for hiding this comment

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

@aleksip, it is possible to make a pull request against a pull request -- you can just target a PR against this branch. That might be the easiest workflow going forward, especially when multi-user collaboration picks up... but since things are quiet right now, feel free to work directly in this branch, at least until you get things into a correct/stable state again. (I think it's easier to just move forward and fix things than to roll back changes and make a separate PR, at least under the present circumstances).

Copy link
Contributor

@aleksip aleksip Nov 2, 2022

Choose a reason for hiding this comment

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

@demiankatz Seems like I can create a PR for the branch in your repository! Should I do that? Edit: missed your above reply.

Copy link
Member Author

Choose a reason for hiding this comment

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

If you want to try it as a proof-of-concept, feel free... but otherwise, as I said, you can just go ahead and push. :-)

@aleksip
Copy link
Contributor

aleksip commented Nov 2, 2022

@demiankatz I have accidentally pushed my changes to your branch, sorry about that! I have been refactoring our Admin Interface database implementation to be based on this PR, and those were the changes I needed to make. They were needed to support two entity managers with connections to different databases.

I don't claim to fully understand how Doctrine's configuration works, but the orm_default naming convention seems a bit problematic in integrations. It would seem better to define an application specific name, and if necessary create an orm_default alias for that.

I also wondered about the need for AnnotationDriverFactory, as it seems that the same result can be achieved with just configuration.

@demiankatz
Copy link
Member Author

@aleksip, I am certainly not an expert on Doctrine's configuration either, and I've been learning as I go... so if the annotation driver can be replaced by pure configuration, I'm entirely in favor of that, and if a different naming convention would be more robust, I also have no objection to changes.

@demiankatz demiankatz added the architecture pull requests that involve significant refactoring / architectural changes label Nov 7, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
architecture pull requests that involve significant refactoring / architectural changes improvement
Projects
None yet
5 participants