Changeset 317


Ignore:
Timestamp:
03/15/10 15:22:34 (10 years ago)
Author:
sander
Message:

Cache testuite gallery views and regresg pages using build-in cron

Location:
trunk/server/www/app
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/server/www/app/config/core.php.default

    r298 r317  
    365365 */ 
    366366        Configure::write('Gallery.abbreviate', 25); 
     367/** 
     368 * Cron job to refresh the cache of test suite galleries 
     369 */ 
     370        Configure::write('Cron.testsuite_refresh', array( 
     371                'Model' => 'Testsuite', 
     372                'method' => 'recache', 
     373                'interval' => 5 * 60, // execute every 5 minutes 
     374        )); 
    367375?> 
  • trunk/server/www/app/controllers/galleries_controller.php

    r315 r317  
    7373 
    7474        /** 
    75          * Sort an array of Galleries threaded, like find('threaded') would do 
    76          */ 
    77         private function _sortThreaded($results) 
    78         { 
    79                 $return = $idMap = array(); 
    80                 $ids = Set::extract($results, '{n}.Gallery.id'); 
    81  
    82                 foreach ($results as $result) { 
    83                         $result['children'] = array(); 
    84                         $id = $result['Gallery']['id']; 
    85                         $parentId = $result['Gallery']['parent_id']; 
    86                         if (isset($idMap[$id]['children'])) { 
    87                                 $idMap[$id] = array_merge($result, (array)$idMap[$id]); 
    88                         } else { 
    89                                 $idMap[$id] = array_merge($result, array('children' => array())); 
    90                         } 
    91                         if (!$parentId || !in_array($parentId, $ids)) { 
    92                                 $return[] =& $idMap[$id]; 
    93                         } else { 
    94                                 $idMap[$parentId]['children'][] =& $idMap[$id]; 
    95                         } 
    96                 } 
    97                 if (count($return) > 1) { 
    98                         $ids = array_unique(Set::extract('/Gallery/parent_id', $return)); 
    99                         if (count($ids) > 1) { 
    100                                 $root = $return[0]['Gallery']['parent_id']; 
    101                                 foreach ($return as $key => $value) { 
    102                                         if ($value['Gallery']['parent_id'] != $root) { 
    103                                                 unset($return[$key]); 
    104                                         } 
    105                                 } 
    106                         } 
    107                 } 
    108                 return $return; 
    109         } 
    110  
    111         /** 
    11275         * Show a list of all galleries 
    11376         */ 
     
    138101                $gallery = $this->Gallery->find('first', array( 
    139102                        'conditions' => array('Gallery.slug' => $slug), 
    140                         'contain' => array( 
    141                                 'Request' => array('order' => 'Request.filename ASC'), 
    142                                 'Request.Validator' => array('order' => 'Validator.name ASC'), 
    143                                 'Request.Job' => array('order' => array( 
    144                                         'Application.name ASC', 
    145                                         'Job.version ASC', 
    146                                         'Platform.name ASC', 
    147                                         'Format.name ASC', 
    148                                 )), 
    149                                 'Request.Job.Application', 
    150                                 'Request.Job.Format', 
    151                                 'Request.Job.Platform', 
    152                                 'Request.Job.Result', 
    153                                 'Request.Job.Result.Validator', 
    154                         ), 
    155                 )); 
    156  
    157                 // Find out if this test suite needs to be abbreviated 
    158                 $requestCount = $this->Gallery->requestCount($gallery['Gallery']['id'], true); 
    159                 $isTestsuite = $this->Gallery->isTestsuite($gallery['Gallery']['id']); 
    160                 $abbreviate = ($requestCount >= Configure::read('Gallery.abbreviate') && !$isTestsuite); 
    161  
    162                 // Get the children of this gallery 
    163                 $children = $this->Gallery->find('all', array( 
    164                         'conditions' => array( 
    165                                 'Gallery.lft >' => $gallery['Gallery']['lft'], 
    166                                 'Gallery.rght <' => $gallery['Gallery']['rght'], 
    167                         ), 
    168                         'contain' => array('Request' => array('order' => 'Request.filename ASC')), 
    169                         'order' => array('Gallery.name ASC'), 
    170                 )); 
    171  
    172                 foreach ($children as &$child) { 
    173                         foreach ($child['Request'] as &$request) { 
    174                                 $request['Validator'] = $this->Request->Validator->find('all', array( 
    175                                         'conditions' => array('Validator.parent_id' => $request['id']), 
    176                                         'order'      => 'Validator.name ASC', 
    177                                         'recursive'  => -1, 
    178                                 )); 
    179  
    180                                 if (!$abbreviate) { 
    181                                         $request['Job'] = $this->Request->Job->find('all', array( 
    182                                                 'conditions' => array('Job.request_id' => $request['id']), 
    183                                                 'contain' => array( 
    184                                                         'Application', 
    185                                                         'Format', 
    186                                                         'Platform', 
    187                                                         'Result', 
    188                                                         'Result.Validator' 
    189                                                 ), 
    190                                                 'order' => array( 
    191                                                         'Application.name ASC', 
    192                                                         'Job.version ASC', 
    193                                                         'Platform.name ASC', 
    194                                                         'Format.name ASC', 
    195                                                 ), 
    196                                         )); 
    197  
    198                                         // Fix array layout to match a regular query layout 
    199                                         foreach ($request['Job'] as &$job) { 
    200                                                 foreach ($job['Job'] as $attr => $value) { 
    201                                                         $job[$attr] = $value; 
    202                                                 } 
    203                                                 unset($job['Job']); 
    204                                         } 
    205                                         unset($job); 
    206                                 } 
    207                         } 
    208                 } 
    209  
    210                 // If this is a Testsuite then we need some extra information 
    211                 if ($isTestsuite) { 
    212                         $versions = array(); 
    213                         $jobs = Set::extract('/Request/Job', $gallery); 
    214                         $jobs = array_merge(Set::extract('/Request/Job', $children), $jobs); 
    215  
    216                         foreach ($jobs as $job) { 
    217                                 $application = $job['Job']['application_id']; 
    218                                 if (!isset($versions[$application])) { 
    219                                         $versions[$application] = $job['Job']['version']; 
    220                                         continue; 
    221                                 } 
    222  
    223                                 if ($job['Job']['version'] > $versions[$application]) { 
    224                                         $versions[$application] = $job['Job']['version']; 
    225                                 } 
    226                         } 
    227                         unset($application); // Because we're referencing below 
    228  
    229                         $applications = $this->Application->find('all', array( 
    230                                 'conditions' => array('Application.id' => array_keys($versions)), 
    231                                 'order' => array('Application.name'), 
    232                                 'recursive' => -1, 
    233                         )); 
    234  
    235                         foreach ($applications as &$application) { 
    236                                 $application['Application']['version'] = $versions[$application['Application']['id']]; 
    237                         } 
    238                         unset($application); // Drop the reference 
    239  
    240                         $this->set(compact('applications')); 
    241                 } 
    242  
    243                 // Sort the subgalleries for display 
    244                 $gallery['children'] = $this->_sortThreaded($children); 
    245  
    246                 // Get the path to this gallery 
    247                 $path = $this->Gallery->getpath($gallery['Gallery']['id']); 
    248                 array_pop($path); 
     103                        'recursive' => -1, 
     104                )); 
     105 
     106                $data = Cache::read('gallery/' . $gallery['Gallery']['id']); 
     107                if ($data === false) { 
     108                        $data = $this->Gallery->viewData($gallery['Gallery']['id']); 
     109                } 
    249110 
    250111                // Check access 
    251112                $access = $this->_checkAccess($slug); 
    252                 $this->set(compact('gallery', 'path', 'access', 'abbreviate')); 
     113                $data = array_merge($data, compact('access')); 
     114                $this->set($data); 
    253115 
    254116                // Render 
    255                 if ($isTestsuite) { 
     117                if ($data['isTestsuite']) { 
    256118                        $this->render('testsuite'); 
    257119                } 
  • trunk/server/www/app/models/gallery.php

    r315 r317  
    9393                } 
    9494 
     95                // First, find the root of the gallery tree 
     96                $gallery = $this->find('first', array( 
     97                        'conditions' => array('Gallery.id' => $id), 
     98                        'recursive' => -1, 
     99                )); 
     100 
     101                if ($gallery['Gallery']['parent_id']) { 
     102                        $root = $this->find('first', array( 
     103                                'conditions' => array( 
     104                                        'Gallery.parent_id IS NULL', 
     105                                        'Gallery.lft <=' => $gallery['Gallery']['lft'], 
     106                                        'Gallery.rght >=' => $gallery['Gallery']['rght'], 
     107                                ), 
     108                                'recursive' => -1, 
     109                        )); 
     110                } else { 
     111                        $root = $gallery; 
     112                } 
     113 
    95114                $count = $this->Testsuite->find('count', array( 
    96                         'conditions' => array('Testsuite.gallery_id' => $id), 
     115                        'conditions' => array('Testsuite.gallery_id' => $root['Gallery']['id']), 
    97116                        'recursive' => -1, 
    98117                )); 
     
    238257 
    239258        /** 
     259         * Get the view data for a gallery 
     260         * This is implemented in the model so we can call it in the background and cache the result 
     261         */ 
     262        public function viewData($id) 
     263        { 
     264                // Get the gallery 
     265                $gallery = $this->find('first', array( 
     266                        'conditions' => array('Gallery.id' => $id), 
     267                        'contain' => array( 
     268                                'Request' => array('order' => 'Request.filename ASC'), 
     269                                'Request.Validator' => array( 
     270                                        'fields' => array('id', 'parent_id', 'name', 'state'), 
     271                                        'order' => 'Validator.name ASC', 
     272                                ), 
     273                                'Request.Job' => array('order' => array( 
     274                                        'Application.name ASC', 
     275                                        'Job.version ASC', 
     276                                        'Platform.name ASC', 
     277                                        'Format.name ASC', 
     278                                )), 
     279                                'Request.Job.Application', 
     280                                'Request.Job.Format', 
     281                                'Request.Job.Platform', 
     282                                'Request.Job.Result', 
     283                                'Request.Job.Result.Validator', 
     284                        ), 
     285                )); 
     286 
     287                // Find out if this test suite needs to be abbreviated 
     288                $requestCount = $this->requestCount($id, true); 
     289                $isTestsuite = $this->isTestsuite($id); 
     290                $abbreviate = ($requestCount >= Configure::read('Gallery.abbreviate') && !$isTestsuite); 
     291 
     292                // Get the children of this gallery 
     293                $children = $this->find('all', array( 
     294                        'conditions' => array( 
     295                                'Gallery.lft >' => $gallery['Gallery']['lft'], 
     296                                'Gallery.rght <' => $gallery['Gallery']['rght'], 
     297                        ), 
     298                        'contain' => array('Request' => array('order' => 'Request.filename ASC')), 
     299                        'order' => array('Gallery.name ASC'), 
     300                )); 
     301 
     302                foreach ($children as &$child) { 
     303                        foreach ($child['Request'] as &$request) { 
     304                                $request['Validator'] = $this->Request->Validator->find('all', array( 
     305                                        'fields'     => array('id', 'parent_id', 'name', 'state'), 
     306                                        'conditions' => array('Validator.parent_id' => $request['id']), 
     307                                        'order'      => 'Validator.name ASC', 
     308                                        'recursive'  => -1, 
     309                                )); 
     310 
     311                                if (!$abbreviate) { 
     312                                        $request['Job'] = $this->Request->Job->find('all', array( 
     313                                                'conditions' => array('Job.request_id' => $request['id']), 
     314                                                'contain' => array( 
     315                                                        'Application', 
     316                                                        'Format', 
     317                                                        'Platform', 
     318                                                        'Result', 
     319                                                        'Result.Validator' 
     320                                                ), 
     321                                                'order' => array( 
     322                                                        'Application.name ASC', 
     323                                                        'Job.version ASC', 
     324                                                        'Platform.name ASC', 
     325                                                        'Format.name ASC', 
     326                                                ), 
     327                                        )); 
     328 
     329                                        // Fix array layout to match a regular query layout 
     330                                        foreach ($request['Job'] as &$job) { 
     331                                                foreach ($job['Job'] as $attr => $value) { 
     332                                                        $job[$attr] = $value; 
     333                                                } 
     334                                                unset($job['Job']); 
     335                                        } 
     336                                        unset($job); 
     337                                } 
     338                        } 
     339                } 
     340 
     341                // If this is a Testsuite then we need some extra information 
     342                $applications = array(); 
     343                if ($isTestsuite) { 
     344                        $versions = array(); 
     345                        $jobs = Set::extract('/Request/Job', $gallery); 
     346                        $jobs = array_merge(Set::extract('/Request/Job', $children), $jobs); 
     347 
     348                        foreach ($jobs as $job) { 
     349                                $application = $job['Job']['application_id']; 
     350                                if (!isset($versions[$application])) { 
     351                                        $versions[$application] = $job['Job']['version']; 
     352                                        continue; 
     353                                } 
     354 
     355                                if ($job['Job']['version'] > $versions[$application]) { 
     356                                        $versions[$application] = $job['Job']['version']; 
     357                                } 
     358                        } 
     359                        unset($application); // Because we're referencing below 
     360 
     361                        $applications = $this->Request->Job->Application->find('all', array( 
     362                                'conditions' => array('Application.id' => array_keys($versions)), 
     363                                'order' => array('Application.name'), 
     364                                'recursive' => -1, 
     365                        )); 
     366 
     367                        foreach ($applications as &$application) { 
     368                                $application['Application']['version'] = $versions[$application['Application']['id']]; 
     369                        } 
     370                        unset($application); // Drop the reference 
     371                } 
     372 
     373                // Sort the subgalleries for display 
     374                $gallery['children'] = $this->_sortThreaded($children); 
     375 
     376                // Get the path to this gallery 
     377                $path = $this->getpath($gallery['Gallery']['id']); 
     378                array_pop($path); 
     379 
     380                return compact('gallery', 'applications', 'path', 'abbreviate', 'isTestsuite'); 
     381        } 
     382 
     383        /** 
     384         * Sort an array of Galleries threaded, like find('threaded') would do 
     385         */ 
     386        private function _sortThreaded($results) 
     387        { 
     388                $return = $idMap = array(); 
     389                $ids = Set::extract($results, '{n}.Gallery.id'); 
     390 
     391                foreach ($results as $result) { 
     392                        $result['children'] = array(); 
     393                        $id = $result['Gallery']['id']; 
     394                        $parentId = $result['Gallery']['parent_id']; 
     395                        if (isset($idMap[$id]['children'])) { 
     396                                $idMap[$id] = array_merge($result, (array)$idMap[$id]); 
     397                        } else { 
     398                                $idMap[$id] = array_merge($result, array('children' => array())); 
     399                        } 
     400                        if (!$parentId || !in_array($parentId, $ids)) { 
     401                                $return[] =& $idMap[$id]; 
     402                        } else { 
     403                                $idMap[$parentId]['children'][] =& $idMap[$id]; 
     404                        } 
     405                } 
     406                if (count($return) > 1) { 
     407                        $ids = array_unique(Set::extract('/Gallery/parent_id', $return)); 
     408                        if (count($ids) > 1) { 
     409                                $root = $return[0]['Gallery']['parent_id']; 
     410                                foreach ($return as $key => $value) { 
     411                                        if ($value['Gallery']['parent_id'] != $root) { 
     412                                                unset($return[$key]); 
     413                                        } 
     414                                } 
     415                        } 
     416                } 
     417                return $return; 
     418        } 
     419 
     420        /** 
    240421         * Convert the Markdown description to HTML before saving 
    241422         * @return boolean True to continue saving 
  • trunk/server/www/app/models/testsuite.php

    r297 r317  
    331331                $this->Request->addJobs($newJobs); 
    332332        } 
     333 
     334        /** 
     335         * Regenerate the cached data for all the test suite gallery views 
     336         */ 
     337        public function recache() 
     338        { 
     339                $suites = $this->find('all', array('recursive' => -1)); 
     340                $this->log('Caching view data for ' . sizeof($suites) . ' testsuites', LOG_DEBUG); 
     341 
     342                foreach ($suites as $suite) { 
     343                        if (!$suite['Testsuite']['gallery_id']) { 
     344                                continue; 
     345                        } 
     346 
     347                        // Cache the view data for the top-level view 
     348                        $data = $this->Gallery->viewData($suite['Testsuite']['gallery_id']); 
     349                        Cache::write('gallery/' . $suite['Testsuite']['gallery_id'], $data); 
     350 
     351                        // Get all subgalleries 
     352                        $gallery = $this->Gallery->find('first', array( 
     353                                'conditions' => array('Gallery.id' => $suite['Testsuite']['gallery_id']), 
     354                                'recursive' => -1, 
     355                        )); 
     356 
     357                        $subgalleries = $this->Gallery->find('all', array( 
     358                                'conditions' => array( 
     359                                        'Gallery.lft >' => $gallery['Gallery']['lft'], 
     360                                        'Gallery.rght <' => $gallery['Gallery']['rght'], 
     361                                ), 
     362                                'recursive' => -1, 
     363                        )); 
     364 
     365                        // Cache the data for all the subgallery views 
     366                        foreach ($subgalleries as $subgallery) { 
     367                                $data = $this->Gallery->viewData($subgallery['Gallery']['id']); 
     368                                Cache::write('gallery/' . $subgallery['Gallery']['id'], $data); 
     369                        } 
     370                } 
     371 
     372                return true; 
     373        } 
    333374} 
    334375 
  • trunk/server/www/app/plugins/bean_stalk/vendors/shells/worker.php

    r278 r317  
    3232        public $pid = null; 
    3333 
     34        /** @var array A queue for cron jobs */ 
     35        public $cron = array(); 
     36 
    3437        /** 
    3538         * Override startup to parse arguments 
     
    123126                $this->beanstalk =& BeanStalkManager::getBeanStalk(); 
    124127                 
     128                // Start watching Beanstalkd tubes 
    125129                foreach ($this->tubes as $tube) { 
    126130                        $tube = trim($tube); 
     
    128132                } 
    129133 
     134                // Initialize the cron queue. We don't know the last run, so run everything at startup 
     135                $tasks = Configure::read('Cron'); 
     136                if (is_array($tasks)) { 
     137                        foreach ($tasks as $task_name => $task) { 
     138                                $this->cron[time()] = $task_name; 
     139                        } 
     140 
     141                        ksort($this->cron); 
     142                        reset($this->cron); 
     143                } 
     144 
     145                // Main loop 
    130146                while (true) { 
    131                         $job = $this->beanstalk->reserve(); 
     147                        // Execute pending cron jobs. This gives the time to the next planned job 
     148                        $time = $this->cron_tick(); 
     149                        $this->log('Next cron job in ' . $time . ' seconds', LOG_DEBUG); 
     150                        $job = $this->beanstalk->reserve_with_timeout($time); 
    132151 
    133152                        if ($job == false) { 
     153                                // We get here when we get a bogus message, on DEALINE_SOON and on TIMEOUT 
    134154                                continue; 
    135155                        } 
     
    272292        } 
    273293 
     294        /** 
     295         * Stop the background daemon 
     296         */ 
    274297        private function run_stop($message) 
    275298        { 
    276299                $this->_stop(); 
     300        } 
     301 
     302        /** 
     303         * Look at the cron queue, execute any outstanding tasks 
     304         * @return int Time in seconds until the next task 
     305         */ 
     306        private function cron_tick() 
     307        { 
     308                if (sizeof($this->cron) == 0) { 
     309                        return 3600; // Arbitrary 
     310                } 
     311 
     312                $time = time(); 
     313                while (key($this->cron) <= $time) { 
     314                        // Read the task 
     315                        $task_name = array_shift($this->cron); 
     316                        $task = Configure::read('Cron.' . $task_name); 
     317 
     318                        // Execute the task 
     319                        App::import('Model', $task['Model']); 
     320                        $model = ClassRegistry::init($task['Model']); 
     321                        $model->create(); 
     322 
     323                        if (!method_exists($model, $task['method'])) { 
     324                                $message = sprintf('%s->%s does not exist', $task['Model'], $task['method']); 
     325                                $this->log($message, LOG_DEBUG); 
     326                                $this->out($message); 
     327                        } 
     328 
     329                        if (isset($task['args'])) { 
     330                                call_user_func_array(array($model, $task['method']), $task['args']); 
     331                        } else { 
     332                                call_user_func(array($model, $task['method'])); 
     333                        } 
     334                        unset($model); 
     335 
     336                        $message = sprintf('Executed cron %s->%s', $task['Model'], $task['method']); 
     337                        $this->log($message, LOG_DEBUG); 
     338                        $this->out($message); 
     339 
     340                        // Reschedule 
     341                        $start = $time + $task['interval']; 
     342                        $this->cron[$start] = $task_name; 
     343                        ksort($this->cron); 
     344                        reset($this->cron); 
     345 
     346                        // Advance time 
     347                        $time = time(); 
     348                } 
     349 
     350                // The time until the next job 
     351                return key($this->cron) - $time; 
    277352        } 
    278353 
     
    288363                $this->out('Commands:'); 
    289364                $this->out("\n\trun\n\t\tRun the worker"); 
     365                $this->out("\n\tstop\n\t\tStop the worker"); 
    290366                $this->out("\n\tstatus\n\t\tShow status of the running worker"); 
    291367                $this->out("\n\thelp\n\t\tShow this help"); 
Note: See TracChangeset for help on using the changeset viewer.