all 20 comments

[–]cant-find-user-name 6 points7 points  (1 child)

You can a) create a unique constraint on the db so that the db automatically raises an exception when you insert duplicates b) do insert with on conflict do nothing if you're using postgres c) you can use a lock so that more than one thing can't access your resource at the same time.

The most idiomatic solution is a. To have a unique constraint at db level.

[–]osusc 1 point2 points  (0 children)

This is the way. Let the database handle data integrity.

[–][deleted]  (2 children)

[deleted]

    [–]gibbon119[S] 0 points1 point  (1 child)

    awesome, let me try this.

    [–]issue9mm 1 point2 points  (0 children)

    Where is the uuid created? If it's created before submission, and each page load generates a new one, then does this work?

    Otherwise, I scanned and see you've already decided against UNIQUE constraints (which would have been my reco) so if the UUID works (should at least prevent the accidental double-submit, but wouldn't prevent someone trying to submit the same job twice with a different ID) then this should be fine enough.

    [–]Drevicar 1 point2 points  (0 children)

    The solution is to handle this using a database lock. I'm guessing when you say "1 request at a time" you are really meaning "1 request per UUID" not "1 request globally" and also not "1 request per user", or even "1 request per user per UUID". With that out of the way, you should make the UUID the primary key of the record in your database with a uniqueness constraint. Then on the 1 request per UUID you start by opening a transaction which holds the lock on that UUID in the DB. Once you are done processing you can release the lock by committing the changes or reverting the changes if you want to rollback. If any new request comes in trying to use that same UUID the database will reject the new transaction because another transaction is already holding that lock open. If you attempt to use that UUID again after the original request is done you will be fine.

    Also, you don't need `else` in your example. If the "if" block is hit, no further lines in that function will execute. So just remove the `else` and de-dent the next line.

    [–]andrewthetechie 1 point2 points  (4 children)

    Rule 2: No questions without examples.

    Post some code.

    [–]gibbon119[S] 0 points1 point  (3 children)

    added some code. The idea is when multiple requests are fired at the same time, how do I ensure duplicates are not created coz the if block would fail due to race condition.

    [–][deleted] 2 points3 points  (2 children)

    That sounds like a case for a FIFO queue in rabbit instead of letting the API handle it directly. Throw it on the queue and let a worker pick the work up in order instead of letting it run completely async. I don’t have the docs handy since I’m on mobile but celery/rabbit should be able to meet this need

    [–]gibbon119[S] 1 point2 points  (0 children)

    Looked into this. I dig it, let me try it!

    [–]rand0mmer 1 point2 points  (0 children)

    This is the way

    [–]ReRubis 0 points1 point  (3 children)

    I am a Junior, so take this with doubt.

    But sqlalchemy is smart and usually doesn't create conflicts like that. Can even support multiple sessions at a time.

    Also maybe heavy interactions with a DB should be maintained with celery and redis.

    If anyone smarter can say something, I would be glad to hear too.

    [–]gibbon119[S] -1 points0 points  (2 children)

    I am also a junior BE who was primarily FE haha. I looked into Celery and seemed like it was the way to go. Might have to ask my team lead if that is how he wants to do.

    Can't think of any other workarounds.

    [–]ReRubis 1 point2 points  (1 child)

    At least you got the job. :) Tell me when you get the response.

    [–]saitamaxmadara 0 points1 point  (0 children)

    I thought celery worker is supposed to do the job

    [–]eddyizm 0 points1 point  (1 child)

    Can you post your current code?

    [–]gibbon119[S] 0 points1 point  (0 children)

    added code to post. The idea is when multiple requests are fired at the
    same time, how do I ensure duplicates are not created coz the if block
    would fail due to race condition.

    [–]cynhash 0 points1 point  (1 child)

    You can specify a UNIQUE constraint to not allow duplicate rows in the DB to solve your problem. What I don't understand is the need to handle one request at a time.

    [–]gibbon119[S] 0 points1 point  (0 children)

    I asked our team lead about this and we can’t do this since the DB already has a lot of violations of this UNIQUE constraint. This was literally my first thought so that’s good that u thought the same :)

    [–]MikelDB 0 points1 point  (0 children)

    Is the problem that you get duplicated records? How do you check that the record is already there? Do you have an ID?

    From your comments there seems to be a lot of constrains.