The NNTP code hasn't received much attention in quite a while, though that's starting to change. It's still pretty crufty.
The NNTP code uses a state machine to send commands to the NNTP server, and to parse the responses. The states are enumerated here
We cache NNTP connections, though it's much simpler than what we do for IMAP. It's simpler partly because we only fetch messages from the server, as opposed to keeping track of state on the server like we do for IMAP, so we don't tend to run nearly as many NNTP urls.
We keep track of the read state of messages in per-server .newsrc format files, though the name of the file is not .newsrc, but rather the <server name>.rc. This was originally done because it's the "standard" way of doing this, and in theory we can share .newsrc file with other apps. I doubt this ever happens, and it causes some issues because we also keep track of read state in the .msf file, and we also keep track of total and unread counts in the .msf file, and counts for threads. Any time you store the same information in multiple ways, you have issues when the information isn't kept in sync. The principle we abide by is that in the case of conflicts, the .newsrc file "wins". Each .msf file stores a copy of the .newsrc line for that newsgroup, and if it doesn't match the actual line in the .newsrc, we try to resync.
The other source of discrepancies is that the db keeps track of actual headers it has stored locally, which usually doesn't match the count of messages on the server. The user may have only downloaded newer headers, or turned on retention settings (e.g., only keep the last 100 messages), or there may be gaps in the article numbers.
nsNNTPNewsgroupList.cpp is used when downloading headers for a newsgroup from the server. It figures out which headers need to be downloaded based on which have already been downloaded. It parses the XOVER response and turns into a msg hdr to put in the .msf file.