-
Notifications
You must be signed in to change notification settings - Fork 167
Add automatic cleanup of local storage for saved forms of evaluations #2528
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: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Uh, one important additional aspect here: If we change anything around what local storage entries look like, we have to consider how to migrate. For example, the Maybe we can find a time in the year/semester where we don't have any open evaluations, then we can just migrate at that point, but syncing that with the merge-time could be annoying. Maybe, this is an argument for not changing existing entries, but using a scheme of localstorage entries
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair, I guess wrapping into JSON makes sense. I don't think For migrating, we could check whether an accessed entry follows the JSON scheme we expect, and if not, convert it to that. To be sure about what our entries are, we could also always include a key like Alternatively, I could see that we have a setting that enables the new interface and toggle it in the semester when we think it makes sense. I think I prefer the former though |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,7 @@ | |
|
|
||
| urlpatterns = [ | ||
| path("", views.index, name="index"), | ||
| path("get_end_date", views.get_end_date, name="get_end_date"), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the canonical form I would expect is something like |
||
| path("vote/<int:evaluation_id>", views.vote, name="vote"), | ||
| path("drop/<int:evaluation_id>", views.vote, {"dropout": True}, name="drop"), | ||
| ] | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,6 +16,7 @@ | |
| from django.utils import translation | ||
| from django.utils.translation import get_language | ||
| from django.utils.translation import gettext as _ | ||
| from django.views.decorators.http import require_POST | ||
|
|
||
| from evap.evaluation.auth import participant_required | ||
| from evap.evaluation.models import ( | ||
|
|
@@ -388,3 +389,12 @@ def vote(request: HttpRequest, evaluation_id: int, dropout: bool = False) -> Htt | |
|
|
||
| messages.success(request, _("Your vote was recorded.")) | ||
| return HttpResponse(SUCCESS_MAGIC_STRING) | ||
|
|
||
| @require_POST | ||
| def get_end_date(request): | ||
| evaluation = get_object_or_404(Evaluation, id=request.POST["evaluation_id"]) | ||
|
|
||
| if not evaluation.can_be_voted_for_by(request.user): | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is however the case for evaluations that users have successfully voted for, so PermissionDenied seems a bit off. I think we can relax the restriction here to |
||
| raise PermissionDenied | ||
|
|
||
| return HttpResponse(evaluation.vote_end_date.isoformat()) | ||
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 am not sure that I like the approach here, we are on the one hand forcing every user of localStorage to adhere to the key names given by localStorageConstants, but on the other hand we need to know exactly how the access of each component works internally when trying to figure out how to decode an evaluation id out of a storage key. So we are sharing implementation details in both directions here.
I think we should abstract away the localStorage access behind some interface, and then use this interface wherever we currently access localStorage. Then, an implementation of the interface can handle the expiry. So using this interface could look something like
This will complicate usages though, for example in AutoFormSaver. So let's do something different.
We could instantiate the ExpiringLocalStorage with a fixed expiry time that is used whenever something is inserted using this instance. Then, instantiating one in the student_vote site would use whatever evaluation we are currently looking at, and other uses of localStorage could reuse the interface and use a constant duration into the future or so. Then, our ExpiringStorage would just mimic the interface of localStorage. I think that would be very nice.
One possible way to actually implement this would be to have two entries in the underlying storage like
data_${key}andexpiry_${key}. Of course, this is somewhat less accurate than your current approach in the case that an evaluation end is changed. However, I think that it is probably fine if we set the expiry date to be like 3 months or so after the suspected end.One question that I am not sure about yet is whether such an ExpiringLocalStorage should update the expiry time of its entries when just using
.get(). Both ways have some pros and cons.What do you think? (by the way, using this set-expiry-at-insert-time approach, we would also not need the
get_end_dateview anymore)cc @richardebeling
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.
Hm, this would indeed be way more clean! I think it doesn't hurt to update the expiry when using get.
Before trying to implement this, is there anything else i should consider?
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.
Determining an expiry-date when storing a value seems natural to me, we can use a very pessimistic expiry date that we extend when we update a value, my initial thought would have been to just use "1 year into the future" and not make it evaluation-dependent. Making it evaluation-dependent is also fine with me, but we'll still need buffer time.
I would try to keep it as simple and minimal as possible, in general
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 mean we would still use AutoFormSaver which eagerly deletes localstorage entries once a vote was successfully submitted; any case where the new approach would keep data around for a long time is equivalent to one today where we keep the same data indefinitely.
Agree, I think that adding this feature today with 1 year expiry is a solid improvement, we can think about choosing better dates in a follow up.