Description
- Laravel Version: 5.8.29
- Nova Version: 2.0.9
- PHP Version: 7.3.3
- Operating System and Version: Debian 9
- Browser type and version: chrome 75
- Reproduction Repository: https://github.com/lk77/nova-observer-transaction-bug
Description:
Hello,
we have an issue with nova inside eloquent observers saved
events,
we expect that any transaction that nova opens, should be closed when the saved
observer method is called, which is not the case.
We want to do something in the observer, like a file deletion, an http request or an event broadcast, something that can be undone. And the fact that transaction is still open and that the row doesn't exists in database yet is not consistent.
That action in the observer will cause other actions in cascade of third parties, like incoming requests. So a incoming request, that wants to recover a newly created instance, will get an error, because row doesn't exist yet (transaction is still going). It depends on the latency between the server and the client, but it's not quite right.
Steps To Reproduce:
1 / git clone https://github.com/lk77/nova-observer-transaction-bug
2 / composer update
3 / cp .env.example .env // change database informations
4 / php artisan serve
5 / go to http://localhost:8000/nova/resources/tests
6 / click on the create button
7 / open F12 network on chrome (or whatever you are using)
8 / submit a new test
9 / inside http://localhost:8000/nova-api/tests
request, see the dump saying :
"transation status : open"
the code responsible for the dump inside App\Observers\TestObserver::saved
:
dd('transation status : ' . (\DB::transactionLevel() > 0 ? 'open' : 'closed'));
10 / see in database the test row has not been added.
For now, the solution seems to add this inside resource :
/**
* Return the location to redirect the user after creation.
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @param \App\Nova\Resource $resource
* @return string
*/
public static function redirectAfterCreate(NovaRequest $request, $resource)
{
// do custom process here, after transaction
return parent::redirectAfterCreate($request, $resource);
}
wich is more like a hack.
A possible solution will be to introduce a hook inside resource, called after transaction in controller.
thanks.