Hi Thomas,

the situation described by you, if I got it right, is that a (payment)
module likes to avoid the rollback of a transaction in case of error.

I would try to do so by overloading methods responsible for calling that
rollback.
First thing came to my mind is to overload finalizeOrder in a way
it always true, even in case of error - so no rollback will happen if
finalizeOrder will fail.

Theoretically you could also overload
 recalculateOrder completely without calling the parent ( that is of cause
kind of evil and should be the very last option :-) ). So you could
owerrite the error handling completely avoiding rollback in all cases.

If you know all the exceptions it could also be possible to catch them
before they are causing the rollback. E.g. catch the email send error, log
it and continue with order.

If you really have to write something to a database independently from the
current transaction you could also start a new db connection. I normally
would not do so because you need to think about resource locking and
referenced data but you may have a case here where it's kind of legal to do
so.

One note about nested transactions: To extend what robert has written I suggest
to use savepoints in case you want to use a nested transaction within the
payment module and that may cause itself exceptions and related rollbacks.
That way it is possible to rollback to nested transaction without having to
rollback the full outer transaction. Dbal is supporting savepoints by
$conn->beginTransaction('mysavepoint');
 and
$conn->rollback('mysavepoint');

which is pretty cool, isn't it ?

One note how to avoid errors during sending emails, even that usecase was
only a example choosen by to point out that there could be errors during
the order, my personal opinion is that each oxid server should have a local
running postfix server that acts as a local mail queue. That way the shop
can always send a email even if the network is down.

best regards

K1
[Your secret expert for high security, availablity and performance.]




From: "Marco Steinhaeuser" <marco.steinhaeu...@oxid-esales.com>

Date: Mon, Nov 27, 2017 at 6:06 PM +0100
Subject: Re: Re-2: oxid V6 MySQL transactions
To: "dev-general@lists.oxidforge.org" <dev-general@lists.oxidforge.org>


Folks,

could we please stick to English in this channel?

Cheers!
Marco



-------- Ursprüngliche Nachricht --------
Von: Robert Blank <robert.bl...@oxid-esales.com>
Datum: 27.11.17 17:54 (GMT+01:00)
An: dev-general@lists.oxidforge.org
Betreff: Re: Re-2: oxid V6 MySQL transactions

Hallo,
Man kann in Doctrine leider das Rollback in verschachtelten Transaktionen
nicht feinkörnig steuern, bzw kapseln: Wenn eine der inneren Transaktionen
einen rollback macht, werden alle daran beteiligten Transaktionen (auch die
äußeren!) zurück gerollt.

http://docs.doctrine-project.org/projects/doctrine-dbal/en/
latest/reference/transactions.html#transaction-nesting

"To achieve that, you need to restructure your application logic so as to
avoid nesting transaction blocks. If this is not possible because the
nested transaction blocks are in a third-party API you’re out of luck."

Da liegt m.E. der Pudels Kern. Durch das Modulsystem haben wir sozusagen
diesen Fall der "third-party API", denn jedes Modul kann ja theoretisch ein
->rollbackTransaction() aufrufen und damit sind dann sowieso alle
Möglichkeiten hinüber. Es wird ausdrücklich darauf hingewiesen nicht
anzufangen kreativ zu programmieren:
Directly invoking PDO#beginTransaction(), PDO#commit() or PDO#rollBack() or
the corresponding methods on the particular
Doctrine\DBAL\Driver\Connection instance
in use bypasses the transparent transaction nesting that is provided by
Doctrine\DBAL\Connection and can therefore corrupt the nesting level,
causing errors with broken transaction boundaries that may be hard to debug.
Das Rollback lässt sich ab diesem Moment nicht mehr überschreiben.

Die einzige Garantie die das Framework hier geben kann und will ist "all or
nothing".


MfG

Robert Blank


P.S.

"Zumal es völlig sinnfrei ist, eine Bestellung nur wegen einer nicht
verschickbaren Mail komplett zu verwerfen."
(+1)

On 27.11.2017 16:34, oxid mailinglist wrote:

Hallo,

die Antwort ist für mich wirklich schwer zu akzeptieren.

"We want really all database transactions to be rolled back, if a problem
during e.g. the payment execution occurs."

Es passiert eine payment transaktion! Wie soll auf so ein Fall korrekt
reagiert werden?

Beispiel: Eine Bestellung ist komplett durchgeführt inkl erfolgreiche
Bezahlung per Paymentanbieter. Nun kann jedoch die Mail an den Kunden nicht
geschickt werden. Es erfolgt ein komplettes rollback!

Wie soll nun ein Paymentmodul korrekt darauf reagieren können? Es gibt
keine transaktionslog-Infos mehr.
Zumal es völlig sinnfrei ist, eine Bestellung nur wegen einer nicht
verschickbaren Mail komplett zu verwerfen. Aber darum geht es gar nicht.

Es gibt aktuell keine Möglichkeit auf ein rollback korrekt zu reagieren, da
nicht überladbar.
->  \OxidEsales\Eshop\Core\DatabaseProvider::getDb()->startTransaction();

Es muss doch von OXID eine Möglichkeit geben auf so ein Ereignis korrekt
reagieren zu können, ohne dass man die eigenen log/transaktions-Daten in
Dateien abspeichern muss!


Mit freundlichen Grüßen
Thomas Dartsch
thomas.dart...@shopmodule.com



 Original Message processed by david®

*Re: oxid V6 MySQL transactions* (27-Nov-2017 16:00)
*From:*   Robert Blank <robert.bl...@oxid-esales.com>
*To:*
dev-general@lists.oxidforge.org


Hi,

in your use-case this may sound strange, but this is by design.
First by OXID eShop design:
We want really _all_ database transactions to be rolled back, if a problem
during e.g. the payment execution occurs.

Then there is the design of the underlying DBAL:
As we us Doctrine DBAL, we cannot provide savepoints or partial rollbacks,
as Doctrine DBAL does not provide this functionality:
http://docs.doctrine-project.org/projects/doctrine-dbal/en/
latest/reference/transactions.html#transaction-nesting

You should also not try to bypass this behavior as it will break the nested
transaction handling of Doctrine.
In you case I fear, there is no other way as to store your log data into a
file.

Best regards

Robert Blank


On 20.11.2017 15:13, oxid mailinglist wrote:


Hello guys,

with oxid Version 6.0 the shop is using MySQL transactions. ->
https://dev.mysql.com/doc/refman/5.7/en/commit.html

For example this is used in OxidEsales\Eshop\Application\
Model\Order::recalculateOrder
(formally known as oxorder::recalculateOrder).
https://github.com/OXID-eSales/oxideshop_ce/blob/
472ce3d73e5f0e46a29566f5290a85d631bd00db/source/Application/
Model/Order.php#L1354

In the process of Order::finalizeOrder, the PaymentGateway::executePayment()
allows
modules to perform module based validations.
https://github.com/OXID-eSales/oxideshop_ce/blob/
472ce3d73e5f0e46a29566f5290a85d631bd00db/source/Application/
Model/Order.php#L916

Some payment provider will create transactions and send it back to the shop.
A module will be willing to save/log these transactions to the database.
If there are a failed transaction and the module save his object via shop
standard BaseModel::save()
and the PaymentGateway::executePayment() return a false,
the complete MySQL transaction will be ROLLBACK'ed.
(Order::recalculateOrder())
https://github.com/OXID-eSales/oxideshop_ce/blob/
472ce3d73e5f0e46a29566f5290a85d631bd00db/source/Application/
Model/Order.php#L1374

So the module lost all informations/transactions, which are saved during
the transaction.


How is oxid's suggestion to save these transactions from ROLLBACK?



best regards
Kristian Hempel

-- 


Richten Sie Fehlermeldungen und Supportanfragen bitte an
supp...@shopmodule.com.
------------------------------
Fresh ideas for your business
------------------------------
D³ Data Development (Inh. Thomas Dartsch)
Stollberger Straße 23
<https://maps.google.com/?q=Stollberger+Stra%C3%9Fe+23&entry=gmail&source=g>
· D-09380 Thalheim
Fon 03721 268090 · Fax 03721 265234

Shop: http://www.oxidmodule.com Firma: http://www.shopmodule.com
Blog: http://blog.oxidmodule.com FAQ: http://faq.oxidmodule.com
OXID eSales AG
Certified Partner
Business Level
Profihost AG
Enterprise Partner


-- 


*Robert Blank*
Software Developer OXID Platform

*robert.bl...@oxid-esales.com <robert.bl...@oxid-esales.com>*
Fon +49 761 36889-233 <+49%20761%2036889233>
Fax +49 761 36889-29 <+49%20761%203688929>
*www.oxid-esales.com
<http://www.oxid-esales.com?campaign=emailsignatur/oxid-esales-com&adword=OXSIG_Startseite>*


*OXID eSales AG*
Bertoldstraße 48
<https://maps.google.com/?q=Bertoldstra%C3%9Fe+48+%0D+79098+Freiburg+%0D+Deutschland&entry=gmail&source=g>
79098 Freiburg
Deutschland

Vorstand: Roland Fesenmayr (Vorsitzender), Dr. Oliver Ciupke
Vorsitzender des Aufsichtsrats: Michael Schlenk, Sitz: Freiburg
Amtsgericht Freiburg i. Br., HRB 701648, USt-IdNr.: DE231450866





-- 


*Robert Blank*
Software Developer OXID Platform

*robert.bl...@oxid-esales.com <robert.bl...@oxid-esales.com>*
Fon +49 761 36889-233 <+49%20761%2036889233>
Fax +49 761 36889-29 <+49%20761%203688929>
*www.oxid-esales.com
<http://www.oxid-esales.com?campaign=emailsignatur/oxid-esales-com&adword=OXSIG_Startseite>*


*OXID eSales AG*
Bertoldstraße 48
<https://maps.google.com/?q=Bertoldstra%C3%9Fe+48+%0D+79098+Freiburg+%0D+Deutschland&entry=gmail&source=g>
79098 Freiburg
Deutschland

Vorstand: Roland Fesenmayr (Vorsitzender), Dr. Oliver Ciupke
Vorsitzender des Aufsichtsrats: Michael Schlenk, Sitz: Freiburg
Amtsgericht Freiburg i. Br., HRB 701648, USt-IdNr.: DE231450866

Reply via email to