Faster NodeInfo stats

This commit is contained in:
Diogo Cordeiro 2019-04-22 17:22:17 +01:00
parent e186ad57d0
commit 586fb5a517
4 changed files with 339 additions and 13 deletions

View File

@ -27,13 +27,153 @@ class NodeinfoPlugin extends Plugin
return true; return true;
} }
/**
* Make sure necessary tables are filled out.
*
* @return boolean hook true
*/
public function onCheckSchema()
{
// Ensure schema
$schema = Schema::get();
$schema->ensureTable('usage_stats', Usage_stats::schemaDef());
// Ensure default rows
if (Usage_stats::getKV('type', 'users') == null) {
$us = new Usage_stats();
$us->type = 'users';
$us->insert();
}
if (Usage_stats::getKV('type', 'posts') == null) {
$us = new Usage_stats();
$us->type = 'posts';
$us->insert();
}
if (Usage_stats::getKV('type', 'comments') == null) {
$us = new Usage_stats();
$us->type = 'comments';
$us->insert();
}
return true;
}
/**
* Increment notices/replies counter
*
* @return boolean hook flag
* @author Diogo Cordeiro <diogo@fc.up.pt>
*/
public function onStartNoticeDistribute($notice)
{
assert($notice->id > 0); // Ignore if not a valid notice
$profile = $notice->getProfile();
if (!$profile->isLocal()) {
return true;
}
// Ignore for activity/non-post-verb notices
if (method_exists('ActivityUtils', 'compareVerbs')) {
$is_post_verb = ActivityUtils::compareVerbs(
$notice->verb,
[ActivityVerb::POST]
);
} else {
$is_post_verb = ($notice->verb == ActivityVerb::POST ? true : false);
}
if ($notice->source == 'activity' || !$is_post_verb) {
return true;
}
// Is a reply?
if ($notice->reply_to) {
$us = Usage_stats::getKV('type', 'comments');
$us->count += 1;
$us->update();
return true;
}
// Is an Announce?
if ($notice->isRepeat()) {
return true;
}
$us = Usage_stats::getKV('type', 'posts');
$us->count += 1;
$us->update();
// That was it
return true;
}
/**
* Decrement notices/replies counter
*
* @return boolean hook flag
* @author Diogo Cordeiro <diogo@fc.up.pt>
*/
public function onStartDeleteOwnNotice($user, $notice)
{
$profile = $user->getProfile();
// Only count local notices
if (!$profile->isLocal()) {
return true;
}
if ($notice->reply_to) {
$us = Usage_stats::getKV('type', 'comments');
$us->count -= 1;
$us->update();
return true;
}
$us = Usage_stats::getKV('type', 'posts');
$us->count -= 1;
$us->update();
return true;
}
/**
* Increment users counter
*
* @return boolean hook flag
* @author Diogo Cordeiro <diogo@fc.up.pt>
*/
public function onEndRegistrationTry()
{
$us = Usage_stats::getKV('type', 'users');
$us->count += 1;
$us->update();
return true;
}
/**
* Decrement users counter
*
* @return boolean hook flag
* @author Diogo Cordeiro <diogo@fc.up.pt>
*/
public function onEndDeleteUser()
{
$us = Usage_stats::getKV('type', 'users');
$us->count -= 1;
$us->update();
return true;
}
public function onPluginVersion(array &$versions) public function onPluginVersion(array &$versions)
{ {
$versions[] = array('name' => 'Nodeinfo', $versions[] = ['name' => 'Nodeinfo',
'version' => self::VERSION, 'version' => self::VERSION,
'author' => 'chimo', 'author' => 'chimo',
'homepage' => 'https://github.com/chimo/gs-nodeinfo', 'homepage' => 'https://github.com/chimo/gs-nodeinfo',
'description' => _m('Plugin that presents basic instance information using the NodeInfo standard.')); 'description' => _m('Plugin that presents basic instance information using the NodeInfo standard.')];
return true; return true;
} }
} }

View File

@ -97,28 +97,24 @@ class Nodeinfo_2_0Action extends ApiAction
public function getUserCount() public function getUserCount()
{ {
$users = new User(); $users = new Usage_stats();
$userCount = $users->count(); $userCount = $users->getUserCount();
return $userCount; return $userCount;
} }
public function getPostCount() public function getPostCount()
{ {
$notices = new Notice(); $posts = new Usage_stats();
$notices->is_local = Notice::LOCAL_PUBLIC; $postCount = $posts->getPostCount();
$notices->whereAdd('reply_to IS NULL');
$noticeCount = $notices->count();
return $noticeCount; return $postCount;
} }
public function getCommentCount() public function getCommentCount()
{ {
$notices = new Notice(); $comments = new Usage_stats();
$notices->is_local = Notice::LOCAL_PUBLIC; $commentCount = $comments->getCommentCount();
$notices->whereAdd('reply_to IS NOT NULL');
$commentCount = $notices->count();
return $commentCount; return $commentCount;
} }

View File

@ -0,0 +1,73 @@
<?php
/**
* GNU social - a federating social network
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
if (!defined('GNUSOCIAL')) {
exit(1);
}
/**
* Table Definition for Usage_stats
*/
class Usage_stats extends Managed_DataObject
{
###START_AUTOCODE
/* the code below is auto generated do not remove the above tag */
public $__table = 'usage_stats'; // table name
public $type; // varchar(191) unique_key not 255 because utf8mb4 takes more space
public $count; // int(4)
public $modified; // timestamp() not_null default_CURRENT_TIMESTAMP
/* the code above is auto generated do not remove the tag below */
###END_AUTOCODE
public static function schemaDef()
{
return [
'description' => 'node stats',
'fields' => [
'type' => ['type' => 'varchar', 'length' => 191, 'description' => 'Type of countable entity'],
'count' => ['type' => 'int', 'size' => 'int', 'default' => 0, 'description' => 'Number of entities of this type'],
'modified' => ['type' => 'datetime', 'not null' => true, 'default' => 'CURRENT_TIMESTAMP', 'description' => 'date this record was modified'],
],
'primary key' => ['type'],
'unique keys' => [
'usage_stats_key' => ['type'],
],
'indexes' => [
'user_stats_idx' => ['type'],
],
];
}
public function getUserCount()
{
return intval(Usage_stats::getKV('type', 'users')->count);
}
public function getPostCount()
{
return intval(Usage_stats::getKV('type', 'posts')->count);
}
public function getCommentCount()
{
return intval(Usage_stats::getKV('type', 'comments')->count);
}
}

View File

@ -0,0 +1,117 @@
#!/usr/bin/env php
<?php
/**
* GNU social - a federating social network
*
* LICENCE: This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* @category Plugin
* @package GNUsocial
* @copyright 2018 Free Software Foundation http://fsf.org
* @license http://www.fsf.org/licensing/licenses/agpl-3.0.html GNU Affero General Public License version 3.0
* @link https://www.gnu.org/software/social/
*/
define('INSTALLDIR', realpath(__DIR__ . '/../../..'));
$longoptions = ['type='];
$helptext = <<<END_OF_HELP
fix_stats.php [options]
Counts the stats from database values and updates the table.
--type Optional flag to specify the type to update. They all are updated by default.
Type: can be 'users', 'posts' or 'comments'. Or 'all', to update all the types.
END_OF_HELP;
require_once INSTALLDIR . '/scripts/commandline.inc';
$valid_types = ['all', 'users', 'posts', 'comments'];
$verbose = have_option('v', 'verbose');
$type_to_fix = get_option_value('type');
if (!in_array($type_to_fix, $valid_types)) {
echo "You must provide a valid type!\n\n";
show_help();
exit(1);
}
if ($verbose) {
echo "Started.\n\n";
}
if ($type_to_fix == 'all' || $type_to_fix == 'users') {
if ($verbose) {
echo "[+] Updating Users stats...\n";
}
$us = Usage_stats::getKV('users');
$us->count = getUserCount();
$us->update();
}
if ($type_to_fix == 'all' || $type_to_fix == 'posts') {
if ($verbose) {
echo "[+] Updating Posts stats...\n";
}
$us = Usage_stats::getKV('posts');
$us->count = getPostCount();
$us->update();
}
if ($type_to_fix == 'all' || $type_to_fix == 'comments') {
if ($verbose) {
echo "[+] Updating Comments stats...\n";
}
$us = Usage_stats::getKV('comments');
$us->count = getCommentCount();
$us->update();
}
if ($verbose) {
echo "\nDONE.\n";
}
/*
* Counting functions
*/
function getUserCount()
{
$users = new User();
$userCount = $users->count();
return $userCount;
}
function getPostCount()
{
$notices = new Notice();
$notices->is_local = Notice::LOCAL_PUBLIC;
$notices->whereAdd('reply_to IS NULL');
$noticeCount = $notices->count();
return $noticeCount;
}
function getCommentCount()
{
$notices = new Notice();
$notices->is_local = Notice::LOCAL_PUBLIC;
$notices->whereAdd('reply_to IS NOT NULL');
$commentCount = $notices->count();
return $commentCount;
}