From 011afb4818628a63897fb6bbac4ff441fe3edfc7 Mon Sep 17 00:00:00 2001 From: Inga Date: Mon, 6 Nov 2023 03:25:28 +0100 Subject: [PATCH] added readme --- README.md | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..b280176 --- /dev/null +++ b/README.md @@ -0,0 +1,137 @@ +# FLocal + +## Motivation + +This is a fully functional alternative to UBB.threads, +complete with capability of migration from UBB.threads. + +First working release implemented in summer 2010, +with occasional additional features added from time to time over the next two years. + +## Features + +It is highly performant, compared to UBB.threads: +on a mid-range rental server in 2010 (dual-core Nehalem CPU, 8GB RAM, 32-bit PostgreSQL, 7200 RPM HDD) +with over 10 million posts in the database, +it handles 1000 simple requests per second with ease, with response time under `DateTime`'s 16ms precision. + +In addition to most features of stock UBB.threads, it also supports +advanced features that were implemented by fbgz.xyz into their custom UBB.threads codebase: + +* Layers (normal, offtopic, garbage), with every post having a layer, + with moderators being able to limit max layer for every user's posts by moderating actions, + and visibility of layers configurable by every user on per-board basis; +* Moderation "strikes" (one notice in a specific board is worth one point; one warning, three points; + notices and warnings have expiration dates; total weight of over 9 or 27 points limits max layer + for posts of that user in that board); +* Threads can be locked (so that nobody except administrators can post in them); +* Default UI of fbgz.xyz (heavily patched over UBB.threads default); +* "Light" UI for extremely low-traffic surfing (minimal HTML, almost no JS, + no automatic display of uploaded files); +* Non-standard colors for usernames of some users (by request); +* Themes and smileys from fbgz.xyz; +* New users registration is only allowed from configurable allowlist of specific subnets; +* etc + +and some additional features never implemented by fbgz.xyz: + +* Ability to list public uploaded files in order (only for logged-in users); +* Ability for users to retroactively limit the visibility of all their posts to logged-in users or to nobody at all; +* Hotlinking for uploaded images is blocked; they can only be viewed when embedded in local posts; +* "Modern" UI in Metro-style (resembling Zune UI); +* RSS (as yet another UI variant); +* Raw XML (as yet another UI variant), for programmatic access by custom user-created applications, + kind of like an API; +* Private messages are grouped in threads by user; +* Instead of "Zone" board (where thread author is a thread moderator), there are "Zone" subboards per user; +* LaTeX support in posts; +* Typographic improvements (e.g. double minus is replaced by mdash); +* Threads are never "archived" (because, as opposed to fbgz.xyz, there are no performance reasons to do so), + even unpinned threads with last posts over two months old can still be replied to + (but old posts feature a slowpoke icon for actions, so that it's clear that they're old); +* Last read post in thread is always tracked + (as opposed to UBB.threads always marking any thread not visited for over seven days as fully read); +* A page listing all posts replying to or mentioning any specific user + (as opposed to listing only posts replying to that user); +* A page listing all threads by a specific user; +* Machichara similar to the ones featured on japanese cell phones; +* Coexistence of imported posts with the new posts; + regular importing of new posts from UBB.threads instance without conflicts + with the posts originally created on the new software + (imported posts always get lower IDs regardless of their date, so they're always displayed below); +* Multi-language support (at the moment, only Russian and English are supported); +* etc. + +## Technical details + +This is mostly a C# 3.5 application, running in IIS 7.5 as a managed IIS module. +Only one instance is running at a time, which allows to do aggressive caching of DB entries +(especially considering that there is no 64-bit PostgreSQL on Windows, so PostgreSQL is limited to 2GB RAM). + +It is currently running on Windows Server 2008 R2 Web Edition x64 with PostgreSQL 8.4, +on a Hetzner box with 8GB RAM and 320GB 7200RPM HDD. + +This is written completely from scratch; +the only third-party libraries used are .NET Framework 3.5, +[Npgsql](https://github.com/npgsql/npgsql) to connect to PostgreSQL, +[NConsoler](https://github.com/csharpus/nconsoler) for convenient CLI UI of importing tool, +lightly modified[BBCode parser by PJonDevelopment](http://pjondevelopment.50webs.com/articles/bbcodeParser.html) +as a base library for BBCode (I implemented support for specific tags), +and .NET Framework stock XSLT processing library. + +This project is 25k LOC of C# code, and 15k LOC of XSLT files (for all supported designs). + +## Technical solutions + +Key highlights: + +### UI + +Implemented via pluggable XSLT template sets in [`Resources/FLocal/templates`](Resources/FLocal/templates). + +At the moment, only four template sets are implemented: + +* Classic: the default one from fbgz.xyz, supporting all its themes; +* Lite: inspired by the lite UI from fbgz.xyz, but even more efficient traffic-wise; +* Modern: created from scratch, inspired by look of Metro UIs (such as the one in Zune), with tiles and stuff; +* RSS: created from scratch, allows subscribing to basically any page + (board, thread, posts of a specific user, mentions of a specific user, you name it); +* Not technically a template set: raw XML, unprocessed by XSLT, for programmatic usage by third-party clients + (e.g. can be used to implement a smartphone app). + +### DB + +I implemented my own ORM here, with the following features: + +* (SQL) DB-agnostic, all postgres-specific quirks are implemented + in a separate [`PostgresDBTraits.cs`](MySQLConnector/PostgresDBTraits.cs); +* Agressive caching of all entries fetched from DB; + since only one instance of the application is supposed to be running at a time, and only on one server, + we can assume that the data in DB is never changed unless application changed it, + so we can safely cache everything, and only invalidate specific entries when we ourselves update them. + This also means that for every entry in db fetched to the application, only one unique object exists in RAM. + + Implementation is in [`Registry.cs`](Web.Core/Registry.cs); + example of usage is in [`Post.cs`](FLocal.Common/dataobjects/Post.cs). +* Bundling of all DB changes into one complex changeset + (supporting incrementing values or referring to the newly inserted rows), + executed in one go without any additional business logic slowing it down, + ensuring quick transactions and reducing the possibility of conflicts. + Implementation is in [`ChangeSet.cs`](ChangeSet.cs); + example of usage is in [`Thread.cs:getNewPostChanges`](FLocal.Common/dataobjects/Thread.cs) for a new reply. + + Additionally, changeset executor reorders changes to conform to the ideal table locking order, + and if that's not possible, locks the required tables early, ensuring that there will be no deadlocks. + +### DB patching + +There is a separate service intended to keep DB schema up-to-date and to install the latest patches only once, +and to revert them if needed: [`Updater.cs`](Patcher/Updater.cs). + +Example of usage: [`Patch_00002_mentions.xml`](FLocal.Patcher.Common/Resources/Patch_00002_mentions.xml). + +### Installation + +All builds are packaged as MSI installer files; +it is enough to run a new MSI file on the server to update to a new version +that will automatically handle all new requests.