2017-11-28, 02:52 AM
Can you please add performance and security thread prefixes?
PHP arrays aren't really arrays, they're a weird mix of lists and maps, but I'll call them that since that's the usual terminology.
The current system involves storing every banned user every in a forum in a giant array, serializing it, and storing it in memcached (or the datacache table, if you don't have a cache setup). MyBB will load this giant string on every page-load for users, attempts to deserialize it into a giant array, looks the current user up in this giant array, retrieves the cached ban table row from it, and checks if they have a live ban.
This process is extremely, extremely inefficient and will get slower and slower as the number of banned users on your forum increases, particularly on big boards. In fact, I discovered this issue thanks to a big board owner who ran into performance problems with a different cache and pointed this one out to me as another potential issue.
The first solution to the problem is one which I've already implemented locally, minus the upgrader portions.
It consists of adding a banExpiry column to the users table. 0 would signify that you aren't banned, -1 would represent a permanent ban, and anything over 0 would represent the date the user's ban expires on.
Edit: Option b was terrible in hindsight, so removed.
Edit 2: Ah wait, users are loaded on requests with a join to the groups table, duh. Okay, good idea.
I also looked into an alternate solution, as Euan kindly reminded me that the first solution would lead to a length upgrade process.
The alternate solution involves the ban cache being removed entirely and bans being managed entirely by the task system.
Once every fifteen minutes, the task system would go through all the bans which have expired and restore the user's original groups. It is extremely unlikely that an admin would issue a ban shorter than an hour and we don't really need a high degree of accuracy for ban expiries.
PHP arrays aren't really arrays, they're a weird mix of lists and maps, but I'll call them that since that's the usual terminology.
The current system involves storing every banned user every in a forum in a giant array, serializing it, and storing it in memcached (or the datacache table, if you don't have a cache setup). MyBB will load this giant string on every page-load for users, attempts to deserialize it into a giant array, looks the current user up in this giant array, retrieves the cached ban table row from it, and checks if they have a live ban.
This process is extremely, extremely inefficient and will get slower and slower as the number of banned users on your forum increases, particularly on big boards. In fact, I discovered this issue thanks to a big board owner who ran into performance problems with a different cache and pointed this one out to me as another potential issue.
The first solution to the problem is one which I've already implemented locally, minus the upgrader portions.
It consists of adding a banExpiry column to the users table. 0 would signify that you aren't banned, -1 would represent a permanent ban, and anything over 0 would represent the date the user's ban expires on.
Edit: Option b was terrible in hindsight, so removed.
Edit 2: Ah wait, users are loaded on requests with a join to the groups table, duh. Okay, good idea.
I also looked into an alternate solution, as Euan kindly reminded me that the first solution would lead to a length upgrade process.
The alternate solution involves the ban cache being removed entirely and bans being managed entirely by the task system.
Once every fifteen minutes, the task system would go through all the bans which have expired and restore the user's original groups. It is extremely unlikely that an admin would issue a ban shorter than an hour and we don't really need a high degree of accuracy for ban expiries.