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

Magento resource model can not rollback transactions if error happend #34066

Open
1 of 5 tasks
RomanKrut opened this issue Sep 13, 2021 · 12 comments
Open
1 of 5 tasks

Magento resource model can not rollback transactions if error happend #34066

RomanKrut opened this issue Sep 13, 2021 · 12 comments
Labels
Area: Framework Component: Exception Issue: Confirmed Gate 3 Passed. Manual verification of the issue completed. Issue is confirmed Priority: P3 May be fixed according to the position in the backlog. Progress: ready for dev Reproduced on 2.4.x The issue has been reproduced on latest 2.4-develop branch Triage: Dev.Experience Issue related to Developer Experience and needs help with Triage to Confirm or Reject it

Comments

@RomanKrut
Copy link

RomanKrut commented Sep 13, 2021

We are using magento 2.3 instance on production and we have faced issue with transactions while saving some model to database. But when error happens we can`t log that to database because of transaction level.

Examples (*)

Lets look at https://github.com/magento/magento2/blob/2.4-develop/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php save function
At line 402 we have beginTransaction method. It sets transaction level from 0 to 1 level.
If on the next code some Error happend ( any of this https://www.php.net/manual/en/class.typeerror.php)
It is important that we are faced not an Exception, we are faced an Error object
And catch at line 432 - catchs only Exceptions
It means that transactions will never be rollbacked and the next pieces of code will save nothing to database because of that if we will use same connection instance.

Steps to reproduce (*)

  1. Write declare(strict_types=1) at the beginning of file https://github.com/magento/magento2/blob/2.4-develop/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php - this step is only for reproduce
  2. After $this->beginTransaction(); in save method write preg_match('/\d{10}/', 123); - this step is only for reproduce
  3. Save some entity programmatically or any other way.
  4. Debug this code and see that when preg_match will be executed, we will not catch that error and we will not rollback transaction here https://i.imgur.com/36hC27c.png

Proposed solution

I propose replace catch (\Exception $e) with catch (\Throwable $e).

Please provide Severity assessment for the Issue as Reporter. This information will help during Confirmation and Issue triage processes.

  • Severity: S0 - Affects critical data or functionality and leaves users with no workaround.
  • Severity: S1 - Affects critical data or functionality and forces users to employ a workaround.
  • Severity: S2 - Affects non-critical data or functionality and forces users to employ a workaround.
  • Severity: S3 - Affects non-critical data or functionality and does not force users to employ a workaround.
  • Severity: S4 - Affects aesthetics, professional look and feel, “quality” or “usability”.
@RomanKrut RomanKrut added the Triage: Dev.Experience Issue related to Developer Experience and needs help with Triage to Confirm or Reject it label Sep 13, 2021
@m2-assistant
Copy link

m2-assistant bot commented Sep 13, 2021

Hi @krutkoroma79911. Thank you for your report.
To help us process this issue please make sure that you provided the following information:

  • Summary of the issue
  • Information on your environment
  • Steps to reproduce
  • Expected and actual results

Please make sure that the issue is reproducible on the vanilla Magento instance following Steps to reproduce. To deploy vanilla Magento instance on our environment, please, add a comment to the issue:

@magento give me 2.4-develop instance - upcoming 2.4.x release

For more details, please, review the Magento Contributor Assistant documentation.

Please, add a comment to assign the issue: @magento I am working on this


⚠️ According to the Magento Contribution requirements, all issues must go through the Community Contributions Triage process. Community Contributions Triage is a public meeting.

🕙 You can find the schedule on the Magento Community Calendar page.

📞 The triage of issues happens in the queue order. If you want to speed up the delivery of your contribution, please join the Community Contributions Triage session to discuss the appropriate ticket.

🎥 You can find the recording of the previous Community Contributions Triage on the Magento Youtube Channel

✏️ Feel free to post questions/proposals/feedback related to the Community Contributions Triage process to the corresponding Slack Channel

@ameysar
Copy link
Contributor

ameysar commented Sep 14, 2021

Hi @krutkoroma79911. I agree with you. As far as M2 moved to PHP 7+ it would be very good to replace all catch(\Exception){} with catch(\Throwable){}, as far as from PHP 7 \Throwable become the basic interface for catching exceptions/errors.

@engcom-Lima engcom-Lima self-assigned this Sep 14, 2021
@m2-assistant
Copy link

m2-assistant bot commented Sep 14, 2021

Hi @engcom-Lima. Thank you for working on this issue.
In order to make sure that issue has enough information and ready for development, please read and check the following instruction: 👇

  • 1. Verify that issue has all the required information. (Preconditions, Steps to reproduce, Expected result, Actual result).

    DetailsIf the issue has a valid description, the label Issue: Format is valid will be added to the issue automatically. Please, edit issue description if needed, until label Issue: Format is valid appears.

  • 2. Verify that issue has a meaningful description and provides enough information to reproduce the issue. If the report is valid, add Issue: Clear Description label to the issue by yourself.

  • 3. Add Component: XXXXX label(s) to the ticket, indicating the components it may be related to.

  • 4. Verify that the issue is reproducible on 2.4-develop branch

    Details- Add the comment @magento give me 2.4-develop instance to deploy test instance on Magento infrastructure.
    - If the issue is reproducible on 2.4-develop branch, please, add the label Reproduced on 2.4.x.
    - If the issue is not reproducible, add your comment that issue is not reproducible and close the issue and stop verification process here!

  • 5. Add label Issue: Confirmed once verification is complete.

  • 6. Make sure that automatic system confirms that report has been added to the backlog.

@engcom-Lima
Copy link
Contributor

Hi @krutkoroma79911,

Can you please elaborate on the errors that you are getting while dealing with db transactions ? It would be helpful for further analysis if we can replicate the same errors at our end.

Thanks

@RomanKrut
Copy link
Author

RomanKrut commented Sep 14, 2021

Hi @engcom-Lima . It happened with our customization of order address model, not with magento core functionality.
We have an observer on beforeSave event wich validates data of shipping address.
All files of validators starts with declare(strict_types=1); https://i.imgur.com/JLClVFI.png
In one of validators we have validate function with code
public function validate($innNumber) { return is_numeric($innNumber) && preg_match('/\d{10}/', $innNumber); }
So if we give to this function not string value, for example 1234567890, we will have Error on preg_match execution
The argument type being passed to a function does not match its corresponding declared parameter type.
(P.S. we know it was our issue not magento issue with implementation of this function)
But magento resource model should be able to catch that error and rollback transactions
All what you need to reproduce this issue locally in fastest way is:

  1. Write declare(strict_types=1) at the beginning of file https://github.com/magento/magento2/blob/2.4-develop/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php - this step is only for reproduce
  2. After $this->beginTransaction(); in save method write preg_match('/\d{10}/', 123); - this step is only for reproduce
  3. Save some entity programmatically or any other way.
  4. Debug this code and see that when preg_match will be executed, we will not catch that error and we will not rollback transaction here https://i.imgur.com/36hC27c.png
    This is just an simple example of the problem. It can be much worst for somebuddy.
    This resource model should catch Throwable instead of Exception and i hope that it is obvious for any magento developer

@ameysar
Copy link
Contributor

ameysar commented Sep 14, 2021

https://github.com/magento/magento2/blob/2.4-develop/lib/internal/Magento/Framework/Model/ResourceModel/Db/AbstractDb.php

declare(strict_types=1);
....

public function save(\Magento\Framework\Model\AbstractModel $object)
    {
        if ($object->isDeleted()) {
            return $this->delete($object);
        }

        $this->beginTransaction();

        try {
            preg_match('/\d{10}/', 123);
            if (!$this->isModified($object)) {
                $this->processNotModifiedSave($object);
                $this->commit();
                $object->setHasDataChanges(false);
                return $this;
            }
            $object->validateBeforeSave();
            $object->beforeSave();
            if ($object->isSaveAllowed()) {
                $this->_serializeFields($object);
                $this->_beforeSave($object);
                $this->_checkUnique($object);
                $this->objectRelationProcessor->validateDataIntegrity($this->getMainTable(), $object->getData());
                if ($this->isObjectNotNew($object)) {
                    $this->updateObject($object);
                } else {
                    $this->saveNewObject($object);
                }
                $this->unserializeFields($object);
                $this->processAfterSaves($object);
            }
            $this->addCommitCallback([$object, 'afterCommitCallback'])->commit();
            $object->setHasDataChanges(false);
        } catch (DuplicateException $e) {
            $this->rollBack();
            $object->setHasDataChanges(true);
            throw new AlreadyExistsException(new Phrase('Unique constraint violation found'), $e);
        } catch (\Exception $e) {
            $this->rollBack();
            $object->setHasDataChanges(true);
            throw $e;
        }
        return $this;
    }

and call model save() for example product, category, etc.

@engcom-Lima
Copy link
Contributor

Hi @krutkoroma79911, @ameysar,

Thank you for the reply.

As you said, this error is from the customised code's side which can be handles there itself and not from the Magento Implementation.

I asked for the errors you are getting so that I can understand the situation better. What I think is, If we replace catch (\Exception $e) with catch (\Throwable $e), it will not only catch all exceptions; it will also catch ALL errors. Errors are thrown to indicate serious problems that are not intended to be handled by an application. I don't think it is best practice to use \Throwable everywhere we get any errors.

Hope this clarifies.
Thanks

@engcom-Lima engcom-Lima added the Issue: needs update Additional information is require, waiting for response label Sep 15, 2021
@m2-community-project m2-community-project bot moved this from Ready for Confirmation to Needs Update in Issue Confirmation and Triage Board Sep 15, 2021
@RomanKrut
Copy link
Author

RomanKrut commented Sep 15, 2021

@engcom-Lima
Thank you for the reply.
Of course we understand that if we replace \Exception with catch \Throwable we will catch all errors. That is exaclty the point.
But look at catch \Exception block. After $this->rollBack(); we can see that exception is thrown again throw $e;, so I don`t see any problem if we catch \Throwable instance, rollback the transactions and throw \Throwable again.
Can you explain why it is bad practice?

@ameysar
Copy link
Contributor

ameysar commented Sep 15, 2021

@engcom-Lima
I've got your point. But if some extension adds observer for example on catalog_product_save_before and somehow TypeError will occur. We already have started transaction in database. I guess the expected behavior in this case would be gracefully rolled back transaction and record inserted in system.log/exception.log.
What do you think ?

@engcom-Lima
Copy link
Contributor

Hi @krutkoroma79911 , @ameysar,

Thank you guys for your inputs. I did some research on the same and found that it might not be bad if we can implement Throwable instead of Exception since it covers all the errors as well including TypeError. I am confirming this not as a bug but on the basis that we'll analyse it further and take action accordingly.

Thanks

@engcom-Lima engcom-Lima added Component: Exception Area: Framework Reproduced on 2.4.x The issue has been reproduced on latest 2.4-develop branch Issue: Confirmed Gate 3 Passed. Manual verification of the issue completed. Issue is confirmed labels Oct 6, 2021
@m2-community-project m2-community-project bot moved this from Needs Update to Confirmed in Issue Confirmation and Triage Board Oct 6, 2021
@m2-community-project m2-community-project bot removed the Issue: needs update Additional information is require, waiting for response label Oct 6, 2021
@github-jira-sync-bot
Copy link

✅ Jira issue https://jira.corp.magento.com/browse/AC-1396 is successfully created for this GitHub issue.

@m2-assistant
Copy link

m2-assistant bot commented Oct 6, 2021

✅ Confirmed by @engcom-Lima. Thank you for verifying the issue.
Issue Available: @engcom-Lima, You will be automatically unassigned. Contributors/Maintainers can claim this issue to continue. To reclaim and continue work, reassign the ticket to yourself.

@github-jira-sync-bot github-jira-sync-bot added the Priority: P2 A defect with this priority could have functionality issues which are not to expectations. label Oct 8, 2021
@m2-community-project m2-community-project bot added this to Ready for Development in High Priority Backlog Oct 8, 2021
@github-jira-sync-bot github-jira-sync-bot added Priority: P3 May be fixed according to the position in the backlog. and removed Priority: P2 A defect with this priority could have functionality issues which are not to expectations. labels Oct 8, 2021
@m2-community-project m2-community-project bot added this to Ready for Development in Low Priority Backlog Oct 8, 2021
@m2-community-project m2-community-project bot removed this from Ready for Development in High Priority Backlog Oct 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Framework Component: Exception Issue: Confirmed Gate 3 Passed. Manual verification of the issue completed. Issue is confirmed Priority: P3 May be fixed according to the position in the backlog. Progress: ready for dev Reproduced on 2.4.x The issue has been reproduced on latest 2.4-develop branch Triage: Dev.Experience Issue related to Developer Experience and needs help with Triage to Confirm or Reject it
Projects
Low Priority Backlog
  
Ready for Development
Development

No branches or pull requests

4 participants