Just an initial portion for now fixing incorrect text and preventing future incorrect text. Eventually, I'd like to fix everything still listed under "ignoredWords" in cspell.json.
If a user has started a torrent, the torrent client will cache peers, which the user may then pause and clear those peers out of the peerlist. A user might then start enough torrents to fill their download slots, and then resume the originally paused torrents, allowing them to download more torrents than their slot limits allow. When this happens, we send a failure message and don't send a peerlist. However, because the torrent client already cached peers, it will continue downloading the torrent and sending announces. However, libtorrent clients will continue sending started events until they receive a successful announce without a failure message. The logic in our announce hard codes the peer's uploaded/downloaded values to 0 on any started event. This means that all of the deltas are recorded as 0 until the user completes the torrent, at which point it saves the currently uploaded/downloaded values and only saves the delta once the event is no longer a started event. This PR uses a warning message instead of a failure message, that way the response will be assumed to be successful, but will still provide a message to the client that will show up in the trackers tab, and the client will not continue sending started events.
The peer must be selected while we hold the `WithoutOverlapping()` middleware lock. Previously, the peer was selected beforehand, which caused previous data (single digit seconds sooner) to be used to calculate the delta in the case where a user quickly sent a stopped event right after a completed event. Selecting the peer during the lock means that the data is selected and updated before any other job can process its own delta.
Sometimes, for whatever reason, a user might have more peers than their slot limit. This occurs because we don't ensure every user completes every download they start. This means a user could stop a torrent, clear the slot, and start a new one, and then resume the first one using peers cached by the client. When a user did this, the peer that was stopped would no longer be shown by the tracker and stats weren't affected. When the user completed the torrent, they got a error saying they couldn't send a completed event without first sending a started event. This could only be resolved by restarting the client or pausing/resuming the torrent which would reset the stats for that torrent session. This PR accounts for this fact and will allow peers updates to continue, but the user will no longer be able to receive peers in the peer list, and other users won't receive their peer in the list.
There were very minor edge cases with the previous system that had issues when users paused a torrent immediately after they completed it, causing data to be duplicated. We now opt to use DTOs to transfer the data into the job queue instead of models to prevent the extra database queries caused by passing models into a job queue.
Updating all of a user's peers to either be connectable or unconnectable causes deadlocks when updated at the same time as a bulk peer upsert. We need to combine the peer connectability updates with the regular bulk peer upserts.
phpredis has a different function signature for the redis set command compared to predis. Laravel just passes the arguments directly through to the underlying package.
Only loop through the peers when absolutely needed. Don't loop through more peers after we reach the limit. Do logic before looping instead of inside it.