During dogfooding, we noticed that two duplicate vacate appeal streams were being created after the JudgeAddressMotionToVacate task was completed. I'm not sure if this was a test data flaw, but this ticket is to check the code and fix this bug.
The PostDecisionMotionUpdater is a good place to start.
I haven't been able to reproduce this bug, but I can see in UAT that it definitely happened (see investigation notes below). I wonder if we want to turn create_motion into a find_or_create_motion in the PostDecisionMotionUpdater, but since the creation timestamps are the same I'm not sure if that would help.
original_appeal=Appeal.find_by(uuid: "180e4e4b-0f52-41e3-8437-c8105e5945d0")
veteran_file_number="700062055" # Test data
as=Appeal.where(veteran_file_number: "700062056")
pp as
# returns 4: 1 original, 2 vacate, and 1 de_novo
# the two vacate streams have the same timestamps
PostDecisionMotion.where(appeal_id: 326)
# Also shows two PostDecisionMotions, one that created the first vacate stream, and one that created the second. Both of them are tied to the same JudgeAddressMotionToVacate task. Both have the same timestamps.
I believe I've reproduced this in the UI, by opening up the Address MTV flow, filling out all the fields, and rapidly clicking on Submit. This causes multiple POST /post_decision_motions calls to get kicked off until one XHR finishes -- but all of them succeed anyway.
The simplest fix is to patch the frontend, so that clicking on Submit disables the button from being re-clicked until the screen changes.
The safer but harder fix is to address the race condition on the backend so that one JudgeAddress task can only spawn one vacatur. Currently these data structures aren't really related (and I'm not sure we want that to be the solution).
Oooh, good sleuthing! We might want to add this front-end improvement to other submit buttons that make a post as well.
Looks like I built in support for it via a prop to MTVJudgeDisposition, but apparently never actually passed that prop in from AddressMotionToVacateView.
So frontend fix for it would be to just add a state var in AddressMotionToVacateView that gets set in handleSubmit and passed to MTVJudgeDisposition.