Hi,

I have been working with quiz module for some time and i am opening my drupal site and allowing anonymous users to take exams

I have seen the site going up in memory as i am always getting error message of "drupal Allowed memory size of ... bytes exhausted" when anonymous user tries to take a quiz

so as a quick solution, i used to raise my memory limit till it went to 350MB (by setting php memory_limit) though i am on VPS and this used to work.

Then i decided to take this into some analysis and installed xhprof to see what is consuming the memory, from the call graph i am seeing huge amount of calls and memory going to QuizResultController:save
which i see always loading all previous attempts in below part and this is usually valid but in case of anonymous users (uid is always 0) it will always load all anonymous users results before starting the quiz.

I would expect anonymous users to be excluded from allowing them many attempts for the same quiz

I am attaching the call graph for some info, let me know what you think please

    if (!isset($entity->attempt)) {
      $efq = new EntityFieldQuery();
      $result = $efq->entityCondition('entity_type', 'quiz_result')
        ->propertyCondition('nid', $entity->nid)
        ->propertyCondition('uid', $entity->uid)
        ->propertyOrderBy('attempt', 'DESC')
        ->execute();
      if (!empty($result['quiz_result'])) {
        $keys = array_keys($result['quiz_result']);
        $existing = quiz_result_load(reset($keys));
        $entity->attempt = $existing->attempt + 1;
      }
    }
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Sherif Darwish created an issue. See original summary.

djdevin’s picture

Thanks for the report.

This is definitely a bug.

djdevin’s picture

Version: 7.x-5.0-beta2 » 7.x-5.x-dev
Status: Active » Needs review
FileSize
581 bytes
djdevin’s picture

Can you try the above patch and let me know if the memory issues disappear?

Sherif Darwish’s picture

Thanks a lot for your support, I would see this should resolve the bug by only loading the one row, but i was suggesting a different alternative which is to keep aside attempts for anonymous users, so in my case i added the below condition to the code (user_is_logged_in) as it makes some common sense for me to say that all anonymous users cannot track their attempts as they are all having the same UID = 0 though they are different persons

Please, let me know what do you think, thanks


    $new = !empty($entity->is_new);

    if ( user_is_logged_in() && !isset($entity->attempt)) {
      $efq = new EntityFieldQuery();
      $result = $efq->entityCondition('entity_type', 'quiz_result')
        ->propertyCondition('nid', $entity->nid)
        ->propertyCondition('uid', $entity->uid)
        ->propertyOrderBy('attempt', 'DESC')
        ->range(0, 1)
        ->execute();
      if (!empty($result['quiz_result'])) {
        $keys = array_keys($result['quiz_result']);
        $existing = quiz_result_load(reset($keys));
        $entity->attempt = $existing->attempt + 1;
      }
    }

djdevin’s picture

That's probably better, with two small changes:

- Set the attempt number to 1 (since every anonymous user is considered a "first" attempt)
- Check $entity->uid, in case the result is being saved by a different user or created programmatically

Sherif Darwish’s picture

Thanks but looks like you forgot to include the range statement which will limit the returned results in case of authenticated users

        ->range(0, 1)

i would assume the below should pass the test cases


     if (!isset($entity->attempt)) {
-      $efq = new EntityFieldQuery();
-      $result = $efq->entityCondition('entity_type', 'quiz_result')
-        ->propertyCondition('nid', $entity->nid)
-        ->propertyCondition('uid', $entity->uid)
-        ->propertyOrderBy('attempt', 'DESC')
-        ->execute();
-      if (!empty($result['quiz_result'])) {
-        $keys = array_keys($result['quiz_result']);
-        $existing = quiz_result_load(reset($keys));
-        $entity->attempt = $existing->attempt + 1;
+      if ($entity->uid == 0) {
+        $entity->attempt = 1;
+      }
+      else {
+        $efq = new EntityFieldQuery();
+        $result = $efq->entityCondition('entity_type', 'quiz_result')
+          ->propertyCondition('nid', $entity->nid)
+          ->propertyCondition('uid', $entity->uid)
+          ->propertyOrderBy('attempt', 'DESC')
+          ->range(0, 1)
+          ->execute();
+        if (!empty($result['quiz_result'])) {
+          $keys = array_keys($result['quiz_result']);
+          $existing = quiz_result_load(reset($keys));
+          $entity->attempt = $existing->attempt + 1;
+        }
       }
     }
 
djdevin’s picture

djdevin’s picture

Status: Needs review » Fixed

Thanks, fixed!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.