refactor: dedupe service/collector helper twins (#1135) - #1285
Conversation
Five genuine (non-parity) clones across services/ and telegram/: * channel_analytics_service._calc_err / _calc_err24 duplicated the engagement-rate formula (sum / rows*subs * 100); extracted _engagement_rate(rows) — each caller keeps its own data fetch. * pipeline_nodes/handlers duplicated the context_messages -> source block in LlmGenerateHandler and AgentLoopHandler; extracted module-level _build_source_messages(messages). Behaviour identical: blank texts dropped, same [header] text (id:.. date:..) format, blank-joined; the truthiness guard on the agent-loop user_message is preserved (the joined string is empty iff the parts list was empty). * telegram_actions.download_media / download_media_sized duplicated the resolve-entity + iter_messages(ids=) lookup + MessageNotFoundError raise; extracted _fetch_message_with_flood_wait(client, phone, entity, id). * photo_task_service.send_now / schedule_send duplicated the PhotoBatch + PhotoBatchItem construction (parameterized by status + started_at vs schedule_at); extracted _create_send_batch_item returning (batch_id, item_id). * collector_mixins/stats stats_*worker_count and available_stats_*_worker_count were two pairs of twins differing only by config attr / default / log label; extracted _configured_worker_count and _available_worker_count. 1359 targeted tests pass. jscpd total holds at 0.67% (clones from these files removed; remaining clones are parity/declarative — see PR #1135 notes). Part of #1135 (axis 5 of #1130). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
c9be6f9 to
36cfaca
Compare
🔍 Local review — cycle 1/3 (clean)Reviewed locally via built-in Five MOVE/extraction refactors — both reviewers confirmed semantic equivalence of each:
The subtle point both flagged and cleared: the AgentLoop No Tests: 1373 targeted tests green after rebase. ruff clean. Totals: 0 FIX, 0 SKIP, 0 UNVERIFIED. Review cycle complete — merge is yours to trigger (local mode does not auto-merge). |
Part of #1135 (axis 5 of #1130). Five genuine (non-parity) clones across
services/andtelegram/.Clones & extraction
channel_analytics_service._calc_err↔_calc_err24_engagement_rate(channel_id, rows)sum / (rows*subs) * 100. Each caller keeps its own data fetch (get_err_datavsget_err24_data).pipeline_nodes/handlerssource block (LlmGenerate + AgentLoop)_build_source_messages(messages)[header] text (id:.. date:..)rendering, blank-joined; blank texts dropped. The AgentLoopuser_messagetruthiness guard is preserved (joined string empty ⟺ parts list empty).telegram_actions.download_media↔download_media_sizedlookup_fetch_message_with_flood_wait(...)iter_messages(ids=)under flood-wait +MessageNotFoundErrorraise.photo_task_service.send_now↔schedule_sendbatch+item ctor_create_send_batch_item(..., status, schedule_at)→(batch_id, item_id)started_atvsschedule_at.collector_mixins/statsstats_*worker_count+available_stats_*worker_count(2 pairs)_configured_worker_count,_available_worker_countVerification
analytics/err/pipeline_node/telegram_action/download_media/photo_task/collector_stats/worker_count/source_messages).jscpd
Total: 0.67%(49 clones) — flat vs. the PR-2 state. The remainingservices/telegram_actions.py:575↔594andcollector_mixins/cancellation↔statshits are parity-style Telegram-error-handling blocks and the shared TYPE_CHECKINGCollectorProtocol (see tech-debt: дедуп кода (jscpd 0.56%, не-parity клоны) #1135 parity notes), intentionally untouched.Part of #1135 / #1130. Not for merge — review requested.
🤖 Generated with Claude Code