We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
It's possible to create a FollowRequest for a Follow that already exists
Send a follow request.
User accepts.
Send a second follow request (eg. using an old tab)

Because requests and follows are stored in separate tables it's not possible to enforce this with a constraint. Pre-checking would leave a race condition, so I guess we either need to mess with table locks or create the follow request, and then delete it if its unneeded. Can we enforce this in the pre save of the model, perhaps?

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `bookwyrm/models/relationship.py`
Content:
```
1 ''' defines relationships between users '''
2 from django.db import models
3 
4 from bookwyrm import activitypub
5 from .base_model import ActivitypubMixin, ActivityMapping, BookWyrmModel
6 
7 
8 class UserRelationship(ActivitypubMixin, BookWyrmModel):
9     ''' many-to-many through table for followers '''
10     user_subject = models.ForeignKey(
11         'User',
12         on_delete=models.PROTECT,
13         related_name='%(class)s_user_subject'
14     )
15     user_object = models.ForeignKey(
16         'User',
17         on_delete=models.PROTECT,
18         related_name='%(class)s_user_object'
19     )
20 
21     class Meta:
22         ''' relationships should be unique '''
23         abstract = True
24         constraints = [
25             models.UniqueConstraint(
26                 fields=['user_subject', 'user_object'],
27                 name='%(class)s_unique'
28             ),
29             models.CheckConstraint(
30                 check=~models.Q(user_subject=models.F('user_object')),
31                 name='%(class)s_no_self'
32             )
33         ]
34 
35     activity_mappings = [
36         ActivityMapping('id', 'remote_id'),
37         ActivityMapping('actor', 'user_subject'),
38         ActivityMapping('object', 'user_object'),
39     ]
40     activity_serializer = activitypub.Follow
41 
42     def get_remote_id(self, status=None):
43         ''' use shelf identifier in remote_id '''
44         status = status or 'follows'
45         base_path = self.user_subject.remote_id
46         return '%s#%s/%d' % (base_path, status, self.id)
47 
48 
49     def to_accept_activity(self):
50         ''' generate an Accept for this follow request '''
51         return activitypub.Accept(
52             id=self.get_remote_id(status='accepts'),
53             actor=self.user_object.remote_id,
54             object=self.to_activity()
55         ).serialize()
56 
57 
58     def to_reject_activity(self):
59         ''' generate an Accept for this follow request '''
60         return activitypub.Reject(
61             id=self.get_remote_id(status='rejects'),
62             actor=self.user_object.remote_id,
63             object=self.to_activity()
64         ).serialize()
65 
66 
67 class UserFollows(UserRelationship):
68     ''' Following a user '''
69     status = 'follows'
70 
71     @classmethod
72     def from_request(cls, follow_request):
73         ''' converts a follow request into a follow relationship '''
74         return cls(
75             user_subject=follow_request.user_subject,
76             user_object=follow_request.user_object,
77             remote_id=follow_request.remote_id,
78         )
79 
80 
81 class UserFollowRequest(UserRelationship):
82     ''' following a user requires manual or automatic confirmation '''
83     status = 'follow_request'
84 
85 
86 class UserBlocks(UserRelationship):
87     ''' prevent another user from following you and seeing your posts '''
88     # TODO: not implemented
89     status = 'blocks'
90
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/bookwyrm/models/relationship.py b/bookwyrm/models/relationship.py
--- a/bookwyrm/models/relationship.py
+++ b/bookwyrm/models/relationship.py
@@ -82,6 +82,17 @@
     ''' following a user requires manual or automatic confirmation '''
     status = 'follow_request'
 
+    def save(self, *args, **kwargs):
+        ''' make sure the follow relationship doesn't already exist '''
+        try:
+            UserFollows.objects.get(
+                user_subject=self.user_subject,
+                user_object=self.user_object
+            )
+            return None
+        except UserFollows.DoesNotExist:
+            return super().save(*args, **kwargs)
+
 
 class UserBlocks(UserRelationship):
     ''' prevent another user from following you and seeing your posts '''

{"golden_diff": "diff --git a/bookwyrm/models/relationship.py b/bookwyrm/models/relationship.py\n--- a/bookwyrm/models/relationship.py\n+++ b/bookwyrm/models/relationship.py\n@@ -82,6 +82,17 @@\n     ''' following a user requires manual or automatic confirmation '''\n     status = 'follow_request'\n \n+    def save(self, *args, **kwargs):\n+        ''' make sure the follow relationship doesn't already exist '''\n+        try:\n+            UserFollows.objects.get(\n+                user_subject=self.user_subject,\n+                user_object=self.user_object\n+            )\n+            return None\n+        except UserFollows.DoesNotExist:\n+            return super().save(*args, **kwargs)\n+\n \n class UserBlocks(UserRelationship):\n     ''' prevent another user from following you and seeing your posts '''\n", "issue": "It's possible to create a FollowRequest for a Follow that already exists\nSend a follow request.\r\nUser accepts.\r\nSend a second follow request (eg. using an old tab)\r\n\r\nBecause requests and follows are stored in separate tables it's not possible to enforce this with a constraint. Pre-checking would leave a race condition, so I guess we either need to mess with table locks or create the follow request, and then delete it if its unneeded. Can we enforce this in the pre save of the model, perhaps?\n", "before_files": [{"content": "''' defines relationships between users '''\nfrom django.db import models\n\nfrom bookwyrm import activitypub\nfrom .base_model import ActivitypubMixin, ActivityMapping, BookWyrmModel\n\n\nclass UserRelationship(ActivitypubMixin, BookWyrmModel):\n    ''' many-to-many through table for followers '''\n    user_subject = models.ForeignKey(\n        'User',\n        on_delete=models.PROTECT,\n        related_name='%(class)s_user_subject'\n    )\n    user_object = models.ForeignKey(\n        'User',\n        on_delete=models.PROTECT,\n        related_name='%(class)s_user_object'\n    )\n\n    class Meta:\n        ''' relationships should be unique '''\n        abstract = True\n        constraints = [\n            models.UniqueConstraint(\n                fields=['user_subject', 'user_object'],\n                name='%(class)s_unique'\n            ),\n            models.CheckConstraint(\n                check=~models.Q(user_subject=models.F('user_object')),\n                name='%(class)s_no_self'\n            )\n        ]\n\n    activity_mappings = [\n        ActivityMapping('id', 'remote_id'),\n        ActivityMapping('actor', 'user_subject'),\n        ActivityMapping('object', 'user_object'),\n    ]\n    activity_serializer = activitypub.Follow\n\n    def get_remote_id(self, status=None):\n        ''' use shelf identifier in remote_id '''\n        status = status or 'follows'\n        base_path = self.user_subject.remote_id\n        return '%s#%s/%d' % (base_path, status, self.id)\n\n\n    def to_accept_activity(self):\n        ''' generate an Accept for this follow request '''\n        return activitypub.Accept(\n            id=self.get_remote_id(status='accepts'),\n            actor=self.user_object.remote_id,\n            object=self.to_activity()\n        ).serialize()\n\n\n    def to_reject_activity(self):\n        ''' generate an Accept for this follow request '''\n        return activitypub.Reject(\n            id=self.get_remote_id(status='rejects'),\n            actor=self.user_object.remote_id,\n            object=self.to_activity()\n        ).serialize()\n\n\nclass UserFollows(UserRelationship):\n    ''' Following a user '''\n    status = 'follows'\n\n    @classmethod\n    def from_request(cls, follow_request):\n        ''' converts a follow request into a follow relationship '''\n        return cls(\n            user_subject=follow_request.user_subject,\n            user_object=follow_request.user_object,\n            remote_id=follow_request.remote_id,\n        )\n\n\nclass UserFollowRequest(UserRelationship):\n    ''' following a user requires manual or automatic confirmation '''\n    status = 'follow_request'\n\n\nclass UserBlocks(UserRelationship):\n    ''' prevent another user from following you and seeing your posts '''\n    # TODO: not implemented\n    status = 'blocks'\n", "path": "bookwyrm/models/relationship.py"}], "after_files": [{"content": "''' defines relationships between users '''\nfrom django.db import models\n\nfrom bookwyrm import activitypub\nfrom .base_model import ActivitypubMixin, ActivityMapping, BookWyrmModel\n\n\nclass UserRelationship(ActivitypubMixin, BookWyrmModel):\n    ''' many-to-many through table for followers '''\n    user_subject = models.ForeignKey(\n        'User',\n        on_delete=models.PROTECT,\n        related_name='%(class)s_user_subject'\n    )\n    user_object = models.ForeignKey(\n        'User',\n        on_delete=models.PROTECT,\n        related_name='%(class)s_user_object'\n    )\n\n    class Meta:\n        ''' relationships should be unique '''\n        abstract = True\n        constraints = [\n            models.UniqueConstraint(\n                fields=['user_subject', 'user_object'],\n                name='%(class)s_unique'\n            ),\n            models.CheckConstraint(\n                check=~models.Q(user_subject=models.F('user_object')),\n                name='%(class)s_no_self'\n            )\n        ]\n\n    activity_mappings = [\n        ActivityMapping('id', 'remote_id'),\n        ActivityMapping('actor', 'user_subject'),\n        ActivityMapping('object', 'user_object'),\n    ]\n    activity_serializer = activitypub.Follow\n\n    def get_remote_id(self, status=None):\n        ''' use shelf identifier in remote_id '''\n        status = status or 'follows'\n        base_path = self.user_subject.remote_id\n        return '%s#%s/%d' % (base_path, status, self.id)\n\n\n    def to_accept_activity(self):\n        ''' generate an Accept for this follow request '''\n        return activitypub.Accept(\n            id=self.get_remote_id(status='accepts'),\n            actor=self.user_object.remote_id,\n            object=self.to_activity()\n        ).serialize()\n\n\n    def to_reject_activity(self):\n        ''' generate an Accept for this follow request '''\n        return activitypub.Reject(\n            id=self.get_remote_id(status='rejects'),\n            actor=self.user_object.remote_id,\n            object=self.to_activity()\n        ).serialize()\n\n\nclass UserFollows(UserRelationship):\n    ''' Following a user '''\n    status = 'follows'\n\n    @classmethod\n    def from_request(cls, follow_request):\n        ''' converts a follow request into a follow relationship '''\n        return cls(\n            user_subject=follow_request.user_subject,\n            user_object=follow_request.user_object,\n            remote_id=follow_request.remote_id,\n        )\n\n\nclass UserFollowRequest(UserRelationship):\n    ''' following a user requires manual or automatic confirmation '''\n    status = 'follow_request'\n\n    def save(self, *args, **kwargs):\n        ''' make sure the follow relationship doesn't already exist '''\n        try:\n            UserFollows.objects.get(\n                user_subject=self.user_subject,\n                user_object=self.user_object\n            )\n            return None\n        except UserFollows.DoesNotExist:\n            return super().save(*args, **kwargs)\n\n\nclass UserBlocks(UserRelationship):\n    ''' prevent another user from following you and seeing your posts '''\n    # TODO: not implemented\n    status = 'blocks'\n", "path": "bookwyrm/models/relationship.py"}]}