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

2.6 add 'atomic' option to "save()" API #3516

Closed
wants to merge 18 commits into from

Conversation

Haititi
Copy link
Contributor

@Haititi Haititi commented May 17, 2014

add a transaction context to 'save()' API in order to rollback possible modifications done
in some 'Model.beforeSave' listener callback.
this will allow cakephp 2.x to behave like 3.0 .

this commit resolves issue #3511

add a transaction context to 'save()' API in order to rollback possible modifications done
in some 'Model.beforeSave' listener callback.
this will allow cakephp 2.x to behave like 3.0 .
@markstory markstory added this to the 2.6.0 milestone May 17, 2014
@markstory
Copy link
Member

This needs some testcases before it can be merged.

@ndm2
Copy link
Contributor

ndm2 commented May 17, 2014

Wouldn't the operations between begin() and commit() need to be put in a try/catch block with a rollback() in the catch, to make sure things are being rolled back even when an exception occurs half way through?

@jippi
Copy link
Contributor

jippi commented May 18, 2014

If a transaction is started and an uncaught exception happens, then everything would default to rollback() in MySQL - not calling commit() is the same as calling rollback()

@htstudios
Copy link
Contributor

What about other SQL RDBMS?

@ndm2
Copy link
Contributor

ndm2 commented May 18, 2014

Weird, my comment got lost, it appeared twice and I deleted one of them, now they are both gone. So again, @jippi thanks for the reminder. @jhli PDO has an auto-rollback mechanism implemented that kicks in in such situations, I would think that this is independent of the DBMS functionality. I'm not sure though if it's the best idea to rely on this.

@markstory
Copy link
Member

I wouldn't rely on the automatic rollback personally. It will make testing gross and could cause unwanted data to be commited when there are subsequent save operations.

@Haititi
Copy link
Contributor Author

Haititi commented May 19, 2014

I tried to add some tests but I'm not really used to that (I should really spend some time on that ...).
I don't even know how to launch these tests so I couldn't test my modification.
Please tell me if I'm doing things wrong, I will try to correct them.

* test callback used in testSaveTransaction method
*/
public function testSaveTransactionCallback($event) {
$TestModel = new Article();
Copy link
Member

Choose a reason for hiding this comment

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

You might not want to start this method name with test. Phpunit will try to execute all methods starting with test as test cases.

Haititi added 11 commits May 19, 2014 17:20
Validation occurs before the event is sent.
As the validation failed, event was not sent. So test was not relevant.
solution :
- use the global Event Manager.
- try to save a correct 'Post' data.
- the first time the callback is called, try to save a correct 'Article' data.
- the second time the callback is called, stop the event to rollback everything.
update (again) the test due to my stupidity.
- the second time the callback is called, the 'Article' data are still not saved, so there will be no data to rollback.
new test which will hopefully work :
- use the 'Post' specific Event Manager to attach the callback.
- when callback is called, try to save 'Article' data.
- assert Article->save() succeeded.
- stop event and return false to force rollback in Post->save()
testSaveTransactionNoRollback was not relevant, as validation occurs out of transaction scope.
solution :
- use the callback 'callbackForTestSaveTransaction' as in 'testSaveTransaction' as the event dispatching is done in transaction scope.
Rename previous save() API to protected _doSave() method.
create new save() method for transaction handling.
@Haititi
Copy link
Contributor Author

Haititi commented May 20, 2014

sorry for the multiple commits, but i don't know how to use git for the moment, so i'm using github to edit and commit.
moreover, I don't know how to launch the phpunit test, so i commit in order to have Travis CI launch the tests.

btw, I don't know why travis is failing with my test :
https://travis-ci.org/cakephp/cakephp/jobs/25598232
can someone look at it ?

@markstory
Copy link
Member

The docs have a section on how to run the tests. That should help with not having to push to travis on each change.

Don't worry about the additional commits, I can squash them before merging.

set a returnValue 'true' to DboSource stubbed method 'begin'
'body' => 'Fifth Article Body',
'published' => 'Y'
));
$result = $TestModel->create() && $TestModel->save($data, array('atomic' => true));
Copy link
Member

Choose a reason for hiding this comment

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

Personally, I would not test create() and just move it outside of this one row up.

'published' => 'Y'
));
$result = $TestModel->create() && $TestModel->save($data, array('atomic' => true));
$this->assertFalse(empty($result));
Copy link
Member

Choose a reason for hiding this comment

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

I would usually check on this "positively" - $this->assertTrue((bool)$result) for example.
as you expect a non empty value here. Using the opposite is a little bit counter intuitive.
But I guess this is this way for a lot of other tests as well.. So never mind.

@Haititi
Copy link
Contributor Author

Haititi commented May 21, 2014

After hours of fight to do my first phpunit run, I succeeded in fixing my errors !
Should be ok now. Tell me if something is wrong.

@markstory
Copy link
Member

There are still a few tests failing with sqlite and postgres.

@Haititi
Copy link
Contributor Author

Haititi commented May 28, 2014

apparently, the error was here before my PR, but it was not detected during the test :
https://github.com/Haititi/cakephp/blob/2.6-save-transaction/lib/Cake/Test/Case/Model/ModelWriteTest.php#L2077
Here, the 'save()' call is wrongly returning false while the database has correctly been updated.

the error comes from this line :
https://github.com/Haititi/cakephp/blob/2.6-save-transaction/lib/Cake/Model/Model.php#L1895

In ModeWriteTest.php , the data array to save does not contain 'Portfolio' key, so '$count' is equal to 0 in Model.php.

As this is another bug, should I fix it here or should I create a new bug ?

@markstory
Copy link
Member

Might as well fix it here.

@Haititi
Copy link
Contributor Author

Haititi commented May 28, 2014

sorry, too late :(
just created #3590 for this bug as i thought it should be better for review, shouldn't it ?

@Haititi Haititi closed this May 29, 2014
@Haititi Haititi deleted the 2.6-save-transaction branch May 29, 2014 15:37
@Haititi
Copy link
Contributor Author

Haititi commented May 29, 2014

oups... sorry, not used to git .... I had some problem with the 3 'cake.bat' files related to this fix :
f287bc7

I could not work with my branch anymore.
I merged all my work in a new branch '2.6-save-atomic' and deleted the previous...
How can I reopen this PR and change the source branch ?

@markstory
Copy link
Member

You can use git checkout -f 2.6-save-atomic to ignore the errors related to the .bat files.

@Haititi
Copy link
Contributor Author

Haititi commented May 30, 2014

this PR was closed when i deleted my previous branch. how can I reopen this PR?
moreover, this PR is still using the old branch. how can I update this PR to use the new branch ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants