-
Notifications
You must be signed in to change notification settings - Fork 3
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
include download stats #14
base: master
Are you sure you want to change the base?
Conversation
dd70952
to
42394ec
Compare
42394ec
to
8266aa6
Compare
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.
I've reviewed the code and ran local tests. There are a few issues:
-
download_stat
already envisioned:
@NicolasDorier has already implementeddownload_stat
by recording install events:
await conn.InsertEvent("Download", new JObject -
Methods are
[AllowAnonymous]
:
Both methods are[AllowAnonymous]
, making it easy to pump up download stats artificially.
Proposed changes:
-
Add
ip
field toevts
:
And then record only one install per IP by adding anip
field to theevts
table. -
Modify
evts.type
field:
Changeevts.type
tovarchar(16)
- the current field beingtext
is retarded. We can eventually even switch tosmall_int
for faster queries... but we can leave it as is for now. -
Enhance
evts
withplugin_slug
andbuild_id
:
Includeplugin_slug
andbuild_id
in evts to improve event indexing. While we can keep the blob for now (although I’m not a fan), we should reduce the data we write into it. -
Add index on
plugin_slug
,type
,build_id
:
This will improve query performance. -
Add primary key on
evts
table:
We can go with auto-incrementingbigint
for the primary key.
Implementation Steps:
- When the
plugins/{pluginSlug}/versions/{version}/download
endpoint is hit, log the download in theevts
table. If an entry with the sameip
,plugin_slug
,build_id
, andtype
exists, update the timestamp. - Only increment
download_stat
inversions.download_stat
if it’s a fresh insert. - Instead of adding another
JOIN versions
in thePlugins
API query, updateget_latest_versions
andget_all_versions
SQL functions to returndownload_stat
.get_latest_versions
should return the sum of downloads across versions. - Implement an
UninstallPlugin
method inApiController
to log plugin uninstalls inevts
and decrementdownload_stat
for version.
@rockstardev I have pushed requested changed for Proposed changes:, could you take another look? |
} | ||
else if (lastEventType?.ToLower() == "uninstall") | ||
{ | ||
await conn.RecordPluginDownloadStatistics(pluginSlug, "install", version.VersionParts); |
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 is no different from the other branch of the if? what is the intent here?
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.
Based on Rockstar proposed changes:
Only increment download_stat in versions.download_stat if it’s a fresh insert.
A case scenario that played in my head was that:
"If a user install a plugin, the download_stat would increase, and if the user uninstalls the same plugin the stat would reduce.
If the user reinstalls the same plugin, the download stats should pop back up.. "
So what I am trying to achieve on this endpoint is to check if the last event the user (ip) did on that plugin was an uninstall that would mean the user is trying to re-install the plugin. I am then increasing the download_stat by one
} | ||
else if (lastEventType?.ToLower() == "download") | ||
{ | ||
await conn.RecordPluginDownloadStatistics(pluginSlug, "delete", version.VersionParts); |
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.
both branch same?
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.
I have merge the else with the original 'if' for both scenario
|
||
CREATE INDEX idx_evts_plugin_slug ON evts(plugin_slug); | ||
CREATE INDEX idx_evts_type ON evts(type); | ||
CREATE INDEX idx_evts_build_id ON evts(build_id); |
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.
why idx_evts_build_id
and idx_evts_type
are necessary?
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.
Might not be core for now, but should incase we would need to run queries/filtering on the event type it would come a good to have
What do you think?
About data collection
About queriesI am far from convinced that all those requests won't end up blowing up the server when there will be enough data. The indices seems to have been added in a "spread and pray" manner. Alternative proposedCounting stats seems an easy problem but it is surprisingly hard to do it correctly. The simplest solution for counting would be a trigger on If that's the case, I suspect you can't achieve this by your current approach, and you need to use HLL extension in postgres. But in this case, this also open another can of worm where we need to install this extension in our postgres image which isn't really easy at all... All in all, I think we don't need a perfect solution for now. I would just:
Anything more than this would require way too much time to achieve, when there is probably other lower hanging fruits with more impact in front of us. |
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.
I did a quick glance and can already spot a couple of issues:
- You can't modify old migrations; you need to create a new migration to make alterations to the table and those two functions.
GetLastEventTypeForIpAsync
should also check the version, and the way you're handling the insert can be optimized. You could move it below theif
check, or even consolidate everything into a single database call (though that's not a requirement). There definitely shouldn't be separateRecordPluginStatistics
calls... all that goes into one DB query.
There is probably more, I need to look at it with fresh eyes in the morning.
But I am also thinking - since this isn’t urgent, @TChukwuleta, so maybe we can schedule a call to go over the issues and figure out which ones you can work on. I’ll finish my review passes before we loop in @NicolasDorier to take a look at the changes.
OK, only now seeing that @NicolasDorier did his own review with post... I propose we ice work on this PR until we meet over the call to get a consensus on how to move forward. |
Include a download stat column in the version table.
So that on install or uninstall or any plugin the count increases or reduces, and this can be used for analytics and also to measure popular plugins based on most downloaded
Cc. @dennisreimann