From 25afba2f5280c65d28c427e53b10b73ca1bcc9cb Mon Sep 17 00:00:00 2001 From: Yung Han Khoe Date: Mon, 23 Mar 2009 20:54:26 +0000 Subject: [PATCH] Added caching to statistics on Matrix view. --- docs/upgrades/upgrade_7.7.0-7.7.1.pl | 9 ++ lib/WebGUI/Asset/Wobject/Matrix.pm | 143 +++++++++++++++--------- lib/WebGUI/i18n/English/Asset_Matrix.pm | 11 ++ 3 files changed, 108 insertions(+), 55 deletions(-) diff --git a/docs/upgrades/upgrade_7.7.0-7.7.1.pl b/docs/upgrades/upgrade_7.7.0-7.7.1.pl index 743274c68..6ddcce291 100644 --- a/docs/upgrades/upgrade_7.7.0-7.7.1.pl +++ b/docs/upgrades/upgrade_7.7.0-7.7.1.pl @@ -33,6 +33,7 @@ my $session = start(); # this line required # upgrade functions go here addWelcomeMessageTemplateToSettings( $session ); +addStatisticsCacheTimeoutToMatrix( $session ); finish($session); # this line required @@ -44,6 +45,14 @@ sub addWelcomeMessageTemplateToSettings { print "Done.\n" unless $quiet; } +#---------------------------------------------------------------------------- +sub addStatisticsCacheTimeoutToMatrix{ + my $session = shift; + print "\tAdding statisticsCacheTimeout setting to Matrix table... \n" unless $quiet; + $session->db->write("alter table Matrix add statisticsCacheTimeout int(11) not null default 3600"); + print "Done.\n" unless $quiet; +} + #---------------------------------------------------------------------------- # Describe what our function does #sub exampleFunction { diff --git a/lib/WebGUI/Asset/Wobject/Matrix.pm b/lib/WebGUI/Asset/Wobject/Matrix.pm index 03fa36d8b..b23baac70 100644 --- a/lib/WebGUI/Asset/Wobject/Matrix.pm +++ b/lib/WebGUI/Asset/Wobject/Matrix.pm @@ -238,6 +238,14 @@ sub definition { hoverHelp =>$i18n->get('ratings duration description'), label =>$i18n->get('ratings duration label'), }, + statisticsCacheTimeout => { + tab => "display", + fieldType => "interval", + defaultValue => 3600, + uiLevel => 8, + label => $i18n->get("statistics cache timeout label"), + hoverHelp => $i18n->get("statistics cache timeout description") + }, ); push(@{$definition}, { assetName=>$i18n->get('assetName'), @@ -520,6 +528,7 @@ sub view { $self->session->style->setScript($self->session->url->extras('wobject/Matrix/matrix.js'), {type => 'text/javascript'}); + my ($varStatistics,$varStatisticsEncoded); my $var = $self->get; $var->{isLoggedIn} = ($self->session->user->userId ne "1"); $var->{addMatrixListing_url} = $self->getUrl('func=add;class=WebGUI::Asset::MatrixListing'); @@ -527,90 +536,104 @@ sub view { $var->{exportAttributes_url} = $self->getUrl('func=exportAttributes'); $var->{listAttributes_url} = $self->getUrl('func=listAttributes'); $var->{search_url} = $self->getUrl('func=search'); - - # Get the MatrixListing with the most views as an object using getLineage. - my ($bestViews_listing) = @{ $self->getLineage(['descendants'], { + + if ($self->canEdit){ + # Get all the MatrixListings that are still pending. + my @pendingListings = @{ $self->getLineage(['descendants'], { + includeOnlyClasses => ['WebGUI::Asset::MatrixListing'], + orderByClause => "revisionDate asc", + returnObjects => 1, + statusToInclude => ['pending'], + }) }; + foreach my $pendingListing (@pendingListings){ + push (@{ $var->{pending_loop} }, { + url => $pendingListing->getUrl + ."?func=view;revision=".$pendingListing->get('revisionDate'), + name => $pendingListing->get('title'), + }); + } + } + + my $versionTag = WebGUI::VersionTag->getWorking($session, 1); + my $noCache = + $session->var->isAdminOn + || $self->get("statisticsCacheTimeout") <= 10 + || ($versionTag && $versionTag->getId eq $self->get("tagId")); + unless ($noCache) { + $varStatisticsEncoded = WebGUI::Cache->new($session,"matrixStatistics_".$self->getId)->get; + } + + if ($varStatisticsEncoded){ + $varStatistics = JSON->new->decode($varStatisticsEncoded); + } + else{ + # Get the MatrixListing with the most views as an object using getLineage. + my ($bestViews_listing) = @{ $self->getLineage(['descendants'], { includeOnlyClasses => ['WebGUI::Asset::MatrixListing'], joinClass => "WebGUI::Asset::MatrixListing", orderByClause => "views desc", limit => 1, returnObjects => 1, }) }; - if($bestViews_listing){ - $var->{bestViews_url} = $bestViews_listing->getUrl; - $var->{bestViews_count} = $bestViews_listing->get('views'); - $var->{bestViews_name} = $bestViews_listing->get('title'); - $var->{bestViews_sortButton} = "
"; - } + if($bestViews_listing){ + $varStatistics->{bestViews_url} = $bestViews_listing->getUrl; + $varStatistics->{bestViews_count} = $bestViews_listing->get('views'); + $varStatistics->{bestViews_name} = $bestViews_listing->get('title'); + $varStatistics->{bestViews_sortButton} = "
"; + } - # Get the MatrixListing with the most compares as an object using getLineage. + # Get the MatrixListing with the most compares as an object using getLineage. - my ($bestCompares_listing) = @{ $self->getLineage(['descendants'], { + my ($bestCompares_listing) = @{ $self->getLineage(['descendants'], { includeOnlyClasses => ['WebGUI::Asset::MatrixListing'], joinClass => "WebGUI::Asset::MatrixListing", orderByClause => "compares desc", limit => 1, returnObjects => 1, }) }; - if($bestCompares_listing){ - $var->{bestCompares_url} = $bestCompares_listing->getUrl; - $var->{bestCompares_count} = $bestCompares_listing->get('compares'); - $var->{bestCompares_name} = $bestCompares_listing->get('title'); - $var->{bestCompares_sortButton} = "
"; - } + if($bestCompares_listing){ + $varStatistics->{bestCompares_url} = $bestCompares_listing->getUrl; + $varStatistics->{bestCompares_count} = $bestCompares_listing->get('compares'); + $varStatistics->{bestCompares_name} = $bestCompares_listing->get('title'); + $varStatistics->{bestCompares_sortButton} = "
"; + } - # Get the MatrixListing with the most clicks as an object using getLineage. - my ($bestClicks_listing) = @{ $self->getLineage(['descendants'], { + # Get the MatrixListing with the most clicks as an object using getLineage. + my ($bestClicks_listing) = @{ $self->getLineage(['descendants'], { includeOnlyClasses => ['WebGUI::Asset::MatrixListing'], joinClass => "WebGUI::Asset::MatrixListing", orderByClause => "clicks desc", limit => 1, returnObjects => 1, }) }; - if($bestClicks_listing){ - $var->{bestClicks_url} = $bestClicks_listing->getUrl; - $var->{bestClicks_count} = $bestClicks_listing->get('clicks'); - $var->{bestClicks_name} = $bestClicks_listing->get('title'); - $var->{bestClicks_sortButton} = "
"; - } - # Get the 5 MatrixListings that were last updated as objects using getLineage. + if($bestClicks_listing){ + $varStatistics->{bestClicks_url} = $bestClicks_listing->getUrl; + $varStatistics->{bestClicks_count} = $bestClicks_listing->get('clicks'); + $varStatistics->{bestClicks_name} = $bestClicks_listing->get('title'); + $varStatistics->{bestClicks_sortButton} = "
"; + } - my @lastUpdatedListings = @{ $self->getLineage(['descendants'], { + # Get the 5 MatrixListings that were last updated as objects using getLineage. + + my @lastUpdatedListings = @{ $self->getLineage(['descendants'], { includeOnlyClasses => ['WebGUI::Asset::MatrixListing'], joinClass => "WebGUI::Asset::MatrixListing", orderByClause => "lastUpdated desc", limit => 5, returnObjects => 1, }) }; - foreach my $lastUpdatedListing (@lastUpdatedListings){ - push (@{ $var->{last_updated_loop} }, { + foreach my $lastUpdatedListing (@lastUpdatedListings){ + push (@{ $varStatistics->{last_updated_loop} }, { url => $lastUpdatedListing->getUrl, name => $lastUpdatedListing->get('title'), lastUpdated => $self->session->datetime->epochToHuman($lastUpdatedListing->get('lastUpdated'),"%z") }); - } - $var->{lastUpdated_sortButton} = "
"; + } + $var->{lastUpdated_sortButton} = "
"; + # For each category, get the MatrixListings with the best ratings. - # Get all the MatrixListings that are still pending. - - my @pendingListings = @{ $self->getLineage(['descendants'], { - includeOnlyClasses => ['WebGUI::Asset::MatrixListing'], - orderByClause => "revisionDate asc", - returnObjects => 1, - statusToInclude => ['pending'], - }) }; - foreach my $pendingListing (@pendingListings){ - push (@{ $var->{pending_loop} }, { - url => $pendingListing->getUrl - ."?func=view;revision=".$pendingListing->get('revisionDate'), - name => $pendingListing->get('title'), - }); - } - - # For each category, get the MatrixListings with the best ratings. - - foreach my $category (keys %{$self->getCategories}) { + foreach my $category (keys %{$self->getCategories}) { my $data; my $sql = " select @@ -641,7 +664,7 @@ sub view { order by rating.meanValue "; $data = $db->quickHashRef($sql." desc limit 1",[$category,$self->getId]); - push(@{ $var->{best_rating_loop} },{ + push(@{ $varStatistics->{best_rating_loop} },{ url=>'/'.$data->{url}, category=>$category, name=>$data->{productName}, @@ -650,7 +673,7 @@ sub view { count=>$data->{countValue} }); $data = $db->quickHashRef($sql." asc limit 1",[$category,$self->getId]); - push(@{ $var->{worst_rating_loop} },{ + push(@{ $varStatistics->{worst_rating_loop} },{ url=>'/'.$data->{url}, category=>$category, name=>$data->{productName}, @@ -658,9 +681,9 @@ sub view { median=>$data->{medianValue}, count=>$data->{countValue} }); - } + } - $var->{listingCount} = scalar $db->buildArray(" + $varStatistics->{listingCount} = scalar $db->buildArray(" select * from asset, assetData where asset.assetId=assetData.assetId @@ -670,7 +693,17 @@ sub view { and assetData.status='approved' group by asset.assetId", [$self->getId]); - + + $varStatisticsEncoded = JSON->new->encode($varStatistics); + WebGUI::Cache->new($session,"matrixStatistics_".$self->getId)->set( + $varStatisticsEncoded,$self->get("statisticsCacheTimeout") + ); + } + + foreach my $statistic (keys %{$varStatistics}) { + $var->{$statistic} = $varStatistics->{$statistic}; + } + return $self->processTemplate($var, undef, $self->{_viewTemplate}); } diff --git a/lib/WebGUI/i18n/English/Asset_Matrix.pm b/lib/WebGUI/i18n/English/Asset_Matrix.pm index f7ace67ae..a8b5b5bf9 100644 --- a/lib/WebGUI/i18n/English/Asset_Matrix.pm +++ b/lib/WebGUI/i18n/English/Asset_Matrix.pm @@ -427,6 +427,17 @@ listing,|, lastUpdated => 1235681965, }, + 'statistics cache timeout label' => { + message => q|Statistics Cache Timeout|, + lastUpdated => 0, + }, + + 'statistics cache timeout description' => { + message => q|Since all users will see the matrix statistics the same way, we can cache them for some time +to increase performance. How long should we cache them?|, + lastUpdated => 0, + }, + 'rating timeout description' => { message => q|Set a timeout so that users are prevented from rating a given listing too often.|, lastUpdated => 1135271460,