Feed entries became unread on updating to PHP 8.1

  • [ ] I’m using stock docker compose setup, unmodified.
  • [ ] I’m using docker compose setup, with modifications (modified .yml files, third party plugins/themes, etc.) - if so, describe your modifications in your post. Before reporting, see if your issue can be reproduced on the unmodified setup.
  • [x] I’m not using docker on my primary instance, but my issue can be reproduced on the aforementioned docker setup and/or official demo.

This is a relatively minor issue, but I’m making this post in case my diagnosis is useful to someone else.

On updating my tt-rss instance to PHP 8.1, entries in my feeds became unread (that were previously marked as read).

  • Tiny Tiny RSS version (including git commit id): v22.09-d47b8c849
  • Platform (i.e. Linux distro, Docker, PHP, PostgreSQL, etc) versions: Ubuntu 22.04, PHP 8.1, MariaDB 10.6

I initially didn’t know it was the PHP update, as I updated several components at once but I narrowed it down to an inconsistency generating the guid in ttrss_entries.

Notice the difference between these two rows:

+------------------------------------------+----------------------------------------------------------------------------+
| content_hash                             | guid                                                                       |
+------------------------------------------+----------------------------------------------------------------------------+
| 2691d5ef1110f053a4951636f31dc89f366b8f2d | {"ver":2,"uid":"2","hash":"SHA1:c1d2277bc203467347b3aedca37266ecee07b2f1"} |
| 2691d5ef1110f053a4951636f31dc89f366b8f2d | {"ver":2,"uid":2,"hash":"SHA1:c1d2277bc203467347b3aedca37266ecee07b2f1"}   |

The first row is the old entry, with a string uid, while the second has an integer uid.

The uid comes from owner_uid, an int column straight out the database: https://dev.tt-rss.org/fox/tt-rss/src/commit/42bc1620b8deda73b96b2e0029c6de79daa5ccca/classes/rssutils.php#L681

In PHP 8.1, the MySQL driver has the following backwards incompatible change:

Integers and floats in result sets will now be returned using native PHP types instead of strings when using emulated prepared statements. This matches the behavior of native prepared statements. The previous behaviour can be restored by enabling the PDO::ATTR_STRINGIFY_FETCHES option.

hxxps://www.php.net/manual/en/migration81.incompatible.php#migration81.incompatible.pdo.mysql

With some minor tweaking to the docker compose setup (to use MySQL instead of PostgreSQL), I can reproduce this with a simple test:

test script:

<?php

$db = new PDO(getenv('TTRSS_DB_TYPE') . ":dbname=" . getenv('TTRSS_DB_NAME') . ";host=" . getenv('TTRSS_DB_HOST'), getenv('TTRSS_DB_USER'), getenv('TTRSS_DB_PASS'));
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $db->prepare('select 1');
$stmt->execute();
var_dump($stmt->fetch(PDO::FETCH_ASSOC));

checkout ttrss-docker-compose using PHP 8, I chose 4ae13e8900bcf920cb0bdd873eb2d0c5b361052a

Configure with mariadb and launch (apk add php8-pdo_mysql)

$ docker cp test.php ttrss-docker_updater_1:/
$ docker exec -it ttrss-docker_updater_1 /bin/sh
/ # php8 /test.php 
array(1) {
  [1]=>
  string(1) "1"
}

Then checkout the latest ttrss-docker-compose (which uses PHP 8.1) 426ed93214020b26eabf3465b308c31dbffb77b6

configure and launch (apk add php81-pdo_mysql)

$ docker cp test.php ttrss-docker_updater_1:/
$ docker exec -it ttrss-docker_updater_1 /bin/sh
/ # php81 /test.php 
array(1) {
  [1]=>
  int(1)
}

My proposed fix is to have a migration script ensure all uid entries are integers. Though it will cause a bit of mess due to the UNIQUE constraint.

my proposed fix is using an actually supported database instead of clinging to mysql.

If MySQL is indeed unsupported (last I heard, it was “maintenance only”) then I suggest making that more explicit in the documentation and code.

As I have many years experience using and administering MySQL databases it was the obvious choice, given I’m prepared to get my hands dirty if required.

Anyway, I’m just posting this out there to inform the community of my experience.

<snarky-response>Maybe use a better language rather than clinging on to PHP</snarky-response>

anything but stock docker setup (which uses postgres) is not supported.

:man_facepalming: