Avatar for the mpiton user
mpiton
vortex
BlogDocsChangelog

Performance History

Latest Results

fix(link): dedupe probe inputs without indexing on originalUrl The intermediate Map<originalUrl, getDuplicateKey> in dispatchDuplicateDetection would silently drop a row if two ResolvedLinks shared the same originalUrl, leaving that row with duplicate === undefined and blocking it from bulk start when skipDuplicates was on. Compute canonical keys per-row, then collapse through a Set.
feat/task-33-detect-duplicates
8 minutes ago
refactor(link): tighten task-33 duplicate detection per code review Round-1 cleanup off the simplify pass: - Extract `application/services/history_paginate.rs` with `for_each_history_page` (callback per page) + `list_full_history` (collect-all wrapper). `export_history` and the new `detect_duplicates` query both consume it; the bounded-page pagination loop is no longer copy-pasted. - Hoist `InMemoryDownloadReadRepo` and a new `make_history_and_downloads_query_bus` builder into `application/test_support`. Drops ~120 lines of stub fixtures from the `detect_duplicates` test module. - Replace `DuplicateCheckDto.source: Option<&'static str>` (stringly- typed IPC) with a proper serde enum `DuplicateSourceDto` lined up with the rest of the IPC layer. - `detect_duplicates` handler: store the existing-id as `u64` in the index, stringify only on a confirmed hit; pre-check `contains_key` on the history loop so shadowed-by-active entries no longer allocate a `(source, id, file_name)` tuple. - `url_normalizer`: detect the scheme via `eq_ignore_ascii_case` on the prefix instead of allocating a lowercase copy of the whole URL, and trim the WHAT-style block-list / behaviour comments to the load-bearing WHY notes (path-case rationale, batch-size rationale). - `LinkGrabberView`: extract `isStartable` + `startLink` helpers so `handleStartSelected` and `handleStartAllOnline` no longer carry the duplicated status / duplicate gates. Wrap `duplicateCount` in `useMemo`. The `detectDuplicates` `onSuccess` now compares against the previous `duplicate` reference and returns `prev` when nothing moved, so an all-unique batch does not retrigger downstream re-renders. - `LinkRow`: replace the duplicate-source ternary chain with a `duplicateLabelMap` lookup and switch the `data-duplicate` sentinel from `"no"` to `"none"` so unique rows surface a meaningful tag. Test file gains a `makeDuplicate` helper that halves the fixture boilerplate. Tests: cargo test --workspace 1438 passed, vitest 668 passed.
feat/task-33-detect-duplicates
13 hours ago
feat(link): auto-group split archives into one package (task 31) (#144) * feat(link): auto-group split archives into one package (task 31) Cluster Link-Grabber URLs by detected archive base name (`*.partNN.rar`, `*.rNN`, `*.7z.NNN`, `*.zip.NNN`, `*.tar.{gz,bz2,xz}.NNN`) and create one `Package` per cluster with `source_type = SplitArchive` and `external_id = "split-archive:{base}"` for idempotent re-resolve. New `GroupSplitArchivesCommand` handler + `link_group_split_archives` Tauri IPC mirror the playlist grouper flow. Gaps in the part numbering emit a new `DomainEvent::SplitArchiveIncomplete { package_id, base_name, missing_parts }` event (forwarded to the frontend as `split-archive-incomplete`) so the UI can warn the user before extraction blocks. Frontend `SplitArchiveLinkInput` / `SplitArchiveGroupResult` types added in `src/types/media.ts`. 25 service unit tests (matcher fixtures + grouping integration) + 3 handler tests cover the contract. Refs PRD-v2 §P1.12, PRD §6.3. * refactor(link): harden split-archive grouper from /simplify review Code-review pass on the task-31 split-archive grouper: - Format-namespaced `external_id` (`split-archive:{format_tag}:{base}`) so a RAR set and a ZIP set sharing a base name produce two distinct packages instead of silently collapsing under one row. Replaces the previous base-only key documented as "acceptable" in the test that has now been rewritten to assert the correct behaviour. - New `application/services/group_lock` module shared by `PlaylistGrouper` and `SplitArchiveGrouper`, removing a duplicated OnceLock + poisoned-mutex-recovery pair. - `group_one_base` now releases the grouper lock before publishing `PackageCreated` / `SplitArchiveIncomplete` events so synchronous subscribers cannot block other concurrent grouping calls. Same refactor also collapses the duplicated reuse-vs-created branching into a single tail block. - `MAX_LINKS = 500` cap on `group_all` mirrors `MAX_URLS` in `resolve_links` so a runaway IPC payload cannot allocate unbounded cluster state. New `test_group_all_caps_link_count_to_avoid_dos` test covers the path. - `SplitArchiveFormat`, `DetectedPart`, `detect_from_filename` demoted to `pub(crate)`: they were exported but only consumed inside the module. Reduces the public API surface. * fix(link): detect legacy RAR header + release playlist lock before publish Legacy multi-volume RAR sets ship the first volume as `name.rar` followed by `name.r00`, `name.r01`, … The previous matcher only captured `.rNN`, so a valid `name.rar + name.r00` set produced a single-part cluster and was dropped by MIN_PARTS_TO_GROUP. Add `match_legacy_rar_header` (part 0), order it after the other matchers so the more specific patterns still win, and extend `compute_missing_parts` to walk from 0 for LegacyRar so a missing header is reported as `rar` instead of silently dropped. PlaylistGrouper used to hold the shared grouper lock across `event_bus.publish`, which can block re-entrant grouping paths and matches the bug already fixed in SplitArchiveGrouper. Scope the lock to the find-then-save window and publish after the guard drops. Addresses CodeRabbit, Codex, and Cubic review feedback on PR #144. * fix(link): bound part indices + gate on distinct part numbers Three converging review findings on PR #144: 1. `MIN_PARTS_TO_GROUP` was checked against raw link count, so two mirrors of `movie.part01.rar` slipped through the singleton guard and produced a misleading "complete" group with `missing_parts` empty. Replace `parts.len()` with the distinct `part_num` count. 2. The modern RAR (`\d+`) and legacy RAR (`\d{2,}`) regexes accepted unbounded suffixes, letting a hostile `name.part1000000000.rar` force `compute_missing_parts` into a multi-billion-step iteration. Add `MAX_PART_INDEX = 10_000` and reject anything above it inside `detect_from_filename` (after the matcher cascade so a rejected index does not silently cascade into `match_legacy_rar_header`). 3. Defensive `checked_add` on `raw_num + 1` in `match_legacy_rar` so the (now-impossible after the cap) `u32` overflow path is closed. Addresses CodeRabbit, Codex, and Cubic feedback. * docs(changelog): correct split-archive test count (31, not 35) --------- Co-authored-by: Mathieu Piton <27002047+mpiton@users.noreply.github.com>
main
14 hours ago

Latest Branches

CodSpeed Performance Gauge
-23%
refactor(link): tighten task-33 duplicate detection per code review#145
29 minutes ago
c216cff
feat/task-33-detect-duplicates
CodSpeed Performance Gauge
+19%
feat(link): auto-group split archives into one package (task 31)#144
14 hours ago
144c2ba
feat/task-31-split-archives
CodSpeed Performance Gauge
N/A
17 hours ago
c3a7733
codspeed-wizard-1777816068872
© 2026 CodSpeed Technology
Home Terms Privacy Docs