Skip to content
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

Make user not nullable in DailyXFormSubmissionCounter #900

Merged
merged 7 commits into from Oct 13, 2023

Conversation

LMNTL
Copy link
Contributor

@LMNTL LMNTL commented Oct 12, 2023

Makes the user relation on DailyXFormSubmissionCounter non-nullable, to make it match MonthlyXFormSubmissionCounter.

This fixes issues running logger.0030_backfill_lost_monthly_counters. The migrations aren't squashed so that the schema alterations can be atomic.

@LMNTL LMNTL marked this pull request as draft October 12, 2023 14:40
@LMNTL LMNTL marked this pull request as ready for review October 12, 2023 14:45
Comment on lines 18 to 28
# Associate each daily counter with user=None with a user based on its xform
for counter in DailyXFormSubmissionCounter.objects.filter(user=None).iterator:
if counter.xform and counter.xform.user:
has_duplicate = DailyXFormSubmissionCounter.objects.filter(
date=counter.date, xform=counter.xform
).exclude(user=None).exists()
# don't add a user to duplicate counters, so they get deleted in the next step
if not has_duplicate:
counter.user = counter.xform.user
counter.save()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to use bulk_update() to be more efficient.

Something like that:

    batch = []
    batch_size = 5000 
    for counter in (
        DailyXFormSubmissionCounter.objects.filter(user=None)
        .exclude(xform=None)
        .iterator(chunk_size=batch_size)
    ):
        counter.user = counter.xform.user
        if DailyXFormSubmissionCounter.objects.filter(
            date=counter.date, xform=counter.xform
        ).exclude(user=None).exists():
            continue
        batch.append(counter)
        if len(batch) >= batch_size:
            DailyXFormSubmissionCounter.objects.bulk_update(batch, ['user_id'])
            batch = []
    if batch:
        DailyXFormSubmissionCounter.objects.bulk_update(batch, ['user_id'])

What do you think?

Comment on lines 29 to 31
# Delete daily counters without a user to avoid creating invalid monthly counters
DailyXFormSubmissionCounter.objects.filter(user=None).delete()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if those lines should be present in the 0031 too for users who have already run 0030 on an earlier date.

Example:

  • Upgrade to 2.023.37g (which contains 0030) on Oct 5.
  • Upgrade to 2.023.37h (which contains 0031) on Oct 13.

0030 won't be reapplied and null could have been inserted between both patch releases.

What about adding adding a RunPython in 0031 which would block the migration if null is detected in user_id field? We could provided instruction to rollback to 0029 and upgrade to 0031. Otherwise, it would apply without any message.

Copy link
Contributor Author

@LMNTL LMNTL Oct 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's a very good point. I refactored 0030 to delete the daily counters and then repopulate the monthly counters, as well as creating a new 0031 migration that just deletes daily counters. The previous 0031 migration that alters the schema is now 0032.

This covers the edge case where a user upgraded to 2.023.37g on the same date as they upgrade to 2.023.37h. (Also, it means one less manual step needed to deploy.)

@noliveleger noliveleger self-assigned this Oct 13, 2023
@noliveleger noliveleger merged commit 42f9545 into release/2.023.37 Oct 13, 2023
1 check was pending
@noliveleger noliveleger deleted the daily-counters-user-null branch October 13, 2023 19:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants