]> git.mxchange.org Git - quix0rs-gnu-social.git/commitdiff
Faster NodeInfo stats
authorDiogo Cordeiro <diogo@fc.up.pt>
Mon, 22 Apr 2019 16:22:17 +0000 (17:22 +0100)
committerDiogo Cordeiro <diogo@fc.up.pt>
Mon, 22 Apr 2019 19:03:28 +0000 (20:03 +0100)
plugins/Nodeinfo/NodeinfoPlugin.php
plugins/Nodeinfo/actions/nodeinfo_2_0.php
plugins/Nodeinfo/classes/Usage_stats.php [new file with mode: 0644]
plugins/Nodeinfo/scripts/fix_stats.php [new file with mode: 0755]

index 5c23ac5e577a75fb1bdaef3fd28047c72d9db96c..07a86e93f7fb17673d0251af04695ca1bcce21a3 100644 (file)
@@ -27,13 +27,153 @@ class NodeinfoPlugin extends Plugin
         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)
     {
-        $versions[] = array('name' => 'Nodeinfo',
+        $versions[] = ['name' => 'Nodeinfo',
             'version' => self::VERSION,
             'author' => 'chimo',
             '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;
     }
 }
index bdd83963e6fa324ad76c64c3855780ee4a40fe15..411e5c318f3178a2f4cad55f8ab883219ff3995d 100644 (file)
@@ -97,28 +97,24 @@ class Nodeinfo_2_0Action extends ApiAction
 
     public function getUserCount()
     {
-        $users = new User();
-        $userCount = $users->count();
+        $users = new Usage_stats();
+        $userCount = $users->getUserCount();
 
         return $userCount;
     }
 
     public function getPostCount()
     {
-        $notices = new Notice();
-        $notices->is_local = Notice::LOCAL_PUBLIC;
-        $notices->whereAdd('reply_to IS NULL');
-        $noticeCount = $notices->count();
+        $posts = new Usage_stats();
+        $postCount = $posts->getPostCount();
 
-        return $noticeCount;
+        return $postCount;
     }
 
     public function getCommentCount()
     {
-        $notices = new Notice();
-        $notices->is_local = Notice::LOCAL_PUBLIC;
-        $notices->whereAdd('reply_to IS NOT NULL');
-        $commentCount = $notices->count();
+        $comments = new Usage_stats();
+        $commentCount = $comments->getCommentCount();
 
         return $commentCount;
     }
diff --git a/plugins/Nodeinfo/classes/Usage_stats.php b/plugins/Nodeinfo/classes/Usage_stats.php
new file mode 100644 (file)
index 0000000..fcfc1c8
--- /dev/null
@@ -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);
+    }
+}
diff --git a/plugins/Nodeinfo/scripts/fix_stats.php b/plugins/Nodeinfo/scripts/fix_stats.php
new file mode 100755 (executable)
index 0000000..dadb8e4
--- /dev/null
@@ -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;
+}