-
Notifications
You must be signed in to change notification settings - Fork 19
Fix duplicate scrobbles by ignoring repeated submissions within 15 seconds #87
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
If #72 is also merged, would have to change the code to not use the |
jesseward
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for these changes @danielfariati
I left a comment about the possibility of using an IMemoryCache that would allow us to expire records after a timeframe. Preventing growth that could lead to complaints from very heavy JF users relating to memory utilization..
This pattern is used elsewhere in JF plugins as well.
|
|
||
| // if the last scrobble for the user is of the same song and happened within 15 seconds, do not scrobble. | ||
| private const long minimumTimeBetweenDuplicateScrobblesInSeconds = 15; | ||
| private readonly Dictionary<string, (string TrackId, long Timestamp)> _lastScrobble = new(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should look at using a Microsoft.Extensions.Caching.Memory here instead. Then Set the key with a Timespan in which it will expire.
The reason is: This plugin sees little updates and maintenance. I want to ensure that little is left behind with its usage. If there are heavy JF (music library) users that don't restart often, they may start to report (very) slow memory growth due to this object filling (unbound) with scrobble records.
Expiring the records after N hours would keep the object trim.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's my first time using C# / .NET, but will take a look at it.
Since we only care about scrobbles in the last 15 seconds, instead of using the "minimumTimeBetweenScrobbles" logic, we could just use the cache with 15 seconds TTL...
If I use the userId / trackId as the key, that would allow me to remove most of the checks in the current implementation.
Will try to make that change, test it and commit it today.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done @jesseward ... Tested with the new logic and it's working as expected.
Also, now I'm not using the timestamp helper method as it is not needed anymore... so this PR not conflict with the other one that is open.
Can you please review once again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, to explain why I use _scrobbleLock even though MemoryCache is already thread-safe... it's to ensure the check-and-set operation for duplicate scrobbles is atomic.
Without the lock, two concurrent requests could both see a cache miss and both set the value, resulting in duplicate scrobbles.
The lock guarantees that only one thread can perform the check-and-set at a time, fully preventing race conditions.
I know this may be overly cautious, but I prefer to be safe rather than sorry (and the operation is very lightweight, so there’s no practical downside, in my opinion).
Fixes #85
What was happening
In certain cases, Jellyfin fires
PlaybackStoppedorUserDataSavedmore than once for the same listening session. Because the plugin triggers a scrobble during those events, two identical scrobbles could be submitted to Last.fm within a very short time window.This results in duplicate plays of the same track on the user’s Last.fm profile.
What this PR changes
A lightweight safeguard has been added to
LastfmApiClientto ignore scrobbles that meet both conditions:This is consistent with Last.fm’s guidelines, which state that clients should not submit multiple scrobbles within such a short interval.
The check ensures correct behavior across both scrobbling paths (default and alternative).
Summary
This PR prevents accidental duplicate scrobbles without affecting normal scrobbling behavior. No configuration changes are required from the user.