@@ -69,7 +69,7 @@ async def test_enqueue_candidate_uses_hash_locator_and_redacts_durable_payload(m
6969 from pallas .product .llm .sticker_labels import content_hash_for_bytes
7070
7171 original = b"original-gif-bytes"
72- store = SimpleNamespace (requeue_terminal = AsyncMock (side_effect = lambda job : job ))
72+ store = SimpleNamespace (requeue_terminal = AsyncMock (side_effect = lambda job : ( job , True ) ))
7373 repository = SimpleNamespace (get = AsyncMock (return_value = None ))
7474 monkeypatch .setattr (sticker_label_jobs , "build_work_job_store" , lambda : store )
7575 monkeypatch .setattr (sticker_label_jobs , "sticker_label_repository" , lambda : repository )
@@ -140,7 +140,7 @@ async def test_low_confidence_or_old_prompt_label_requeues(monkeypatch: pytest.M
140140 )
141141 )
142142 )
143- store = SimpleNamespace (requeue_terminal = AsyncMock (side_effect = lambda job : job ))
143+ store = SimpleNamespace (requeue_terminal = AsyncMock (side_effect = lambda job : ( job , True ) ))
144144 monkeypatch .setattr (sticker_label_jobs , "sticker_label_repository" , lambda : repository )
145145 monkeypatch .setattr (sticker_label_jobs , "build_work_job_store" , lambda : store )
146146 monkeypatch .setattr ("pallas.core.shared.utils.media_cache.bind_image_content_hash" , AsyncMock ())
@@ -151,6 +151,71 @@ async def test_low_confidence_or_old_prompt_label_requeues(monkeypatch: pytest.M
151151 store .requeue_terminal .assert_awaited_once ()
152152
153153
154+ @pytest .mark .asyncio
155+ async def test_enqueue_candidate_counts_cache_hit_when_label_is_sufficient (
156+ monkeypatch : pytest .MonkeyPatch ,
157+ ) -> None :
158+ from pallas .product .llm import sticker_label_jobs
159+ from pallas .product .llm .sticker_label_jobs import StickerLabelSource
160+ from pallas .product .llm .sticker_labels import StickerSemanticLabel , content_hash_for_bytes
161+ from pallas .product .llm .task_metrics import record_bot_llm_task
162+
163+ content = b"already-labeled"
164+ repository = SimpleNamespace (
165+ get = AsyncMock (
166+ return_value = StickerSemanticLabel (
167+ content_hash = content_hash_for_bytes (content ),
168+ is_sticker = True ,
169+ confidence = 0.95 ,
170+ prompt_version = 1 ,
171+ )
172+ )
173+ )
174+ store = SimpleNamespace (requeue_terminal = AsyncMock ())
175+ metric = Mock ()
176+ monkeypatch .setattr (sticker_label_jobs , "sticker_label_repository" , lambda : repository )
177+ monkeypatch .setattr (sticker_label_jobs , "build_work_job_store" , lambda : store )
178+ monkeypatch .setattr ("pallas.product.llm.task_metrics.record_bot_llm_task" , metric )
179+
180+ assert not await sticker_label_jobs .enqueue_sticker_label_candidate (
181+ cache_key = "[CQ:image,file=already-labeled.image]" ,
182+ content = content ,
183+ source = StickerLabelSource .FOLLOWUP_CANDIDATE ,
184+ )
185+ store .requeue_terminal .assert_not_awaited ()
186+ metric .assert_any_call ("sticker_label" , "cache_hit" )
187+ assert not any (call .args [1 ] == "submit_ok" for call in metric .call_args_list )
188+ assert record_bot_llm_task is not None
189+
190+
191+ @pytest .mark .asyncio
192+ async def test_enqueue_candidate_counts_coalesced_when_job_already_pending (
193+ monkeypatch : pytest .MonkeyPatch ,
194+ ) -> None :
195+ from pallas .product .llm import sticker_label_jobs
196+ from pallas .product .llm .sticker_label_jobs import StickerLabelSource
197+ from pallas .product .llm .sticker_labels import content_hash_for_bytes
198+
199+ content = b"dup-content"
200+ repository = SimpleNamespace (get = AsyncMock (return_value = None ))
201+ store = SimpleNamespace (requeue_terminal = AsyncMock (side_effect = lambda job : (job , False )))
202+ metric = Mock ()
203+ monkeypatch .setattr (sticker_label_jobs , "sticker_label_repository" , lambda : repository )
204+ monkeypatch .setattr (sticker_label_jobs , "build_work_job_store" , lambda : store )
205+ monkeypatch .setattr ("pallas.core.shared.utils.media_cache.bind_image_content_hash" , AsyncMock ())
206+ monkeypatch .setattr ("pallas.product.llm.task_metrics.record_bot_llm_task" , metric )
207+
208+ queued = await sticker_label_jobs .enqueue_sticker_label_candidate (
209+ cache_key = "[CQ:image,file=dup.image]" ,
210+ content = content ,
211+ source = StickerLabelSource .FOLLOWUP_CANDIDATE ,
212+ )
213+
214+ assert queued is True
215+ assert not any (call .args [1 ] == "submit_ok" for call in metric .call_args_list )
216+ assert any (call .args == ("sticker_label" , "background_coalesced" ) for call in metric .call_args_list )
217+
218+
154219@pytest .mark .asyncio
155220async def test_string_source_cannot_enqueue_a_label_job (monkeypatch : pytest .MonkeyPatch ) -> None :
156221 from pallas .product .llm import sticker_label_jobs
@@ -413,3 +478,49 @@ async def test_cache_changed_is_completed_by_actual_worker(monkeypatch: pytest.M
413478
414479 assert await worker .run_once ()
415480 assert await store .claim (owner = "other" , lease_sec = 1 ) is None
481+
482+
483+ @pytest .mark .asyncio
484+ async def test_permanent_label_errors_do_not_retry_worker (
485+ monkeypatch : pytest .MonkeyPatch ,
486+ ) -> None :
487+ from pallas .core .platform .work_jobs .models import WorkJob
488+ from pallas .core .platform .work_jobs .store import MemoryWorkJobStore
489+ from pallas .core .platform .work_jobs .worker import WorkJobWorker
490+ from pallas .product .llm import sticker_label_jobs
491+ from pallas .product .llm .sticker_labels import content_hash_for_bytes
492+
493+ sticker_label_jobs .reset_sticker_label_runtime_state_for_tests ()
494+ for case in ("parse_error" , "no_vision" ):
495+ save_observation = AsyncMock ()
496+ monkeypatch .setattr (sticker_label_jobs , "save_sticker_label_observation" , save_observation )
497+ monkeypatch .setattr (
498+ "pallas.core.shared.utils.media_cache.get_image_by_content_hash" , AsyncMock (return_value = b"image" )
499+ )
500+
501+ async def fail_vision (_content : bytes ) -> None :
502+ if case == "parse_error" :
503+ raise ValueError ("invalid sticker label JSON" )
504+ raise RuntimeError ("no sticker vision endpoint" )
505+
506+ monkeypatch .setattr (sticker_label_jobs , "label_sticker_with_vision" , fail_vision )
507+ store = MemoryWorkJobStore ()
508+ await store .enqueue (
509+ WorkJob .create (
510+ kind = "sticker.label.visual" ,
511+ payload = {"content_hash" : content_hash_for_bytes (b"image" ), "observation" : {"state" : "queued" }},
512+ idempotency_key = f"label:permanent:{ case } " ,
513+ )
514+ )
515+ worker = WorkJobWorker (
516+ store = store , owner = "worker" , handlers = {"sticker.label.visual" : sticker_label_jobs .handle_sticker_label_visual }
517+ )
518+
519+ assert await worker .run_once ()
520+ assert (await store .stats ())["leased" ] == 0
521+ assert (await store .stats ())["dead_lettered" ] == 0
522+ assert worker .metrics .snapshot ()["retried_since_start" ] == 0
523+ assert (await store .stats ())["pending" ] == 0
524+ assert await store .claim (owner = "next" , lease_sec = 1 ) is None
525+ assert save_observation .await_args .args [2 ]["state" ] in {"parse_error" , "no_vision" }
526+ sticker_label_jobs .reset_sticker_label_runtime_state_for_tests ()
0 commit comments