feat: extended data structures #50

Merged
devitq merged 15 commits from feat/extend-data-structures-48 into develop 2026-05-20 21:37:12 +00:00
devitq commented 2026-05-19 23:53:02 +00:00 (Migrated from github.com)
No description provided.
coderabbitai[bot] commented 2026-05-19 23:53:08 +00:00 (Migrated from github.com)

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: de3090ad-c1ad-432e-82f1-ec1bb7fcbee7

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/extend-data-structures-48

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.

<!-- This is an auto-generated comment: summarize by coderabbit.ai --> <!-- This is an auto-generated comment: skip review by coderabbit.ai --> > [!IMPORTANT] > ## Review skipped > > Auto reviews are disabled on base/target branches other than the default branch. > > > > Please check the settings in the CodeRabbit UI or the `.coderabbit.yaml` file in this repository. To trigger a single review, invoke the `@coderabbitai review` command. > > <details> > <summary>⚙️ Run configuration</summary> > > **Configuration used**: Organization UI > > **Review profile**: ASSERTIVE > > **Plan**: Pro > > **Run ID**: `de3090ad-c1ad-432e-82f1-ec1bb7fcbee7` > > </details> > > You can disable this status message by setting the `reviews.review_status` to `false` in the CodeRabbit configuration file. > > Use the checkbox below for a quick retry: > - [ ] <!-- {"checkboxId": "e9bb8d72-00e8-4f67-9cb2-caf3b22574fe"} --> 🔍 Trigger review <!-- end of auto-generated comment: skip review by coderabbit.ai --> <!-- finishing_touch_checkbox_start --> <details> <summary>✨ Finishing Touches</summary> <details> <summary>🧪 Generate unit tests (beta)</summary> - [ ] <!-- {"checkboxId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Create PR with unit tests - [ ] <!-- {"checkboxId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Commit unit tests in branch `feat/extend-data-structures-48` </details> </details> <!-- finishing_touch_checkbox_end --> <!-- tips_start --> --- Thanks for using [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=devitq/movienight-backend&utm_content=50)! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. <details> <summary>❤️ Share</summary> - [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai) - [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai) - [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai) - [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code) </details> <sub>Comment `@coderabbitai help` to get the list of available commands and usage tips.</sub> <!-- tips_end -->
copilot-pull-request-reviewer[bot] (Migrated from github.com) reviewed 2026-05-20 16:51:56 +00:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) left a comment

Pull request overview

This PR expands the backend data model and APIs to support richer film metadata, user preferences/ratings, recommendations, and a Jellyfin integration (sync + event ingestion), along with persistence and metrics support.

Changes:

  • Extend core domain + DB schema for films, library entries (watchedAt), user preferences, film ratings, and Jellyfin sync/event state.
  • Add new application services and REST controllers for preferences, ratings, recommendations, and Jellyfin sync/events.
  • Add Micrometer business metrics and supporting JDBC repositories/entities.

Reviewed changes

Copilot reviewed 70 out of 70 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/test/kotlin/com/project/movienight/RecommendationSmokeTest.kt End-to-end smoke test for preferences/ratings/recommendations
src/test/kotlin/com/project/movienight/application/services/FilmLibraryServiceTest.kt Updates FilmLibraryService unit tests for new behavior
src/test/kotlin/com/project/movienight/adapters/persistence/entity/UserEntityMappingTest.kt Extends mapping test for jellyfinUserId
src/main/resources/db/migration/V3__jellyfin_events.sql Adds jellyfin_events table for idempotency/auditing
src/main/resources/db/migration/V1__init.sql Expands initial schema (users/films/favorites/etc.)
src/main/resources/application.yaml Adds Jellyfin integration config
src/main/kotlin/com/project/movienight/MovieNightApplication.kt Enables Spring scheduling
src/main/kotlin/com/project/movienight/domain/model/UserPreferences.kt New domain model for user preferences
src/main/kotlin/com/project/movienight/domain/model/User.kt Adds preferences + jellyfinUserId to User
src/main/kotlin/com/project/movienight/domain/model/RecommendationContext.kt Adds recommendation context/result models
src/main/kotlin/com/project/movienight/domain/model/JellyfinSyncState.kt Adds Jellyfin sync state/summary models
src/main/kotlin/com/project/movienight/domain/model/FilmRating.kt Adds film rating domain model
src/main/kotlin/com/project/movienight/domain/model/FilmLibrary.kt Adds watchedAt to library entries
src/main/kotlin/com/project/movienight/domain/model/Film.kt Extends Film + introduces ContentType enum
src/main/kotlin/com/project/movienight/config/JellyfinIntegrationProperties.kt Configuration properties for Jellyfin integration
src/main/kotlin/com/project/movienight/application/services/UserService.kt Supports updating jellyfinUserId
src/main/kotlin/com/project/movienight/application/services/UserPreferencesService.kt Service for upserting/getting preferences
src/main/kotlin/com/project/movienight/application/services/RecommendationService.kt Recommendation scoring + retrieval
src/main/kotlin/com/project/movienight/application/services/JellyfinSyncService.kt Scheduled/manual Jellyfin library sync
src/main/kotlin/com/project/movienight/application/services/JellyfinEventService.kt Jellyfin event handling + marking viewed
src/main/kotlin/com/project/movienight/application/services/FilmService.kt Persists extended film fields
src/main/kotlin/com/project/movienight/application/services/FilmRatingService.kt Rating submission + listing
src/main/kotlin/com/project/movienight/application/services/FilmLibraryService.kt Library entries: add/remove/mark viewed/list
src/main/kotlin/com/project/movienight/application/ports/output/UserPreferencesRepositoryPort.kt Port for preferences persistence
src/main/kotlin/com/project/movienight/application/ports/output/JellyfinSyncStateRepositoryPort.kt Port for sync state persistence
src/main/kotlin/com/project/movienight/application/ports/output/FilmRepositoryPort.kt Adds Jellyfin lookup methods
src/main/kotlin/com/project/movienight/application/ports/output/FilmRatingRepositoryPort.kt New ratings repository port
src/main/kotlin/com/project/movienight/application/ports/output/FilmLibraryRepositoryPort.kt Adds lookup by (userId, filmId)
src/main/kotlin/com/project/movienight/application/ports/input/UserUseCase.kt Adds jellyfinUserId to EditUserCommand
src/main/kotlin/com/project/movienight/application/ports/input/UserPreferencesUseCase.kt Preferences use cases + command
src/main/kotlin/com/project/movienight/application/ports/input/GetRecommendationsUseCase.kt Recommendations use case + query
src/main/kotlin/com/project/movienight/application/ports/input/FilmUseCase.kt Adds extended fields to film commands
src/main/kotlin/com/project/movienight/application/ports/input/FilmRatingUseCase.kt Rating use cases + command
src/main/kotlin/com/project/movienight/application/ports/input/FilmLibraryUseCase.kt Adds mark-viewed + list entries use cases
src/main/kotlin/com/project/movienight/adapters/web/UserPreferencesController.kt REST API for preferences
src/main/kotlin/com/project/movienight/adapters/web/UserController.kt Wires jellyfinUserId into edit endpoint
src/main/kotlin/com/project/movienight/adapters/web/RecommendationController.kt REST API for recommendations
src/main/kotlin/com/project/movienight/adapters/web/JellyfinSyncController.kt REST API for manual sync + sync state
src/main/kotlin/com/project/movienight/adapters/web/JellyfinEventsController.kt REST API for Jellyfin event ingestion
src/main/kotlin/com/project/movienight/adapters/web/FilmRatingController.kt REST API for rating submission/listing
src/main/kotlin/com/project/movienight/adapters/web/FilmLibraryController.kt REST API updates for entries + mark viewed
src/main/kotlin/com/project/movienight/adapters/web/FilmController.kt Parses contentType + passes extended film fields
src/main/kotlin/com/project/movienight/adapters/web/dto/response/UserResponse.kt Adds jellyfinUserId to response DTO
src/main/kotlin/com/project/movienight/adapters/web/dto/response/UserPreferencesResponse.kt New preferences response DTO
src/main/kotlin/com/project/movienight/adapters/web/dto/response/FilmResponse.kt Extends film response DTO fields
src/main/kotlin/com/project/movienight/adapters/web/dto/response/FilmRatingResponse.kt New rating response DTO
src/main/kotlin/com/project/movienight/adapters/web/dto/response/FilmLibraryResponse.kt Adds watchedAt to library response DTO
src/main/kotlin/com/project/movienight/adapters/web/dto/request/UpsertUserPreferencesRequest.kt New preferences request DTO
src/main/kotlin/com/project/movienight/adapters/web/dto/request/RateFilmRequest.kt New rating request DTO
src/main/kotlin/com/project/movienight/adapters/web/dto/request/JellyfinEventRequest.kt New Jellyfin event request DTO
src/main/kotlin/com/project/movienight/adapters/web/dto/request/EditUserRequest.kt Adds jellyfinUserId to request DTO
src/main/kotlin/com/project/movienight/adapters/web/dto/request/EditFilmRequest.kt Extends film edit request DTO fields
src/main/kotlin/com/project/movienight/adapters/web/dto/request/CreateFilmRequest.kt Extends film create request DTO fields
src/main/kotlin/com/project/movienight/adapters/persistence/jdbc/UserRepository.kt Persists/reads jellyfin_user_id column
src/main/kotlin/com/project/movienight/adapters/persistence/jdbc/UserPreferencesRepository.kt JDBC persistence for user preferences
src/main/kotlin/com/project/movienight/adapters/persistence/jdbc/support/DelimitedValueCodec.kt Encodes/decodes delimited list/map fields
src/main/kotlin/com/project/movienight/adapters/persistence/jdbc/JellyfinSyncStateRepository.kt JDBC persistence for sync state
src/main/kotlin/com/project/movienight/adapters/persistence/jdbc/JellyfinEventRepository.kt JDBC persistence for jellyfin_events
src/main/kotlin/com/project/movienight/adapters/persistence/jdbc/FilmRepository.kt Persists/reads expanded film fields
src/main/kotlin/com/project/movienight/adapters/persistence/jdbc/FilmRatingRepository.kt JDBC persistence for film ratings
src/main/kotlin/com/project/movienight/adapters/persistence/jdbc/FilmLibraryRepository.kt Persists/reads watchedAt + lookup by user/film
src/main/kotlin/com/project/movienight/adapters/persistence/entity/UserPreferencesEntity.kt Entity mapping for user preferences
src/main/kotlin/com/project/movienight/adapters/persistence/entity/UserEntity.kt Adds jellyfinUserId in mapping
src/main/kotlin/com/project/movienight/adapters/persistence/entity/JellyfinSyncStateEntity.kt Entity mapping for sync state
src/main/kotlin/com/project/movienight/adapters/persistence/entity/FilmRatingEntity.kt Entity mapping for ratings
src/main/kotlin/com/project/movienight/adapters/metrics/BusinessMetricsService.kt Adds business metrics counters/timers
src/main/kotlin/com/project/movienight/adapters/jellyfin/JellyfinApiClient.kt Jellyfin HTTP client + snapshot mapping
config/detekt/detekt.yaml Updates detekt rule configuration
Comments suppressed due to low confidence (1)

src/main/kotlin/com/project/movienight/application/services/FilmLibraryService.kt:141

  • findByUserId / findByUserAndFilmId load all favorites and then filter in memory. Since FilmLibraryRepositoryPort now exposes findByUserIdAndFilmId, FilmLibraryService should call that (and ideally add a findByUserId query) to avoid full-table scans and reduce memory/latency as favorites grow.

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

## Pull request overview This PR expands the backend data model and APIs to support richer film metadata, user preferences/ratings, recommendations, and a Jellyfin integration (sync + event ingestion), along with persistence and metrics support. **Changes:** - Extend core domain + DB schema for films, library entries (watchedAt), user preferences, film ratings, and Jellyfin sync/event state. - Add new application services and REST controllers for preferences, ratings, recommendations, and Jellyfin sync/events. - Add Micrometer business metrics and supporting JDBC repositories/entities. ### Reviewed changes Copilot reviewed 70 out of 70 changed files in this pull request and generated 6 comments. <details> <summary>Show a summary per file</summary> | File | Description | | ---- | ----------- | | src/test/kotlin/com/project/movienight/RecommendationSmokeTest.kt | End-to-end smoke test for preferences/ratings/recommendations | | src/test/kotlin/com/project/movienight/application/services/FilmLibraryServiceTest.kt | Updates FilmLibraryService unit tests for new behavior | | src/test/kotlin/com/project/movienight/adapters/persistence/entity/UserEntityMappingTest.kt | Extends mapping test for jellyfinUserId | | src/main/resources/db/migration/V3__jellyfin_events.sql | Adds jellyfin_events table for idempotency/auditing | | src/main/resources/db/migration/V1__init.sql | Expands initial schema (users/films/favorites/etc.) | | src/main/resources/application.yaml | Adds Jellyfin integration config | | src/main/kotlin/com/project/movienight/MovieNightApplication.kt | Enables Spring scheduling | | src/main/kotlin/com/project/movienight/domain/model/UserPreferences.kt | New domain model for user preferences | | src/main/kotlin/com/project/movienight/domain/model/User.kt | Adds preferences + jellyfinUserId to User | | src/main/kotlin/com/project/movienight/domain/model/RecommendationContext.kt | Adds recommendation context/result models | | src/main/kotlin/com/project/movienight/domain/model/JellyfinSyncState.kt | Adds Jellyfin sync state/summary models | | src/main/kotlin/com/project/movienight/domain/model/FilmRating.kt | Adds film rating domain model | | src/main/kotlin/com/project/movienight/domain/model/FilmLibrary.kt | Adds watchedAt to library entries | | src/main/kotlin/com/project/movienight/domain/model/Film.kt | Extends Film + introduces ContentType enum | | src/main/kotlin/com/project/movienight/config/JellyfinIntegrationProperties.kt | Configuration properties for Jellyfin integration | | src/main/kotlin/com/project/movienight/application/services/UserService.kt | Supports updating jellyfinUserId | | src/main/kotlin/com/project/movienight/application/services/UserPreferencesService.kt | Service for upserting/getting preferences | | src/main/kotlin/com/project/movienight/application/services/RecommendationService.kt | Recommendation scoring + retrieval | | src/main/kotlin/com/project/movienight/application/services/JellyfinSyncService.kt | Scheduled/manual Jellyfin library sync | | src/main/kotlin/com/project/movienight/application/services/JellyfinEventService.kt | Jellyfin event handling + marking viewed | | src/main/kotlin/com/project/movienight/application/services/FilmService.kt | Persists extended film fields | | src/main/kotlin/com/project/movienight/application/services/FilmRatingService.kt | Rating submission + listing | | src/main/kotlin/com/project/movienight/application/services/FilmLibraryService.kt | Library entries: add/remove/mark viewed/list | | src/main/kotlin/com/project/movienight/application/ports/output/UserPreferencesRepositoryPort.kt | Port for preferences persistence | | src/main/kotlin/com/project/movienight/application/ports/output/JellyfinSyncStateRepositoryPort.kt | Port for sync state persistence | | src/main/kotlin/com/project/movienight/application/ports/output/FilmRepositoryPort.kt | Adds Jellyfin lookup methods | | src/main/kotlin/com/project/movienight/application/ports/output/FilmRatingRepositoryPort.kt | New ratings repository port | | src/main/kotlin/com/project/movienight/application/ports/output/FilmLibraryRepositoryPort.kt | Adds lookup by (userId, filmId) | | src/main/kotlin/com/project/movienight/application/ports/input/UserUseCase.kt | Adds jellyfinUserId to EditUserCommand | | src/main/kotlin/com/project/movienight/application/ports/input/UserPreferencesUseCase.kt | Preferences use cases + command | | src/main/kotlin/com/project/movienight/application/ports/input/GetRecommendationsUseCase.kt | Recommendations use case + query | | src/main/kotlin/com/project/movienight/application/ports/input/FilmUseCase.kt | Adds extended fields to film commands | | src/main/kotlin/com/project/movienight/application/ports/input/FilmRatingUseCase.kt | Rating use cases + command | | src/main/kotlin/com/project/movienight/application/ports/input/FilmLibraryUseCase.kt | Adds mark-viewed + list entries use cases | | src/main/kotlin/com/project/movienight/adapters/web/UserPreferencesController.kt | REST API for preferences | | src/main/kotlin/com/project/movienight/adapters/web/UserController.kt | Wires jellyfinUserId into edit endpoint | | src/main/kotlin/com/project/movienight/adapters/web/RecommendationController.kt | REST API for recommendations | | src/main/kotlin/com/project/movienight/adapters/web/JellyfinSyncController.kt | REST API for manual sync + sync state | | src/main/kotlin/com/project/movienight/adapters/web/JellyfinEventsController.kt | REST API for Jellyfin event ingestion | | src/main/kotlin/com/project/movienight/adapters/web/FilmRatingController.kt | REST API for rating submission/listing | | src/main/kotlin/com/project/movienight/adapters/web/FilmLibraryController.kt | REST API updates for entries + mark viewed | | src/main/kotlin/com/project/movienight/adapters/web/FilmController.kt | Parses contentType + passes extended film fields | | src/main/kotlin/com/project/movienight/adapters/web/dto/response/UserResponse.kt | Adds jellyfinUserId to response DTO | | src/main/kotlin/com/project/movienight/adapters/web/dto/response/UserPreferencesResponse.kt | New preferences response DTO | | src/main/kotlin/com/project/movienight/adapters/web/dto/response/FilmResponse.kt | Extends film response DTO fields | | src/main/kotlin/com/project/movienight/adapters/web/dto/response/FilmRatingResponse.kt | New rating response DTO | | src/main/kotlin/com/project/movienight/adapters/web/dto/response/FilmLibraryResponse.kt | Adds watchedAt to library response DTO | | src/main/kotlin/com/project/movienight/adapters/web/dto/request/UpsertUserPreferencesRequest.kt | New preferences request DTO | | src/main/kotlin/com/project/movienight/adapters/web/dto/request/RateFilmRequest.kt | New rating request DTO | | src/main/kotlin/com/project/movienight/adapters/web/dto/request/JellyfinEventRequest.kt | New Jellyfin event request DTO | | src/main/kotlin/com/project/movienight/adapters/web/dto/request/EditUserRequest.kt | Adds jellyfinUserId to request DTO | | src/main/kotlin/com/project/movienight/adapters/web/dto/request/EditFilmRequest.kt | Extends film edit request DTO fields | | src/main/kotlin/com/project/movienight/adapters/web/dto/request/CreateFilmRequest.kt | Extends film create request DTO fields | | src/main/kotlin/com/project/movienight/adapters/persistence/jdbc/UserRepository.kt | Persists/reads jellyfin_user_id column | | src/main/kotlin/com/project/movienight/adapters/persistence/jdbc/UserPreferencesRepository.kt | JDBC persistence for user preferences | | src/main/kotlin/com/project/movienight/adapters/persistence/jdbc/support/DelimitedValueCodec.kt | Encodes/decodes delimited list/map fields | | src/main/kotlin/com/project/movienight/adapters/persistence/jdbc/JellyfinSyncStateRepository.kt | JDBC persistence for sync state | | src/main/kotlin/com/project/movienight/adapters/persistence/jdbc/JellyfinEventRepository.kt | JDBC persistence for jellyfin_events | | src/main/kotlin/com/project/movienight/adapters/persistence/jdbc/FilmRepository.kt | Persists/reads expanded film fields | | src/main/kotlin/com/project/movienight/adapters/persistence/jdbc/FilmRatingRepository.kt | JDBC persistence for film ratings | | src/main/kotlin/com/project/movienight/adapters/persistence/jdbc/FilmLibraryRepository.kt | Persists/reads watchedAt + lookup by user/film | | src/main/kotlin/com/project/movienight/adapters/persistence/entity/UserPreferencesEntity.kt | Entity mapping for user preferences | | src/main/kotlin/com/project/movienight/adapters/persistence/entity/UserEntity.kt | Adds jellyfinUserId in mapping | | src/main/kotlin/com/project/movienight/adapters/persistence/entity/JellyfinSyncStateEntity.kt | Entity mapping for sync state | | src/main/kotlin/com/project/movienight/adapters/persistence/entity/FilmRatingEntity.kt | Entity mapping for ratings | | src/main/kotlin/com/project/movienight/adapters/metrics/BusinessMetricsService.kt | Adds business metrics counters/timers | | src/main/kotlin/com/project/movienight/adapters/jellyfin/JellyfinApiClient.kt | Jellyfin HTTP client + snapshot mapping | | config/detekt/detekt.yaml | Updates detekt rule configuration | </details> <details> <summary>Comments suppressed due to low confidence (1)</summary> **src/main/kotlin/com/project/movienight/application/services/FilmLibraryService.kt:141** * `findByUserId` / `findByUserAndFilmId` load *all* favorites and then filter in memory. Since `FilmLibraryRepositoryPort` now exposes `findByUserIdAndFilmId`, `FilmLibraryService` should call that (and ideally add a `findByUserId` query) to avoid full-table scans and reduce memory/latency as favorites grow. </details> --- 💡 <a href="/devitq/movienight-backend/new/develop?filename=.github/instructions/*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.
@@ -0,0 +1,143 @@
package com.project.movienight.adapters.jellyfin
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-05-20 16:51:55 +00:00

The HTTP status check is inverted: check(response.statusCode() !in 200..299) will throw on successful (2xx) responses and silently accept failures. This makes all Jellyfin calls fail in normal operation. Flip the condition (or use require(response.statusCode() in 200..299)) so non-2xx responses raise an error.

The HTTP status check is inverted: `check(response.statusCode() !in 200..299)` will throw on successful (2xx) responses and silently accept failures. This makes all Jellyfin calls fail in normal operation. Flip the condition (or use `require(response.statusCode() in 200..299)`) so non-2xx responses raise an error.
@@ -0,0 +36,4 @@
throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid plugin token")
}
}
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-05-20 16:51:56 +00:00

This endpoint processes Jellyfin events even when the integration is disabled. Consider rejecting with 404/409/503 (or simply no-op) when integrations.jellyfin.enabled is false to avoid unexpected writes when Jellyfin integration is turned off.

This endpoint processes Jellyfin events even when the integration is disabled. Consider rejecting with 404/409/503 (or simply no-op) when `integrations.jellyfin.enabled` is false to avoid unexpected writes when Jellyfin integration is turned off.
@@ -20,70 +24,105 @@ import java.util.UUID
class FilmLibraryService(
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-05-20 16:51:55 +00:00

create() persists a FilmLibrary row with filmId = libraryId, but favorites.film_id has an FK to films(id) (V1__init.sql). This will insert a non-existent film id and fail at runtime. Consider making library creation a no-op (create only when adding films), or introduce a separate libraries table; in any case, don’t write a placeholder entry with a fake filmId.

This issue also appears on line 133 of the same file.

`create()` persists a FilmLibrary row with `filmId = libraryId`, but `favorites.film_id` has an FK to `films(id)` (V1__init.sql). This will insert a non-existent film id and fail at runtime. Consider making library creation a no-op (create only when adding films), or introduce a separate `libraries` table; in any case, don’t write a placeholder entry with a fake `filmId`. This issue also appears on line 133 of the same file.
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-05-20 16:51:56 +00:00

Logging format string has a stray trailing quote: descriptionLength={}'. This will produce confusing log output and can break log parsing. Remove the extra ' so the message template matches the arguments.

Logging format string has a stray trailing quote: `descriptionLength={}'`. This will produce confusing log output and can break log parsing. Remove the extra `'` so the message template matches the arguments.
@@ -0,0 +1,81 @@
package com.project.movienight.application.services
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-05-20 16:51:55 +00:00

Idempotency handling is unsafe: the event is inserted before processing, so if processing fails (exception or early return), retries will be skipped forever because exists(eventId) becomes true. Also, the exists + save sequence is race-prone and can still double-process concurrent requests. Prefer a single insert with ON CONFLICT DO NOTHING and only proceed when the insert actually happened (updatedRows==1), and/or store a processed status so failed events can be retried.

Idempotency handling is unsafe: the event is inserted before processing, so if processing fails (exception or early return), retries will be skipped forever because `exists(eventId)` becomes true. Also, the `exists` + `save` sequence is race-prone and can still double-process concurrent requests. Prefer a single insert with `ON CONFLICT DO NOTHING` and only proceed when the insert actually happened (updatedRows==1), and/or store a processed status so failed events can be retried.
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-05-20 16:51:54 +00:00

Avoid modifying an existing Flyway migration (V1). Changing previously-applied migration files will cause Flyway checksum validation failures on any environment that has already run V1, blocking startup/migrate. Add a new migration (e.g., V4__extend_schema.sql) with ALTER TABLE statements instead.

Avoid modifying an existing Flyway migration (V1). Changing previously-applied migration files will cause Flyway checksum validation failures on any environment that has already run V1, blocking startup/migrate. Add a new migration (e.g., V4__extend_schema.sql) with ALTER TABLE statements instead.
copilot-swe-agent[bot] (Migrated from github.com) reviewed 2026-05-20 18:33:50 +00:00
copilot-swe-agent[bot] (Migrated from github.com) commented 2026-05-20 18:33:50 +00:00

Fixed in 50923e2. I restored V1__init.sql to baseline and moved the schema extensions into a new migration V6__extend_schema.sql so V1 is no longer modified. UI screenshot: N/A (backend-only change).

Fixed in 50923e2. I restored `V1__init.sql` to baseline and moved the schema extensions into a new migration `V6__extend_schema.sql` so V1 is no longer modified. UI screenshot: N/A (backend-only change).
copilot-swe-agent[bot] (Migrated from github.com) reviewed 2026-05-20 18:33:53 +00:00
@@ -20,70 +24,105 @@ import java.util.UUID
class FilmLibraryService(
copilot-swe-agent[bot] (Migrated from github.com) commented 2026-05-20 18:33:53 +00:00

Fixed in 50923e2. create() no longer persists a placeholder row with filmId = libraryId; it now avoids creating fake library entries. UI screenshot: N/A (backend-only change).

Fixed in 50923e2. `create()` no longer persists a placeholder row with `filmId = libraryId`; it now avoids creating fake library entries. UI screenshot: N/A (backend-only change).
copilot-swe-agent[bot] (Migrated from github.com) reviewed 2026-05-20 18:33:56 +00:00
@@ -0,0 +1,143 @@
package com.project.movienight.adapters.jellyfin
copilot-swe-agent[bot] (Migrated from github.com) commented 2026-05-20 18:33:56 +00:00

Fixed in 50923e2. I corrected the status check to require response.statusCode() in 200..299 so non-2xx responses now fail as intended. UI screenshot: N/A (backend-only change).

Fixed in 50923e2. I corrected the status check to require `response.statusCode() in 200..299` so non-2xx responses now fail as intended. UI screenshot: N/A (backend-only change).
copilot-swe-agent[bot] (Migrated from github.com) reviewed 2026-05-20 18:33:58 +00:00
@@ -0,0 +1,81 @@
package com.project.movienight.application.services
copilot-swe-agent[bot] (Migrated from github.com) commented 2026-05-20 18:33:58 +00:00

Fixed in 50923e2. I removed the exists + save flow and now gate processing on a single insert (ON CONFLICT DO NOTHING via affected rows). For failures/early-return cases, the inserted event is deleted so retries remain possible. UI screenshot: N/A (backend-only change).

Fixed in 50923e2. I removed the `exists + save` flow and now gate processing on a single insert (`ON CONFLICT DO NOTHING` via affected rows). For failures/early-return cases, the inserted event is deleted so retries remain possible. UI screenshot: N/A (backend-only change).
copilot-swe-agent[bot] (Migrated from github.com) reviewed 2026-05-20 18:34:01 +00:00
@@ -0,0 +36,4 @@
throw ResponseStatusException(HttpStatus.UNAUTHORIZED, "Invalid plugin token")
}
}
copilot-swe-agent[bot] (Migrated from github.com) commented 2026-05-20 18:34:01 +00:00

Fixed in 50923e2. The events endpoint now rejects requests with 503 Service Unavailable when integrations.jellyfin.enabled is false. UI screenshot: N/A (backend-only change).

Fixed in 50923e2. The events endpoint now rejects requests with `503 Service Unavailable` when `integrations.jellyfin.enabled` is false. UI screenshot: N/A (backend-only change).
copilot-swe-agent[bot] (Migrated from github.com) reviewed 2026-05-20 18:34:05 +00:00
copilot-swe-agent[bot] (Migrated from github.com) commented 2026-05-20 18:34:05 +00:00

Fixed in 50923e2. I removed the stray trailing quote from the log template string. UI screenshot: N/A (backend-only change).

Fixed in 50923e2. I removed the stray trailing quote from the log template string. UI screenshot: N/A (backend-only change).
Sign in to join this conversation.