Three models :

  1. User
  2. Membership
  3. PurchasedMembership

How application works

Each membership having starting date and ending date. User can purchase the membership and their information stored into PurchasedMemebership model.

When membership date expire (ending date greater then current date) then count the each membership and store the counted value into total_membership (PurchasedMemebership model field).

I have 3 solutions with issues

  • Do manually like when membership ending date met call the perform_Calculations(request) function.(Doing manually)
  • Increment the total_membership filed when user purchased the membership. Race condition will be occur.
  • When user purchased the membership or view the membership then check ending date and perform the calculation but the issue is that every time user view the membership after ending date it will be performing extra check (if-else).

What i want

  • No performance issues.
  • Best way to solve this problem.
  • How to handle race condition ?
  • How to schedule tasks ?
  • Any django package with no stability issues ?
  • Which of my solution is good and how it can be ?

Django Models

User model store the user information.

class User(models.Model):
      #Django User Model 

This model store the membership details.

class Membership(models.Model):
       title = models.CharField(max_length=100)
       start_date = models.DateTimeField(auto_now_add=True)
       end_date=  models.BooleanField(default=None)
       total_membership =  models.IntegerField(default=0)
       price = models.IntegerField(default=0)   
       PurchasedMembership = models.ManyToManyField(settings.AUTH_USER_MODEL,through='PurchasedMembership',through_fields=('Membership ', 'user'))

This model store the Purchased Membership details.

class PurchasedMembership(models.Model):
        Membership = models.ForeignKey(Membership,on_delete=models.CASCADE) 
        user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete=models.CASCADE, default="")
       joined_date = models.DateTimeField(auto_now_add=True)

       class Meta:
            unique_together = ('Membership ', 'user',)

This method will be invoke to perform some calculations and save them into database.

def perform_Calculations(request):
       #Performing calculations 
1

There are 1 best solutions below

0
On BEST ANSWER

Celery is just what you need when you have tasks that need to be done periodically.

# tasks.py
@app.task
def check_membership_expired():
    # check if current_date >= expired_date

You can schedule this task so it'll be called every hour/night/day.

from celery.schedules import crontab

app.conf.beat_schedule = {
    # Executes every Monday morning at 7:30 a.m.
    'check_membership_expired-every-monday-morning': {
        'task': 'tasks.check_membership_expired',
        'schedule': crontab(hour=7, minute=30, day_of_week=1),
    },
}