opigno user selection xhr request fails to render on large sites

Created on 23 January 2024, 10 months ago
Updated 22 March 2024, 8 months ago

Hi all.

We've got a site that is having approx 7300 users and we've been plagued as well with the xhr/post request on the `user_selection/users` callback. The server hosting this site is having PHP 8.1 with 512Mb of available PHP memory and 3 minutes timeout, with the `opigno_learning_path` module at version 3.1.1

While it is quite nicely written in terms of coding, ie respecting the entities etc, it just is not that performant on a high volume of users (and trainings/classes)

This is mainly due to the fact that each entity is trying to get cached so if you have a database of more than 5kg users on the site, the caches break due to out of memory limitations, if the php timeout doesn't kick in.

One would say, why don't you just add more memory ? Well, this will buy you some time but only for a while: I tried to pump up my test site with 10k contacts and everything collapsed on the `group/xxx/content/add/group_membership` page, I got a WSOD only by visiting that page (`group/xxx/content/add/group_membership`).

Phase 1

As a first countermeasure, I tried to simplify/lighten the arrays by removing the email & avatar rendering process on each php call on the submodule
`opigno_user_selection` of `opigno_learning_path` -> https://git.drupalcode.org/project/opigno_learning_path/-/blob/3.1.1/mod... and https://git.drupalcode.org/project/opigno_learning_path/-/blob/3.1.1/mod...

Additionally, in order to make it more understandable to the end-user, I replaced the 'name' => $user->getDisplayName() with the 'name' => $user->getDisplayName() . ' [ ' . $user->id() . ']', so that they could see the user IDs along with the display names.

Then, I replaced the call opigno_messaging_get_all_recipients with my own call where I do a direct DB query to fetch the list of users based on conditions (user status -> 1 and user is not anonymous)

The above corrections started to make things functional again, on my original site with 7300 users, however, it was not enough with 10k users so I had to dig deeper.

Phase 2

On top of the above changes, I've started doing a more aggressive work, I've decided to ditch anything that relates to the function loadMultiple as this was the source of memory exhaustion and replaced them with direct SQL queries.

I've also replaced the getDisplayName() calls since I was having first + last name inside my SQL query results so there was no point to re-request that function. Additionally, for 7k contacts, the amount of calls to this function was massive.

The last thing I did was to drop most nested php calls of this sort:

        'member' => array_filter(array_map(function (GroupMembership $membership) use (&$groups_id, $map) {
          $group = $membership->getGroup();
          if (array_key_exists($group->bundle(), $map)) {
            $groups_id[] = ($gid = (int) $group->id());
            return $gid;
          }
          return NULL;
        }, $memberships)),

by preparing the sql statement, running it, creating an array of users and assigning that array to the `members` element instead of the nested functions.

Doing the above (Phase 2) did gave me a huge improvement and the data are now rendering properly and quickly. I have some doubts on some parts of my changes (especially one that does a permission check).

I can provide a patch though it needs to be carefully tested on the output as I might have missed something!

I believe this issue could be related with the following:
* https://www.drupal.org/project/opigno_learning_path/issues/3244973
* https://www.drupal.org/project/opigno_learning_path/issues/3326247 🐛 Imposible Add member to learningPath Active
* https://www.drupal.org/project/opigno_learning_path/issues/3397054 🐛 Opigno user selection when adding a new user to opigno_class returns 500 error Active

🌱 Plan
Status

Closed: outdated

Version

1.0

Component

User interface

Created by

🇬🇧United Kingdom vangelisp Fife, Scotland

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @vangelisp
  • Assigned to mdphoto
  • Status changed to Closed: outdated 8 months ago
  • Hi,
    I have the same problem with 39,000 classes and 7,000 users. I would like, if it's possible, your path for testing.

    For my part, and to unlock the situation, I removed the function opigno_learning_path_form_group_content_form_alter() to use the default system of the group module.

    Thank you

  • 🇬🇧United Kingdom vangelisp Fife, Scotland

    Hi mdphoto.

    Please try this patch that I've created, it should work/patch itself properly on the tag/version 3.1.1 of the module.

    Please keep in mind that all my optimisations were made towards the users and not the classes. I currently have just a bunch of classes (less than 100)

Production build 0.71.5 2024