Inga 🏳🌈
011afb4818
|
11 months ago | |
---|---|---|
Builder | 13 years ago | |
FLocal.Common | 13 years ago | |
FLocal.IISHandler | 12 years ago | |
FLocal.Migration.Console | 13 years ago | |
FLocal.Migration.Gateway | 13 years ago | |
FLocal.Patcher.Common | 13 years ago | |
FLocal.Patcher.IISHandler | 13 years ago | |
MySQLConnector | 13 years ago | |
Patcher | 13 years ago | |
Patcher.Web | 13 years ago | |
Resources/FLocal | 13 years ago | |
TexCompiler | 13 years ago | |
ThirdParty | 13 years ago | |
Web.Core | 13 years ago | |
Web.IISUploadHandler | 13 years ago | |
.gitignore | 13 years ago | |
FLocal.sln | 13 years ago | |
LICENSE.TXT | 13 years ago | |
README.md | 11 months ago | |
build-all.bat | 13 years ago | |
build-debug.bat | 13 years ago | |
build-release.bat | 13 years ago | |
export-info.bat | 13 years ago |
README.md
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 to connect to PostgreSQL, NConsoler for convenient CLI UI of importing tool, lightly modifiedBBCode parser by PJonDevelopment 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
.
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
; -
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
; example of usage is inPost.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
; example of usage is inThread.cs:getNewPostChanges
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
.
Example of usage: 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.