oncall-engine/engine
Matias Bordese ab700fd4a1
Update OrderedModel serializer not to save previously updated order (#4706)
We are noticing some
[issues](https://ops.grafana-ops.net/goto/sQFLv4XSg?orgId=1) when
updating routes via Terraform because when receiving multiple concurrent
requests updating position, the order is updated in a transaction but it
is then tried to save again in the `.save` call, which could lead to
`IntegrityError`s, because the order may have been updated in a
concurrent request meanwhile.

Test run with the reproduced error (before the serializer update):

```
_____________________________ test_ordered_model_swap_all_to_zero_via_serializer _____________________________

    @pytest.mark.django_db(transaction=True)
    def test_ordered_model_swap_all_to_zero_via_serializer():
        THREADS = 300
        exceptions = []
    
        TestOrderedModel.objects.all().delete()  # clear table
        instances = [TestOrderedModel.objects.create(test_field="test") for _ in range(THREADS)]
    
        # generate random non-unique orders
        random.seed(42)
        positions = [random.randint(0, THREADS - 1) for _ in range(THREADS)]
    
        def update_order_to_zero(idx):
            try:
                instance = instances[idx]
                serializer = TestOrderedModelSerializer(
                    instance, data={"order": 0, "extra_field": idx}, partial=True
                )
                serializer.is_valid(raise_exception=True)
                serializer.save()
                instance.swap(positions[idx])
            except Exception as e:
                exceptions.append(e)
    
        threads = [threading.Thread(target=update_order_to_zero, args=(0,)) for _ in range(THREADS)]
        for thread in threads:
            thread.start()
        for thread in threads:
            thread.join()
    
        # can only check that orders are still sequential and that there are no exceptions
        # can't check the exact order because it changes depending on the order of execution
>       assert not exceptions
E       assert not [IntegrityError(1062, "Duplicate entry 'test-0' for key 'base_testorderedmodel.unique_test_field_order'"), IntegrityEr...rder'"), IntegrityError(1062, "Duplicate entry 'test-0' for key 'base_testorderedmodel.unique_test_field_order'"), ...]

THREADS    = 300
exceptions = [IntegrityError(1062, "Duplicate entry 'test-0' for key 'base_testorderedmodel.unique_test_field_order'"), IntegrityEr...rder'"), IntegrityError(1062, "Duplicate entry 'test-0' for key 'base_testorderedmodel.unique_test_field_order'"), ...]
instances  = [<TestOrderedModel: TestOrderedModel object (841)>, <TestOrderedModel: TestOrderedModel object (842)>, <TestOrderedMod...ject (844)>, <TestOrderedModel: TestOrderedModel object (845)>, <TestOrderedModel: TestOrderedModel object (846)>, ...]
positions  = [57, 12, 140, 125, 114, 71, ...]
thread     = <Thread(Thread-302 (update_order_to_zero), stopped 139636013323840)>
threads    = [<Thread(Thread-3 (update_order_to_zero), stopped 139646722418240)>, <Thread(Thread-4 (update_order_to_zero), stopped ...ate_order_to_zero), stopped 139646608590400)>, <Thread(Thread-8 (update_order_to_zero), stopped 139646600197696)>, ...]
update_order_to_zero = <function test_ordered_model_swap_all_to_zero_via_serializer.<locals>.update_order_to_zero at 0x7f02086274c0>

common/tests/test_ordered_model.py:481: AssertionError
```
2024-07-19 11:56:26 +00:00
..
apps Update regex to jinja route conversion to correctly escape double quotes (#4705) 2024-07-19 11:56:22 +00:00
common Update OrderedModel serializer not to save previously updated order (#4706) 2024-07-19 11:56:26 +00:00
config_integrations Fix docs and UI for connecting Grafana Alerting from other stack (#4243) 2024-04-24 08:02:51 +00:00
engine add exotel call provider (#4433) 2024-06-06 06:19:02 +00:00
settings Add method to send notification bundle by SMS (#4624) 2024-07-16 14:20:16 +00:00
static/images Update resolution note message shortcut instruction (#4482) 2024-06-07 13:54:45 +00:00
type_stubs/icalendar continue addressing mypy violations (#2170) 2023-06-27 10:23:08 +00:00
.dockerignore One startup command to rule them all (#760) 2022-11-07 16:34:43 +01:00
.gitignore modify push notification settings + use fcm-django library (#998) 2022-12-20 12:41:34 +01:00
celery_with_exporter.sh Add flag to debug logs (#912) 2022-11-29 11:16:42 +08:00
conftest.py User notifications bundle (#4457) 2024-07-16 11:24:08 +00:00
Dockerfile bump uwsgi to 2.0.26 + Python to 3.12.3 (#4495) 2024-06-10 15:33:37 -04:00
grpcio-1.64.1-cp312-cp312-linux_aarch64.whl bump uwsgi to 2.0.26 + Python to 3.12.3 (#4495) 2024-06-10 15:33:37 -04:00
manage.py Instrument requests lib (#4008) 2024-03-05 05:22:34 +00:00
pyproject.toml Update out of office task to not retry on HttpError (#4328) 2024-05-09 16:16:46 +00:00
requirements-dev.in bump uwsgi to 2.0.26 + Python to 3.12.3 (#4495) 2024-06-10 15:33:37 -04:00
requirements-dev.txt update sqlparse to address CVE-2024-4340 (#4516) 2024-06-13 09:08:50 -04:00
requirements.in bump uwsgi to 2.0.26 + Python to 3.12.3 (#4495) 2024-06-10 15:33:37 -04:00
requirements.txt Bump zipp from 3.17.0 to 3.19.1 in /engine (#4645) 2024-07-09 22:49:09 +00:00
tox.ini temporarily don't parallelize tests 2024-06-11 11:53:06 -04:00
uwsgi.ini Remove explicit request size limits (#3878) 2024-02-22 15:00:33 +00:00
wait_for_test_mysql_start.sh Revert "Revert "speed up ci builds from 15 to <7 minutes"" (#1643) 2023-03-28 09:34:03 +02:00