Skip to content

Conversation

@imnasnainaec
Copy link
Collaborator

@imnasnainaec imnasnainaec commented Jan 16, 2026

In WordRepo, update DeleteFrontier method

  • Add audioFileName param
    • allows finding and deleting a specific Frontier word with a specific audio file
  • Return deleted word rather than just a success bool
    • enables more atomic operations
  • Rename the multi-word overload to DeleteFrontierWords
    • allows the new audioFileName param to be optional

In WordService

  • Update Delete method: remove the unused overload; rename the used overload to DeleteAudio
  • In DeleteAudio, DeleteFrontierWord, Update methods, make use of DeleteFrontier's returned word
    • avoids separately fetching the word from the WordCollection
  • In Update method, return the id of the updated word, rather than just a success bool

This change is Reviewable

Summary by CodeRabbit

  • New Features

    • Optional audio-file filtering when removing frontier words.
    • Separate audio-file deletion endpoint distinct from word deletion.
  • Bug Fixes

    • Prevented accidental word removals when deleting audio files.
  • Refactor

    • Update operations now return resource identifiers (nullable) instead of booleans.
    • Bulk frontier-deletion API renamed and clarified; collection parameters accept general enumerables.

✏️ Tip: You can customize this high-level summary in your review settings.

@imnasnainaec imnasnainaec self-assigned this Jan 16, 2026
@imnasnainaec imnasnainaec added refactor 🟨Medium Medium-priority PR labels Jan 16, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 16, 2026

📝 Walkthrough

Walkthrough

Repository and service APIs changed: frontier deletions now optionally filter by audio file and return the deleted Word; bulk frontier deletion renamed; WordService renamed Delete -> DeleteAudio and Update now returns a nullable Id. Signatures updated across controller, repository, interfaces, mocks, and tests.

Changes

Cohort / File(s) Summary
Interfaces
Backend/Interfaces/IWordRepository.cs, Backend/Interfaces/IWordService.cs
IWordRepository.DeleteFrontierTask<Word?> DeleteFrontier(string projectId, string wordId, string? audioFileName = null); bulk renamed to DeleteFrontierWords. IWordService.Update return changed to Task<string?>. Removed Delete overloads; added DeleteAudio.
Repository implementation
Backend/Repositories/WordRepository.cs
Added GetProjectWordWithAudioFilter. DeleteFrontier now accepts optional audioFileName and returns deleted Word? via FindOneAndDeleteAsync. Batch method renamed to DeleteFrontierWords.
Services
Backend/Services/WordService.cs, Backend/Services/MergeService.cs
WordService converted to primary-constructor style. Removed old Delete; added DeleteAudio which calls repo DeleteFrontier(..., audioFileName), updates audio list and history. Update now returns updated word Id (string?). MergeService now calls DeleteFrontierWords.
Controller
Backend/Controllers/AudioController.cs
Calls _wordService.DeleteAudio(...) instead of _wordService.Delete(...).
Tests & Mocks
Backend.Tests/Mocks/WordRepositoryMock.cs, Backend.Tests/Services/WordServiceTests.cs
Mock DeleteFrontier updated to return Word? with optional audioFileName handling; bulk mock renamed to DeleteFrontierWords. Tests updated to use DeleteAudio, adjust expectations to nullable returns, and use array-style initializers for collections.

Sequence Diagram(s)

sequenceDiagram
    participant Client as AudioController
    participant Service as WordService
    participant Repo as WordRepository
    participant DB as MongoDB

    Client->>Service: DeleteAudio(projectId, userId, wordId, fileName)
    Service->>Repo: DeleteFrontier(projectId, wordId, fileName)
    Repo->>DB: FindOneAndDelete(filter by projectId+wordId + audio.FileName)
    DB-->>Repo: deleted Word or null
    Repo-->>Service: Word? (deleted frontier word)
    Service->>Service: remove audio entries, update history
    Service-->>Client: return Word? (Ok or NotFound)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I hopped into code with a curious bite,

Split deletes for audio, made signatures right,
Frontier words now yield what they were,
IDs returned where booleans once were,
A little rabbit dance in soft moonlight.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.23% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title '[WordRepository, WordService] Refine DeleteFrontier usage' accurately summarizes the main changes—refactoring how DeleteFrontier is used across the repository and service layers with updated signatures, return types, and method names.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings


📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 304c6f9 and 5723a5f.

📒 Files selected for processing (1)
  • Backend.Tests/Services/WordServiceTests.cs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: docker_build
  • GitHub Check: test_build (8.0.x)
  • GitHub Check: Analyze (csharp)
🔇 Additional comments (7)
Backend.Tests/Services/WordServiceTests.cs (7)

29-29: LGTM — Clean adoption of C# 12 collection expressions.

The use of collection expressions (["other"], [UserId], [new(), new()]) is a clean modernization that improves readability while maintaining identical semantics.

Also applies to: 37-37, 44-44


49-58: LGTM — Good coverage of DeleteAudio failure cases.

The test correctly validates that DeleteAudio returns null for invalid project ID, word ID, and file name. The assertions align with the new nullable return type.


60-80: LGTM — DeleteAudio tests properly verify frontier behavior.

The tests correctly validate:

  • Null return when word is not in frontier (line 66)
  • Successful deletion returns the new word with updated EditedBy and History (lines 76-77)
  • Proper frontier state changes (old word removed, new word added)

82-86: LGTM — Test correctly reflects the new Update return type.

The test name and assertion properly reflect that Update now returns null (instead of false) when the word is not in the frontier, aligning with the API change from bool to string?.


122-147: LGTM — RestoreFrontierWords tests use consistent collection expressions.

The array literal syntax for word ID collections is clean and consistent with the rest of the file's modernization.


176-233: LGTM — FindContainingWord tests properly use collection expressions.

The modernized syntax for Senses and Glosses assignments is consistent and maintains the original test semantics.


88-101: The assertion appears to be incorrect based on the actual mutation behavior.

The Update method does mutate the input word object's Id property, but not as the test assumes. The call chain UpdateCreatePrepEditedData sets word.Id = "" (line 26 of WordService.cs), not to the new word's ID.

At line 96, the assertion compares the returned new ID (from the frontier word) to word.Id, which at that point is an empty string due to the mutation in PrepEditedData. The comparison should be newID Is.EqualTo(""), which suggests the test will fail or is testing unintended behavior.

If the intent is to verify that Update returns the correct new word ID, the assertion should compare against oldId instead, or verify the returned ID separately without relying on the mutation side effect.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Jan 16, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.46%. Comparing base (1c058e5) to head (5723a5f).
⚠️ Report is 17 commits behind head on master.

Additional details and impacted files
@@             Coverage Diff             @@
##           master    #4100       +/-   ##
===========================================
+ Coverage   74.79%   86.46%   +11.66%     
===========================================
  Files         295       54      -241     
  Lines       10946     4750     -6196     
  Branches     1372      583      -789     
===========================================
- Hits         8187     4107     -4080     
+ Misses       2363      500     -1863     
+ Partials      396      143      -253     
Flag Coverage Δ
backend 86.46% <100.00%> (+0.38%) ⬆️
frontend ?

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@imnasnainaec imnasnainaec changed the title Expand WordRepo [WordRepository, WordService] Refine DeleteFrontier usage Jan 16, 2026
@imnasnainaec imnasnainaec marked this pull request as ready for review January 16, 2026 13:38
@imnasnainaec imnasnainaec requested a review from Copilot January 16, 2026 13:38
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the DeleteFrontier method in WordRepository and updates WordService to leverage the improved API, making operations more atomic and returning more useful values instead of simple success booleans.

Changes:

  • Enhanced DeleteFrontier to accept an optional audioFileName parameter and return the deleted word instead of a boolean
  • Renamed the multi-word overload from DeleteFrontier to DeleteFrontierWords to avoid signature conflicts
  • Updated WordService.Update to return the ID of the updated word instead of a boolean, and refactored to use the returned word from DeleteFrontier
  • Renamed WordService.Delete(projectId, userId, wordId, fileName) to DeleteAudio and removed the unused Delete(projectId, userId, wordId) overload

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
Backend/Repositories/WordRepository.cs Added GetProjectWordWithAudioFilter helper, updated DeleteFrontier to return deleted word and accept optional audio parameter, renamed multi-word overload to DeleteFrontierWords
Backend/Interfaces/IWordRepository.cs Updated interface signatures to match repository implementation
Backend/Services/WordService.cs Removed unused Delete overload, renamed remaining Delete to DeleteAudio, updated Update to return word ID, refactored methods to use returned word from DeleteFrontier
Backend/Interfaces/IWordService.cs Updated interface signatures to match service implementation
Backend/Controllers/AudioController.cs Updated call from Delete to DeleteAudio
Backend/Services/MergeService.cs Updated call from DeleteFrontier to DeleteFrontierWords
Backend.Tests/Services/WordServiceTests.cs Updated test method names and assertions, modernized collection initializer syntax
Backend.Tests/Mocks/WordRepositoryMock.cs Updated mock implementation to match new repository signatures

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@Backend.Tests/Mocks/WordRepositoryMock.cs`:
- Around line 130-139: The mock DeleteFrontier currently treats empty-string
audioFileName differently and uses RemoveAll which deletes all matches; change
it to mirror repository FindOneAndDeleteAsync by treating audioFileName == null
or empty the same (i.e., ignore audio filter when
string.IsNullOrEmpty(audioFileName)) when locating the word with _frontier.Find,
and then remove only that single found instance (e.g., call
_frontier.Remove(word) or remove by index) instead of RemoveAll; ensure the
method still returns the deleted Word or null via Task.FromResult.

In `@Backend/Services/WordService.cs`:
- Around line 135-137: The Update method currently discards the result of
Create(userId, word) and returns word.Id which was cleared by PrepEditedData
(PrepEditedData sets word.Id = ""), so Update always returns empty string; fix
by using the value returned from Create (or have Create return the created
object's Id) and return that Id from Update instead of returning the original
word.Id, or alternatively stop clearing Id in PrepEditedData when creating new
records; update the Update method (and/or Create/PrepEditedData) so the returned
Id comes from the created entity rather than the mutated input object.
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1c058e5 and f048002.

📒 Files selected for processing (8)
  • Backend.Tests/Mocks/WordRepositoryMock.cs
  • Backend.Tests/Services/WordServiceTests.cs
  • Backend/Controllers/AudioController.cs
  • Backend/Interfaces/IWordRepository.cs
  • Backend/Interfaces/IWordService.cs
  • Backend/Repositories/WordRepository.cs
  • Backend/Services/MergeService.cs
  • Backend/Services/WordService.cs
🧰 Additional context used
🧬 Code graph analysis (4)
Backend/Controllers/AudioController.cs (1)
src/types/word.ts (1)
  • newWord (88-103)
Backend.Tests/Mocks/WordRepositoryMock.cs (1)
Backend/Models/Word.cs (3)
  • Word (10-177)
  • Word (87-107)
  • Word (110-132)
Backend/Interfaces/IWordRepository.cs (1)
Backend/Models/Word.cs (3)
  • Word (10-177)
  • Word (87-107)
  • Word (110-132)
Backend.Tests/Services/WordServiceTests.cs (3)
Backend/Services/WordService.cs (1)
  • Word (21-30)
Backend.Tests/Util.cs (2)
  • Word (48-61)
  • Util (11-140)
Backend/Models/Word.cs (3)
  • Word (10-177)
  • Word (87-107)
  • Word (110-132)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: CodeQL analysis (csharp)
  • GitHub Check: docker_build
🔇 Additional comments (16)
Backend/Interfaces/IWordService.cs (1)

11-12: Signature updates align with the new service API.
Return types are explicit and match the refactor goals.

Backend/Interfaces/IWordRepository.cs (1)

24-25: Repository delete signatures look consistent.
Optional audio filter plus renamed bulk delete align with the refactor.

Backend.Tests/Mocks/WordRepositoryMock.cs (1)

142-147: Bulk delete rename is consistent.
Return type and behavior remain clear.

Backend/Repositories/WordRepository.cs (3)

43-50: Audio filter helper is clear and scoped.
LGTM.


262-271: Atomic delete with optional audio filter looks correct.
Good use of FindOneAndDeleteAsync for an all-in-one operation.


276-281: Bulk delete rename aligns with the interface.
LGTM.

Backend.Tests/Services/WordServiceTests.cs (5)

29-29: Test data setup updates look consistent.
EditedBy/Audio/list initializations align with the new shapes.

Also applies to: 37-37, 44-44, 54-54, 65-65, 74-74


55-57: DeleteAudio test expectations align with the new contract.
Null-return cases and the updated call site are covered.

Also applies to: 66-66, 75-75


83-85: Update tests reflect nullable id returns.
Covers both null and non-null outcomes.

Also applies to: 95-95


126-126: RestoreFrontierWords scenarios remain well covered.
Inputs reflect the updated collection usage.

Also applies to: 135-136, 145-145


185-185: Sense/gloss setup adjustments are consistent.
No issues noted.

Also applies to: 206-208, 226-226

Backend/Services/WordService.cs (3)

11-13: LGTM! Primary constructor with field assignment is correct.

The primary constructor syntax (C# 12) combined with explicit field initialization is a valid pattern that provides both the convenience of primary constructors and explicit field documentation.


59-74: LGTM! Atomic audio deletion logic is correct.

The method correctly:

  1. Atomically fetches and removes the word from frontier with the audio filter
  2. Removes the matching audio entries
  3. Creates a new word version with updated history

78-93: LGTM! Atomic deletion pattern is correct.

The method correctly uses DeleteFrontier to atomically fetch and remove the word from the frontier before adding it back with the deleted status.

Backend/Services/MergeService.cs (1)

120-124: LGTM! Correct migration to batch deletion API.

The change to DeleteFrontierWords aligns with the new repository API for batch deletions, and the childIds list construction is appropriate.

Backend/Controllers/AudioController.cs (1)

180-185: LGTM! Correctly updated to use the renamed DeleteAudio method.

The error handling remains appropriate—returning NotFound when the word or audio file combination doesn't exist in the frontier.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Copy link
Contributor

@jasonleenaylor jasonleenaylor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

@jasonleenaylor reviewed 8 files and all commit messages, and made 1 comment.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on @imnasnainaec).

@imnasnainaec imnasnainaec merged commit f6c7211 into master Jan 16, 2026
16 checks passed
@imnasnainaec imnasnainaec deleted the word-repo-service branch January 16, 2026 20:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants