Login | Register
My pages Projects Community openCollabNet

Discussions > dev > Improvement to Propel::setForceMasterConnection() behaviour

propel
Discussion topic

Back to topic list

Improvement to Propel::setForceMasterConnection() behaviour

Reply

Author Shane Langley <shane dot langley at gmail dot com>
Full name Shane Langley <shane dot langley at gmail dot com>
Date 2008-09-24 15:26:33 PDT
Message Hi,

I'm using Propel in a master/slave environment and I've noticed a
possible issue with how Propel handles reads.

// i'd expect this to use master for ALL queries, not just rights
Propel::setForceMast​erConnection(true);

// gets the write connection (i.e master);
$conn = Propel::getConnection();

// I'd expect this query to hit the master since Propel has been forced
to use the master, but it hits the slave
$car = CarPeer::retrieveByPk(1);

Now I can easily get around this for this query by passing in $conn to
retreiveByPk() like so:

// this will hit the master
$car = CarPeer::retrieveByPk(1, $conn);

Which I guess is fine, but it gets a bit ugly needing to pass $conn
around to every accessor method.

Another issue is if you have a custom method which accesses a fk. If I
had this method in my Car class:

public function changeEngine(EngineType $newEngine)
{
    // this will access the foreign key for EngineType, and if it hasn't
been loading already, it'll hit the slave
    // even when forceMasterConnection is set to TRUE. Only way to get
around this is the pass in
    // $con to this method as well

    if ($this->getEngin​eType()->isChange​able())
        $this->setEngine​Type($newEngine);
}

So, my suggestion is the tweak the handling of connections for
master/slave setups.

This is the code used currently in SELECT methods:

if ($con === null) {
    $con = Propel::getConnectio​n(BidPeer::DATABASE_​NAME,
Propel::CONNECTION_READ);
}

[Option 1]

Use ternary operator in relevant methods:

if ($con === null) {
    $con = Propel::getConnectio​n(BidPeer::DATABASE_​NAME,
(Propel::getForceMas​terConnection() ? Propel::CONNECTION_WRITE :
Propel::CONNECTION_READ) );
}

[Option 2]

Add new methods which way be easier to extend in the future. In the
Propel class:

/**
 * Returns the connection to be used when writing
 *
 * @return PropelPDO
 */
public static function getWriteConnection($database)
{
    Propel::getConnectio​n($database, Propel::CONNECTION_WRITE);
}

/**
 * Returns the connection to be used when selecting from the db.
 *
 * This method will have different results based on the value of
Propel::$forceMasterConnection has been
 * set in a master/slave environment.
 *
 * @return PropelPDO
 */
public static function getReadConnection($database)
{
    if (Propel::getForceMas​terConnection()) {
        // master has been forced, use write connection
        return self::getWriteConnec​tion($database);
    }

    // master not forced, so use read connection
    Propel::getConnectio​n($database, Propel::CONNECTION_READ);
}

Then the usage in query methods is a bit simpler:

SELECT methods:

if ($con === null) {
    $con = Propel::getReadConnection();
}

INSERT/UPDATE/DELETE methods:

if ($con === null) {
    $con = Propel::getWriteConnection();
}


Thoughts?
Attachments

« Previous message in topic | 1 of 1 | Next message in topic »

Messages

Show all messages in topic

Improvement to Propel::setForceMasterConnection() behaviour Shane Langley <shane dot langley at gmail dot com> Shane Langley <shane dot langley at gmail dot com> 2008-09-24 15:26:33 PDT
Messages per page: