Add Notification Eager Load Support#281
Conversation
make master the highest branch
2 similar comments
|
I think a combination of the last two points would be the best - so add a boolean-flag in On the other side, if we add eagerloading, it would be good to be able to load all relations (category, from, to). So what about a solution like: /**
* @param $eagerLoad array|bool
*/
public function getNotificationRelation($eagerLoad = false)
{
$with = null;
if($eagerLoad === true) {
$with = ['category', 'from', 'to']; // all relations
} elseif(is_array($eagerLoad)) {
$with = $eagerLoad;
}
return $this->notifications()->with($with);
}With this you can load nothing, everything or a specific set of relations. |
|
That's a nice solution! One concern might be should the default value for $eagerLoad be false or true:
|
|
For this I'm for /**
* @param $eagerLoad array|bool
*/
public function getNotificationRelation($eagerLoad = null)
{
$with = null;
if(is_null($eagerLoad)) {
$eagerLoad = notifynder_config('eager_load');
}
if($eagerLoad === true) {
$with = ['category', 'from', 'to']; // all relations
} elseif(is_array($eagerLoad)) {
$with = $eagerLoad;
}
return $this->notifications()->with($with);
} |
|
I've added the eager_load configuration parameter and modified the code accordingly, I will be waiting for your feedback. A Note on database-based tests: |
| $category = NotificationCategory::findOrFail($categoryId); | ||
| $category = $notification->category; | ||
| if (is_null($category)) { | ||
| throw (new ModelNotFoundException)->setModel( |
There was a problem hiding this comment.
Here you make the $categoryId param useless - I'm not 100% sure if this is ok. I think that we can remove it and see what happens - unittests & community.
There was a problem hiding this comment.
Alternatively we could set it to null, and if it is supplied, use the NotificationCategory::findOrFail to be backwards compatible, but I think its a bit of an overkill.
public function parse($notification, $categoryId = null)
{
if (is_null($categoryId)) {
$category = $notification->category;
if (is_null($category)) {
throw (new ModelNotFoundException)->setModel(
NotificationCategory::class, $notification->category_id
);
}
} else {
$category = NotificationCategory::findOrFail($categoryId);
}
src/Notifynder/Traits/Notifable.php
Outdated
| * @return \Illuminate\Database\Eloquent\Relations\HasMany|\Illuminate\Database\Eloquent\Relations\MorphMany | ||
| */ | ||
| public function getNotificationRelation() | ||
| private function getLazyLoadedNotificationRelation() |
There was a problem hiding this comment.
Pls don't use private we are open for overrides and customization - so at least protected. Even if I don't get it 100% why we need it here? We can control the eager loading with the new parameter - so this is just a wrapper for getNotificationRelation(false).
There was a problem hiding this comment.
I added the getLazyLoadedNotification method to avoid code duplication of the getNotificationRelation logic. Otherwise we would need to write the same logic in Notifable and NotifableL53
| $this->assertModelHasNoLoadedRelations($notifications[0], ['to']); | ||
| } | ||
|
|
||
| private function assertModelHasLoadedRelations($model, $relationNames = []) |
There was a problem hiding this comment.
Although it is just a helper test function, I will modify it to be protected for the the sake of Open/Closed Principle
| } | ||
| } | ||
|
|
||
| private function assertModelHasNoLoadedRelations($model, $relationNames = []) |
|
I've discovered an issue, since the default behaviour of getNotificationRelation is to read the configuration parameter eager_load. If the eager_load config is set to true, it will always eager load even in count/update functions. I will have to strictly call getLazyNotificationRelation() where eager loading is not needed like for counts and updates. I will be updating the code to do that. |
|
All modifications are done, I am waiting for your feedback on the remaining review point. |
|
✌️ Farewell PR, You started as a simple query fix, increased in scope to include the actual eager loading, and now you are lost forever.🚶 @Gummibeer I will keep this PR open, maybe one day you would have enough time to review it, I understand how hectic it is to manage multiple repos 📦 📦, last thing I want to become is a feature troll. |
|
@gaussian1 Hey, I'm super sorry for the delay. I had a bicycle accident last week and prepare two new releases at work. Your PR isn't lost or forgot. But I also don't want to merge it without a check - cause of the amount/chain of changes. Again sorry and I hope that you understand it!? |
|
I don't know if @fenos has time to check this? |
|
@Gummibeer Thanks for your quick reply, you don't need to apologize for anything. Sorry to hear about your bicycle incident 🤕 Take all the time you need, I was just poking you out 😋 |
|
@gaussian1 Hey, sorry again for the long delay! I've issued two new builds on travis (master & develop) branch to be sure that everything works like expected and will review what you've done now. |
|
@gaussian1 thanks for this big PR - it's merged into |
The Notification Parser made a direct call to the NotificationCategory::findOrFail function resulting in a n+1 query error, even if the notifications were already eager loaded.
This PR does the following:
Implementation Details:
In src/Notifynder/Parsers/NotificationParser.php: NotificationCategory::findOrFail function call was replaced by a model relation call:
❤️ [UX] Adds An eager loading configuration parameter called 'eager_load':
Each time a user wants to use eager loading he has to write something like this:
It is better to have an 'eager_load' configuration parameter to specify whether users want eager loading or not in their projects. The parameter can take any of these values:
The getNotificationRelation was divided into two methods:
getLazyNotificationRelationto get the relations without eager loading.getNotificationRelationto eager load the relations according to the configuration.Call Modifications:
Modifications were made to ignore the configuration parameter and use lazy loading for the following functions in
src/Notifynder/Traits/NotifableBasic.phpElectronically Yours,
Looking forward to your feedback!
EDIT: This next section discusses other eager loading options instead of using a configuration parameter, these options didn't make it to the Actual PR.. you can ignore it, or keep reading if you are interested: