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

NEW Allow database read-only replicas #11379

Open
wants to merge 1 commit into
base: 6
Choose a base branch
from

Conversation

emteknetnz
Copy link
Member

Issue #11352

* List of rules that must only use the primary database and not a replica
*/
private static array $must_use_primary_db_rules = [
'Security'
Copy link
Member Author

@emteknetnz emteknetnz Sep 16, 2024

Choose a reason for hiding this comment

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

I'm enforcing must_use_primary on anything "Security" related - i.e. any url that matches /Security, any DataObject under the Security namespace, to prevent any weird issues that could happen when a replica is out of sync with the primary

For instance a password is changed, the user logs out, but cannot log back in because the replica isn't synced up yet.

Having replicas be slightly out of sync is one of the trade-offs for using replicas, though for anything security related it introduces risk so it's disallowed

@emteknetnz emteknetnz force-pushed the pulls/5/db-replica branch 9 times, most recently from bc7692c to 2d388e9 Compare September 18, 2024 23:12
@emteknetnz emteknetnz marked this pull request as ready for review September 18, 2024 23:53
Copy link
Member

@GuySartorelli GuySartorelli left a comment

Choose a reason for hiding this comment

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

Haven't tested locally yet but here's some requested changes based on reviewing the code

cli-script.php Outdated
Comment on lines 18 to 19
// CLI scripts must only use the primary database connection and not replicas
DB::setMustUsePrimary();
Copy link
Member

Choose a reason for hiding this comment

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

We'll need to make sure this gets carried over to the new sake somehow

Copy link
Member Author

Choose a reason for hiding this comment

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

Depending on which PR gets merged first, I'd expect it to create merge conflict in the 2nd PR as the cli-script.php was deleted

Copy link
Member

Choose a reason for hiding this comment

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

Fingers crossed whoever deals with the conflict things to check what changed and doesn't just go "it was deleted so we don't need it 😅

src/Control/Director.php Outdated Show resolved Hide resolved
src/ORM/DB.php Show resolved Hide resolved
src/Control/Director.php Outdated Show resolved Hide resolved
src/ORM/DB.php Outdated Show resolved Hide resolved
tests/php/ORM/DBReplicaTest.php Outdated Show resolved Hide resolved
tests/php/ORM/DBReplicaTest.php Outdated Show resolved Hide resolved
tests/php/ORM/DBReplicaTest.php Outdated Show resolved Hide resolved
tests/php/ORM/DBReplicaTest.php Outdated Show resolved Hide resolved
tests/php/ORM/DBReplicaTest.php Outdated Show resolved Hide resolved
@emteknetnz emteknetnz force-pushed the pulls/5/db-replica branch 4 times, most recently from e57f963 to 2d41361 Compare September 25, 2024 02:58
src/Control/Director.php Outdated Show resolved Hide resolved
*/
public static function getMustUsePrimary(): bool
{
return DB::$mustUsePrimary;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return DB::$mustUsePrimary;
return DB::$mustUsePrimary || DB::$withPrimaryCount > 0;

In both of these scenarios, the primary must be used. It doesn't matter why the primary must be used, just that it must.

Copy link
Member Author

@emteknetnz emteknetnz Sep 26, 2024

Choose a reason for hiding this comment

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

I'm not sure about this since it's named as a getting.

What I'll do instead is create a new method to 'willUsePrimary()' and add in the check for replica config, i.e. I'll extract the logic from the top of DB::getDefaultConnectionName()

Copy link
Member

Choose a reason for hiding this comment

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

Ahh okay. My intention was always for this to be the "tell me if I am using the primary" method, not the "Get that property's value" method.

Probably not worth having a getter just for this property on its own, that'll just be confusing I think especially when there's also a willUsePrimary.
IMO remove this getter

Copy link
Member Author

Choose a reason for hiding this comment

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

Removed

src/ORM/DB.php Show resolved Hide resolved
src/ORM/DB.php Outdated Show resolved Hide resolved
Comment on lines +29 to +31
*
* Prior to CMS 5.4 when replica connections were introduced, the 'default' connection
* was not dynamic and instead represented what the 'primary' connection is now
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
*
* Prior to CMS 5.4 when replica connections were introduced, the 'default' connection
* was not dynamic and instead represented what the 'primary' connection is now

We don't tend to keep historical information in PHPDocs - that's probably something for the changelog.

Copy link
Member Author

@emteknetnz emteknetnz Sep 26, 2024

Choose a reason for hiding this comment

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

I want to keep this one inline because 'default' is a poor way to describe 'either primary or replica if configured' i.e. it doesn't do what it sounds like it should do

Copy link
Member Author

Choose a reason for hiding this comment

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

Have reworded a little now that I've changed the const to DB::CONN_DYNAMIC

src/ORM/DB.php Outdated Show resolved Hide resolved
tests/php/ORM/DBReplicaTest.php Outdated Show resolved Hide resolved
src/ORM/DB.php Outdated
Comment on lines 339 to 506
return DB::get_conn()->query($sql, $errorLevel);
$name = DB::getDefaultConnectionName($sql);
return DB::get_conn($name)->query($sql, $errorLevel);
Copy link
Member

Choose a reason for hiding this comment

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

No, it would go to this

    public static function query($sql, $errorLevel = E_USER_ERROR)
    {
        // ...
        updateConnectionIfNeeded($sql);
        $name = DB::getDefaultConnectionName();
        return DB::get_conn($name)->query($sql, $errorLevel);

I guess part of the problem is just naming because for backwards compatibility we have to use 'default' instead of 'dynamic'

We could move this to CMS 6 and rename it if you like. Or deprecate "default" now, and have the const set to "dynamic" - and if "default" is passed in, throw a deprecation warning and set it to "dynamic".

That would probably resolve this problem for me, since a "dynamic connection" could dynamically change based on sql whereas a "default connection" feels like it should have been determined already.

src/Core/CoreKernel.php Outdated Show resolved Hide resolved
src/Core/CoreKernel.php Outdated Show resolved Hide resolved
src/ORM/DB.php Outdated Show resolved Hide resolved
Copy link
Member

@GuySartorelli GuySartorelli left a comment

Choose a reason for hiding this comment

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

*/
public static function getMustUsePrimary(): bool
{
return DB::$mustUsePrimary;
Copy link
Member

Choose a reason for hiding this comment

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

Ahh okay. My intention was always for this to be the "tell me if I am using the primary" method, not the "Get that property's value" method.

Probably not worth having a getter just for this property on its own, that'll just be confusing I think especially when there's also a willUsePrimary.
IMO remove this getter

@emteknetnz emteknetnz changed the base branch from 5 to 6 September 27, 2024 02:37
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.

2 participants