-
Notifications
You must be signed in to change notification settings - Fork 0
Quota representation and behavior in model layer #41
Conversation
dkc/core/models/user_quota.py
Outdated
|
||
# The user is needed to stringify, so join it when directly querying for a quota | ||
objects = SelectRelatedManager('user') | ||
|
||
def __str__(self): | ||
return f'Quota for <{self.user}>; {self.allocation} bytes' |
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'm worried this might actually be a little long. Have you seen it rendered somewhere in the admin page yet?
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 doesn't currently appear on the admin page. I may just strip some of these things out for now and let us deal with the admin page later. I'll probably also remove the SelectRelatedManager as I don't even think we'll query the quota tables directly, but rather always through FK lookups.
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.
Finished my initial review. See inline comments.
c9af758
to
9fe47f6
Compare
PTAL, I've force pushed a new initial commit intended to capture the data modeling and quota resolving behavior. The approach as written is:
This approach means that we will need to specially handle when an admin user flips a folder quota from null to non-null, by transferring the used amount from the owning user's pile to the folder's custom allotment. In that case it's just a matter of subtracting from the user's |
9fe47f6
to
92a9887
Compare
I went ahead and stuck rudimentary quota accounting, as well as enforcement, on this branch. |
04a3c93
to
62a8f61
Compare
dkc/core/models/folder.py
Outdated
f'{user_quota.used}B > {user_quota.allowed}B.' | ||
) | ||
elif amount > 0: | ||
folder_quota.refresh_from_db() |
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.
Please advise on best practices here -- because I'm using an F
expression, refresh_from_db
needs to be called before the updated attributes will have their normally-typed values. I chose to only call refresh_from_db
internally here if it's strictly necessary, for the sake of performance, but callers of this function would then have to be concerned with refreshing the objects themselves if they need to use these properties again (which they probably won't).
instance.size = instance.blob.size | ||
|
||
if not instance.pk: # this is a new file; reserve quota | ||
instance.folder.increment_quota(instance.size) |
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.
This is a temporary place for incrementing the quota. Ultimately we'll want to do that when they first initiate an upload, before any bytes get stored anywhere.
62a8f61
to
4ab79ec
Compare
This provides a workable interface for controlling system quotas.
4ab79ec
to
979ba68
Compare
This now has all the quota features we need for a MVP. The branch is ready for final review, however we shouldn't merge it until we solve one problem that it introduces. This branch adds a new constraint: all folders must have an owning user. I like this constraint and want to keep it. However, since we don't currently have user authentication, the process of assigning an owner to a newly created folder doesn't exist. As such, on this branch right now, it's impossible to create folders via the REST API. Two paths forward would be:
|
Now, when a folder is granted its own specific quota, its usage is subtracted from its owners pool.
e30f6c1
to
c44c59c
Compare
* Use different db create method * Use SelfAttribute in factory Co-authored-by: Brian Helba <brian.helba@kitware.com>
1263fe2
to
44efd30
Compare
7a29107
to
7ce76c6
Compare
Good news... I've worked around the lack of authentication in the REST API for now. This is ready to merge! |
The scope of this PR is just to add the database representation of quotas, not to actually add behavior to enforce them.
I went with the existing strategy, and the one that seems to be recommended in Django land, of using a OneToOneField to effectively attach columns to user rows, but using a separate relation. The performance implications, as far as I can guess, are negligible in both directions simply due to how we use quotas. However, there are other tradeoffs that merit consideration:
Pros:
Cons:
FWIW I'm fine with the approach here, I just want us to make an informed decision. We're taking on a little bit of debt in this approach by forcing our app layer to have more consistency checks.