@@ -518,21 +518,20 @@ def test_database_queries_made(self):
518518 flights = list (self .probabilistic_backend .get_candidate_flights ())
519519 self .assertEqual (len (flights ), 3 )
520520
521- with self .assertNumQueries (1 ):
522- # This should just be the same query from `get_candidate_flights` above
521+ with self .assertNumQueries (3 ):
522+ # One for flights, one for ads, one for ad types (due to prefetch)
523523 flight = self .probabilistic_backend .select_flight ()
524524
525- with self .assertNumQueries (2 ):
526- # One query to get the specific ad for the chosen flight
527- # One to prefetch all the ad types
525+ with self .assertNumQueries (0 ):
526+ # No queries because we used the prefetched ads
528527 ad = self .probabilistic_backend .select_ad_for_flight (flight )
529528 self .assertTrue (ad in self .possible_ads , ad )
530529
531530 with self .assertNumQueries (3 ):
532531 # Three total queries to get an ad placement
533- # 1. Get all the candidate flights
534- # 2. Choose the specific ad for the chosen flight
535- # 3. Prefetch the ad types for all the ads in the chosen flight
532+ # 1. Get all the candidate flights (and prefetch ads/adtypes)
533+ # 2. Choose the specific ad for the chosen flight (0 queries)
534+ # 3. get_placement (0 queries as it uses prefetch)
536535 ad , _ = self .probabilistic_backend .get_ad_and_placement ()
537536 self .assertTrue (ad in self .possible_ads , ad )
538537
@@ -620,6 +619,85 @@ def test_click_probability(self):
620619 ad , _ = self .probabilistic_backend .get_ad_and_placement ()
621620 self .assertEqual (ad , None )
622621
622+ def test_flight_matching_priority (self ):
623+ # Remove existing flights
624+ for flight in Flight .objects .all ():
625+ flight .live = False
626+ flight .save ()
627+
628+ # Priority 1
629+ ad_type_a = get (AdType , has_image = False , slug = "a" )
630+ # Priority 10
631+ ad_type_b = get (AdType , has_image = False , slug = "b" )
632+
633+ placements = [
634+ {"div_id" : "a" , "ad_type" : "a" , "priority" : 1 },
635+ {"div_id" : "b" , "ad_type" : "b" , "priority" : 10 },
636+ ]
637+
638+ # Flight 1: Matches placement A (priority 1)
639+ flight1 = get (
640+ Flight ,
641+ live = True ,
642+ campaign = self .campaign ,
643+ sold_clicks = 1000 ,
644+ start_date = get_ad_day ().date (),
645+ end_date = get_ad_day ().date () + datetime .timedelta (days = 30 ),
646+ pacing_interval = 24 * 60 * 60 ,
647+ )
648+ ad1 = get (
649+ Advertisement ,
650+ slug = "ad1" ,
651+ live = True ,
652+ flight = flight1 ,
653+ )
654+ ad1 .ad_types .add (ad_type_a )
655+
656+ # Flight 2: Matches placement B (priority 10)
657+ flight2 = get (
658+ Flight ,
659+ live = True ,
660+ campaign = self .campaign ,
661+ sold_clicks = 1000 ,
662+ start_date = get_ad_day ().date (),
663+ end_date = get_ad_day ().date () + datetime .timedelta (days = 30 ),
664+ pacing_interval = 24 * 60 * 60 ,
665+ )
666+ ad2 = get (
667+ Advertisement ,
668+ slug = "ad2" ,
669+ live = True ,
670+ flight = flight2 ,
671+ )
672+ ad2 .ad_types .add (ad_type_b )
673+
674+ backend = ProbabilisticFlightBackend (
675+ request = self .request , placements = placements , publisher = self .publisher
676+ )
677+
678+ flight1_count = 0
679+ flight2_count = 0
680+ iterations = 1000
681+
682+ # Ensure base weights are equal
683+ self .assertEqual (
684+ flight1 .weighted_clicks_needed_this_interval (self .publisher ),
685+ flight2 .weighted_clicks_needed_this_interval (self .publisher ),
686+ )
687+
688+ for _ in range (iterations ):
689+ selected = backend .select_flight ()
690+ if selected == flight1 :
691+ flight1_count += 1
692+ elif selected == flight2 :
693+ flight2_count += 1
694+
695+ # Avoid div by 0 and handle potential 0 counts
696+ ratio = flight2_count / (flight1_count + 1 )
697+
698+ # Used to be ~1, now should be ~10
699+ self .assertGreater (ratio , 5.0 )
700+
623701 def test_publisher_campaign_type_restrictions (self ):
624702 self .campaign .campaign_type = PAID_CAMPAIGN
625703 self .campaign .save ()
0 commit comments