77from django .contrib .contenttypes .models import ContentType
88from framework .celery_tasks import app as celery_app
99from osf .models import NotificationSubscription
10+ from django .db .models import Exists , OuterRef
11+ from celery .utils .log import get_task_logger
12+
13+ logger = get_task_logger (__name__ )
14+
1015
1116
1217@celery_app .task (name = 'scripts.remove_after_use.merge_notification_subscription_provider_ct' )
@@ -19,13 +24,37 @@ def merge_notification_subscription_provider_ct():
1924 ContentType .objects .get_by_natural_key ('osf' , 'registrationprovider' ),
2025 ContentType .objects .get_by_natural_key ('osf' , 'collectionprovider' ),
2126 ]
22- subscriptions = NotificationSubscription . objects . filter (
23- content_type__in = provider_ct_list
24- )
25- subscriptions . update (
27+
28+ provider_ct_ids = [ ct . id for ct in provider_ct_list ]
29+
30+ abstract_provider_ct_qs = NotificationSubscription . objects . filter (
2631 content_type = abstract_provider_ct
2732 )
2833
34+ duplicates = NotificationSubscription .objects .filter (
35+ content_type_id__in = provider_ct_ids
36+ ).annotate (
37+ abstract_exists = Exists (
38+ abstract_provider_ct_qs .filter (
39+ notification_type_id = OuterRef ('notification_type_id' ),
40+ user_id = OuterRef ('user_id' ),
41+ object_id = OuterRef ('object_id' ),
42+ _is_digest = OuterRef ('_is_digest' ),
43+ )
44+ )
45+ ).filter (abstract_exists = True )
46+
47+ # delete rows that would conflict
48+ logger .info (f'Deleted { duplicates .count ()} duplicate NotificationSubscription rows with provider content types.' )
49+ duplicates .delete ()
50+
51+ # update remaining rows
52+ update_qs = NotificationSubscription .objects .filter (
53+ content_type_id__in = provider_ct_ids
54+ )
55+ logger .info (f'Updated { update_qs .count ()} NotificationSubscription rows to use abstract provider content type.' )
56+ update_qs .update (content_type = abstract_provider_ct )
57+
2958
3059if __name__ == '__main__' :
3160 merge_notification_subscription_provider_ct .delay ()
0 commit comments