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

Implement new experimental SQLite integration module #547

Merged
merged 129 commits into from
Dec 12, 2022
Merged

Conversation

aristath
Copy link
Member

@aristath aristath commented Sep 29, 2022

Summary

This PR introduces a module to allow testing the SQLite implementation - as discussed in the performance team's Slack meeting this week.
For background, you can read the SQLite proposal on make.w.org

This is a continuous work in progress, but it is working well enough to be included as an experimental module. The issues are not so much with the SQLite implementation itself, as much as with the module's activation/deactivation and the overall User Experience during that process.

The code for the SQLite implementation was copied from https://github.com/aaemnnosttv/wp-sqlite-db/blob/master/src/db.php, which is a fork of the original work on the sqlite-integration plugin. It was then refactored a bit, coding-standards were applied, and an integration with the plugin was built.

Relevant technical choices

Checklist

  • PR has either [Focus] or Infrastructure label.
  • PR has a [Type] label.
  • PR has a milestone or the no milestone label.

@aristath aristath added no milestone PRs that do not have a defined milestone for release [Type] Module Proposal labels Sep 30, 2022
@aristath aristath marked this pull request as ready for review September 30, 2022 10:55
@aristath aristath changed the title WIP - SQLite integration module SQLite integration module Oct 5, 2022
@saas786
Copy link

saas786 commented Oct 10, 2022

It would be awesome if this implementation also encourages WordPress database to be abstracted out,
so we can could call secondary database at runtime.

It would help with situations like these:

Ref: xwp/stream#1360

Not sure if this comment is clear enough, but hoping it make sense and such level of abstraction can be implemented in core.

@aristath aristath force-pushed the module/sqlite branch 2 times, most recently from e6e9615 to edda8bd Compare October 18, 2022 06:33
Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

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

@aristath Thank you for this (massive) PR! I did a first pass and left some comments. Most of them are either about the activation/deactivation routine or following some Performance Lab conventions that are currently off here.

I'm certainly open to not addressing everything in this one PR, we could also see if we could break things down if you prefer that. The only thing that we would need to define clearly is what would be our MVP criteria for when this could launch (even as experimental module) in the Performance Lab plugin. But even for that MVP functionality, there is room for multiple PRs, we could for example create a feature branch for the module rather than working directly against trunk. LMKWYT.

modules/sqlite/integration/load.php Outdated Show resolved Hide resolved
admin/load.php Outdated Show resolved Hide resolved
modules/sqlite/integration/load.php Outdated Show resolved Hide resolved
modules/sqlite/integration/load.php Outdated Show resolved Hide resolved
modules/sqlite/integration/load.php Outdated Show resolved Hide resolved
modules/sqlite/integration/wp-includes/sqlite/db.php Outdated Show resolved Hide resolved
modules/sqlite/integration/wp-includes/sqlite/db.php Outdated Show resolved Hide resolved
modules/sqlite/integration/wp-includes/sqlite/db.php Outdated Show resolved Hide resolved
),
file_get_contents( __DIR__ . '/db.copy' )
);
$wp_filesystem->put_contents( $destination, $file_contents );
Copy link
Member

Choose a reason for hiding this comment

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

As far as I understand, this is the only logic that runs when activating the module, correct? And then it would mean the user would land on a blank WP install?

Based on previous conversations we had on Slack, I would suggest that we also set up the database right away, so that it is at least a blank WordPress install with the Performance Lab plugin and the same modules enabled. This way it would make for a much better and less confusing user experience.

Would it be possible to call wp_install() here for the new SQLite database (at least if that database is empty)? If it's not possible within the initial request where a regular MySQL / MariaDB database is still used, we could also redirect to a custom endpoint that does this in a new request and then redirects the user back to the Performance Lab settings screen.

While this is initially going to be an experimental module and we're not going to get into the weeds of e.g. migrating a full DB, I still think a smoother user experience for this would be crucial, and the above suggestion may be feasible without too much effort.

Copy link
Member Author

Choose a reason for hiding this comment

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

As far as I understand, this is the only logic that runs when activating the module, correct? And then it would mean the user would land on a blank WP install?

Correct.

Based on previous conversations we had on Slack, I would suggest that we also set up the database right away, so that it is at least a blank WordPress install with the Performance Lab plugin and the same modules enabled. This way it would make for a much better and less confusing user experience.

If an SQLite database doesn't exist (ie, this is the 1st time the user activates the module), they will land on the WP-install screen so they can enter their admin username/password, sitename etc.
The copied db.php file then takes care of activating the performance-lab plugin, and activate the default modules + SQLite.

Would it be possible to call wp_install() here for the new SQLite database (at least if that database is empty)? If it's not possible within the initial request where a regular MySQL / MariaDB database is still used, we could also redirect to a custom endpoint that does this in a new request and then redirects the user back to the Performance Lab settings screen.

I just pushed a tweak that does that 👍
However, I was unable to achieve it in PHP so it was accomplished using a window.location.reload(true); call. That in turn, triggers WP to redirect to the login screen if a database exists - and then after login the user lands on the perflab settings - OR, if a database doesn't exist, WP redirects the user to the install screen.

While this is initially going to be an experimental module and we're not going to get into the weeds of e.g. migrating a full DB, I still think a smoother user experience for this would be crucial, and the above suggestion may be feasible without too much effort.

💯

Copy link
Member

Choose a reason for hiding this comment

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

@aristath

If an SQLite database doesn't exist (ie, this is the 1st time the user activates the module), they will land on the WP-install screen so they can enter their admin username/password, sitename etc.

Why do we need to require the user to do that though? They already provided that information when they set up the original DB, so I think it would be a much smoother experience if we didn't prompt them to the WP install screen, but rather called wp_install() for the new DB right away, based on the values that are in the current DB.

Related is my comment #547 (comment), we could right after wp_install() also run logic to mark the Performance Lab and the current modules as active in the new SQLite DB.

Maybe I'm missing something here that makes this infeasible though?

Copy link
Member Author

Choose a reason for hiding this comment

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

In the week that has passed since this comment, I tried multiple iterations and approaches to this. Unfortunately, I was unable to make it work... I agree that it would be better UX if the database was auto-populated.
However, no matter what I tried, there are issues because it's a different database, there are timing issues, we actually need to have 2 different database connections open, and overall it's a nightmare 😰 If I'm not getting an install screen, I'm getting database errors. Switching databases on the fly is no easy task 😞

Since the "copying" functionality will not be part of Core if and when this gets merged, I don't think that getting an install screen would actually be a blocker to get this in the plugin 🤔
If anything, it will allow us to ensure that the actual WP installation runs smoothly when a user wants to use SQLite on their site.

@aristath
Copy link
Member Author

Thank you for all the comments @felixarntz! I addressed all feedback and pushed lots of tweaks as per your comments 👍

modules/database/sqlite/load.php Outdated Show resolved Hide resolved
modules/database/sqlite/load.php Outdated Show resolved Hide resolved
modules/database/sqlite/load.php Outdated Show resolved Hide resolved
activate_plugin( '{PERFLAB_PLUGIN}' );
}
}
);
Copy link
Member

Choose a reason for hiding this comment

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

@aristath

It's not so much about deactivating the plugin... The problem is that when switching databases, the plugin is not active (since the list of active plugins is a db option).

Makes sense. However based on our conversation in #547 (comment), I would think that we can find a way to address this problem at its root: If we can install the SQLite DB prior to switching, we could also make sure that

  • the Performance Lab plugin is immediately active in the SQLite DB as well
  • the same modules that are configured in the old DB are active in the SQLite DB

I think the PERFLAB_VERSION constant check at least makes it a bit better, but I'd prefer if we could do something like the above.

Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

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

@aristath Thanks for all the updates. I left a bit of follow-up feedback.

@aristath
Copy link
Member Author

aristath commented Nov 1, 2022

Pushed another round of fixes & refactors 👍

@aristath aristath force-pushed the module/sqlite branch 2 times, most recently from 83cae70 to e4fce10 Compare November 8, 2022 06:18
@aristath aristath requested a review from OllieJones as a code owner November 8, 2022 06:18
@OllieJones
Copy link
Contributor

OllieJones commented Nov 8, 2022

Here's a small thing. When the php interpreter doesn't have sqlite3 installed (as mine didn't) the settings page said

sqlite3 is already part of your WordPress version and therefore cannot be loaded as part of the plugin.

That's not the right diagnosis, obviously, but it happens on every can_load returning false.

So, users should not forget to do these things (ubuntu) to make sure they have sqlite3.

`sudo apt install sqlite3

sudo apt install php-sqlite3

sudo apachectl restart`

More reviewing to come...

@aristath
Copy link
Member Author

aristath commented Nov 9, 2022

Here's a small thing. When the php interpreter doesn't have sqlite3 installed (as mine didn't) the settings page said
sqlite3 is already part of your WordPress version and therefore cannot be loaded as part of the plugin.
That's not the right diagnosis, obviously, but it happens on every can_load returning false.

Good point! I pushed a commit which will allow us to set the message to be displayed when the module can't be loaded, and added the right messages in this module 👍

@aristath
Copy link
Member Author

aristath commented Dec 12, 2022

your recent commit eb77632 introduces a fatal error that needs to be addressed.

🤦 During my tests it happened that I already had an sqlite db on wp-content/database - so on activation of the module it was skipping the database creation - which is why I missed this.
Thank you for catching that, and my apologies for missing it in the first place 🙏

Applied your fixes and advice, everything is working correctly again 👍

Copy link
Member

@felixarntz felixarntz left a comment

Choose a reason for hiding this comment

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

Thanks @aristath, all good now! 🎉

I left one minor comment below; I can make that change really quickly, I think it's cleaner like that.

);
}

$GLOBALS['wpdb'] = new Perflab_SQLite_DB();
Copy link
Member

Choose a reason for hiding this comment

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

@aristath Can we bring this back into the db.php file? I think this one is a bit confusing to have in a file called *-functions.php. Also, having this in the db.php file is not problematic as it will not execute based on the early return. This is only critical for functions as they would still be loaded into the global scope.

@felixarntz felixarntz changed the title SQLite integration module Implement new experimental SQLite integration module Dec 12, 2022
@felixarntz felixarntz merged commit 1697790 into trunk Dec 12, 2022
@felixarntz felixarntz deleted the module/sqlite branch December 12, 2022 17:44
@felixarntz
Copy link
Member

🎉🎉🎉

@MarekTP
Copy link

MarekTP commented Feb 3, 2023

Nice work, usefull for many "like static", thx. Some notes:

  • Vacuum called by wp-cron would be good.
  • Data synchronisation part, between MariaDB/MySQL and SQLite, is on roadmap or no?
  • [alphabetical ordering (collation) does not work correctly in languages with ascended letters [like á, č, ř], but it's property of SQLite minimalism]

@leo852
Copy link

leo852 commented May 24, 2024

Is there any plans to add support for native cloudflare D1 support?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Type] Feature A new feature within an existing module
Projects
None yet
Development

Successfully merging this pull request may close these issues.