mirror of
https://github.com/BrenBroZAYT/gameyfin.git
synced 2026-06-13 16:40:01 +00:00
Release 2.1.2 (#735)
* Fix multiple db issues (#734) * Bump version to 2.1.2-preview * Fix game image uniqueness (#733) * Fix faulty image cleanup (#733) * Fix faulty image cleanup (#733) * Adjust version to contain preview suffix * Bump gradle/actions from 4 to 5 (#737) Bumps [gradle/actions](https://github.com/gradle/actions) from 4 to 5. - [Release notes](https://github.com/gradle/actions/releases) - [Commits](https://github.com/gradle/actions/compare/v4...v5) --- updated-dependencies: - dependency-name: gradle/actions dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
@@ -79,7 +79,7 @@ jobs:
|
||||
distribution: 'temurin'
|
||||
java-version: '21'
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
uses: gradle/actions/setup-gradle@v5
|
||||
|
||||
- name: Run production build
|
||||
env:
|
||||
@@ -135,7 +135,7 @@ jobs:
|
||||
java-version: '21'
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
uses: gradle/actions/setup-gradle@v5
|
||||
|
||||
- name: Build and push Plugin-API
|
||||
run: ./gradlew publishAndReleaseToMavenCentral --no-configuration-cache
|
||||
|
||||
@@ -94,7 +94,11 @@ class ImageService(
|
||||
// Always try to get existing image first to avoid detached entity issues
|
||||
val existingImage = imageRepository.findByOriginalUrl(image.originalUrl)
|
||||
|
||||
if (existingImage != null && existingImage.contentId != null) {
|
||||
// Check if the existing image has valid content
|
||||
val existingImageHasValidContent = (existingImage != null && imageHasValidContent(existingImage))
|
||||
|
||||
// If the existing image has valid content we can just associate it instead of downloading again
|
||||
if (existingImageHasValidContent && existingImage.contentId != null) {
|
||||
// If we have an existing image with content, associate it with the current image
|
||||
imageContentStore.associate(image, existingImage.contentId)
|
||||
// Update the current image's content metadata
|
||||
@@ -104,7 +108,7 @@ class ImageService(
|
||||
return
|
||||
}
|
||||
|
||||
// If no existing image or existing image has no content, download it
|
||||
// If no existing image or existing image has no valid content, download it
|
||||
TikaInputStream.get { URI.create(image.originalUrl).toURL().openStream() }.use { input ->
|
||||
image.mimeType = tika.detect(input)
|
||||
imageContentStore.setContent(image, input)
|
||||
@@ -135,8 +139,8 @@ class ImageService(
|
||||
val isImageStillInUse = gameRepository.existsByImage(imageId) || userRepository.existsByAvatar(imageId)
|
||||
|
||||
if (!isImageStillInUse) {
|
||||
imageContentStore.unsetContent(image)
|
||||
imageRepository.delete(image)
|
||||
imageContentStore.unsetContent(image)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,4 +149,9 @@ class ImageService(
|
||||
imageRepository.save(image)
|
||||
return imageContentStore.setContent(image, content)
|
||||
}
|
||||
|
||||
private fun imageHasValidContent(image: Image): Boolean {
|
||||
val imageContent = imageContentStore.getContent(image)
|
||||
return imageContent != null && image.contentLength != null && image.contentLength!! > 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
-- Flyway Migration: V2.1.2
|
||||
-- Purpose: Remove unintended single-column uniqueness on GAME_IMAGES.IMAGES_ID
|
||||
-- (leftover unique constraint / index from initial schema) and
|
||||
-- replace it with a proper composite uniqueness over (GAME_ID, IMAGES_ID)
|
||||
-- allowing the same image to be linked to multiple games while
|
||||
-- preventing duplicate pairs.
|
||||
--
|
||||
-- Context Recap:
|
||||
-- * Initial table GAME_IMAGES had: IMAGES_ID UNIQUE (constraint UKBDE7M3TKHIEEYBINM2ED0B6X1)
|
||||
-- * V2.1.0.1 only renamed that constraint (to UQ_GAME_IMAGES_IMAGE_ID if present) – did not drop it.
|
||||
-- * Attempting to drop unique index now shows: "Index ... belongs to constraint FK_GAME_IMAGES_IMAGE".
|
||||
-- This means H2 re-used (or bound) the existing unique index for the foreign key, so we must drop the FK first.
|
||||
-- * Prior partial execution of an earlier draft of this migration might already have created
|
||||
-- composite index UX_GAME_IMAGES_GAME_IMAGE. Script is idempotent.
|
||||
-- Strategy (idempotent):
|
||||
-- 1. Drop foreign key FK_GAME_IMAGES_IMAGE (and legacy hashed name) to free the index.
|
||||
-- 2. Drop the old unique constraint names (hashed and friendly) if they still exist.
|
||||
-- 3. Drop lingering unique indexes (hashed + variants, including the one ending with _INDEX_C).
|
||||
-- 4. Create a NON-UNIQUE index on IMAGES_ID.
|
||||
-- 5. Create (or ensure) composite UNIQUE index (GAME_ID, IMAGES_ID).
|
||||
-- 6. Recreate foreign key FK_GAME_IMAGES_IMAGE.
|
||||
-- 7. (Optional) Verification queries shown in comments.
|
||||
|
||||
/******************************************************************************************
|
||||
* 1. Drop foreign key so bound unique index can be removed
|
||||
******************************************************************************************/
|
||||
ALTER TABLE GAME_IMAGES
|
||||
DROP CONSTRAINT IF EXISTS FK_GAME_IMAGES_IMAGE;
|
||||
-- Legacy hashed name (in case rename migration not applied yet)
|
||||
ALTER TABLE GAME_IMAGES
|
||||
DROP CONSTRAINT IF EXISTS FK5YWV1DMXCM2VSQUEB7RHQ3JK9;
|
||||
|
||||
/******************************************************************************************
|
||||
* 2. Drop legacy/friendly unique constraints (if still defined)
|
||||
******************************************************************************************/
|
||||
ALTER TABLE GAME_IMAGES
|
||||
DROP CONSTRAINT IF EXISTS UKBDE7M3TKHIEEYBINM2ED0B6X1; -- original hashed name
|
||||
ALTER TABLE GAME_IMAGES
|
||||
DROP CONSTRAINT IF EXISTS UQ_GAME_IMAGES_IMAGE_ID;
|
||||
-- friendly name
|
||||
|
||||
/******************************************************************************************
|
||||
* 3. Drop lingering unique indexes that may remain after constraint drop
|
||||
* (H2 auto-named variants; include conservative list). Safe if absent.
|
||||
******************************************************************************************/
|
||||
DROP INDEX IF EXISTS UKBDE7M3TKHIEEYBINM2ED0B6X1_INDEX_C;
|
||||
|
||||
/******************************************************************************************
|
||||
* 4. Create supporting NON-UNIQUE index for IMAGES_ID (only if missing)
|
||||
******************************************************************************************/
|
||||
CREATE INDEX IF NOT EXISTS IDX_GAME_IMAGES_IMAGE ON GAME_IMAGES (IMAGES_ID);
|
||||
|
||||
/******************************************************************************************
|
||||
* 5. Create / ensure composite uniqueness (prevents duplicate pairs, allows reuse of images)
|
||||
******************************************************************************************/
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS UX_GAME_IMAGES_GAME_IMAGE ON GAME_IMAGES (GAME_ID, IMAGES_ID);
|
||||
|
||||
/******************************************************************************************
|
||||
* 6. Recreate foreign key (H2 will use existing non-unique index or create one silently)
|
||||
******************************************************************************************/
|
||||
ALTER TABLE GAME_IMAGES
|
||||
ADD CONSTRAINT FK_GAME_IMAGES_IMAGE FOREIGN KEY (IMAGES_ID) REFERENCES IMAGE (ID);
|
||||
-- (FK to GAME side should already exist; keep idempotent recreation separate if ever needed.)
|
||||
|
||||
/******************************************************************************************
|
||||
* 7. (Optional verification after migration)
|
||||
* -- SELECT CONSTRAINT_NAME, CONSTRAINT_TYPE FROM INFORMATION_SCHEMA.CONSTRAINTS WHERE TABLE_NAME='GAME_IMAGES';
|
||||
* -- SELECT INDEX_NAME, NON_UNIQUE, COLUMN_NAME FROM INFORMATION_SCHEMA.INDEXES WHERE TABLE_NAME='GAME_IMAGES';
|
||||
* Expected:
|
||||
* Constraint FK_GAME_IMAGES_IMAGE present (TYPE='REFERENTIAL').
|
||||
* Composite unique index UX_GAME_IMAGES_GAME_IMAGE (NON_UNIQUE=FALSE, columns GAME_ID, IMAGES_ID).
|
||||
* Non-unique index IDX_GAME_IMAGES_IMAGE (NON_UNIQUE=TRUE, column IMAGES_ID).
|
||||
* No remaining single-column unique index enforcing uniqueness of IMAGES_ID alone.
|
||||
******************************************************************************************/
|
||||
-- End of migration.
|
||||
@@ -0,0 +1,33 @@
|
||||
-- Flyway Migration: V2.1.2.2
|
||||
-- Purpose: Remove orphan (unreferenced) IMAGE rows that are no longer linked to any
|
||||
-- GAME (cover/header), GAME_IMAGES (many-to-many screenshots), or USERS (avatar).
|
||||
--
|
||||
-- Rationale:
|
||||
-- A previous bug deleted content (files) before deleting the DB row, allowing the
|
||||
-- IMAGE entity to remain referenced or resurrected. After fixing logic order, we
|
||||
-- now perform a one-time cleanup of rows that have no remaining foreign key references.
|
||||
--
|
||||
-- Safety:
|
||||
-- The DELETE only targets rows for which no referencing rows exist; it will not
|
||||
-- violate FK constraints. Uses NOT EXISTS predicates (safer than NOT IN when NULLs present).
|
||||
--
|
||||
-- Idempotency:
|
||||
-- Running this migration again (e.g., in replayed environments) is harmless because
|
||||
-- once removed, those rows no longer exist.
|
||||
--
|
||||
-- Verification (optional; run manually):
|
||||
-- SELECT COUNT(*) FROM IMAGE i
|
||||
-- WHERE NOT EXISTS (SELECT 1 FROM GAME g WHERE g.COVER_IMAGE_ID = i.ID)
|
||||
-- AND NOT EXISTS (SELECT 1 FROM GAME g2 WHERE g2.HEADER_IMAGE_ID = i.ID)
|
||||
-- AND NOT EXISTS (SELECT 1 FROM GAME_IMAGES gi WHERE gi.IMAGES_ID = i.ID)
|
||||
-- AND NOT EXISTS (SELECT 1 FROM USERS u WHERE u.AVATAR_ID = i.ID);
|
||||
-- -- Expect 0 after delete.
|
||||
|
||||
DELETE FROM IMAGE i
|
||||
WHERE NOT EXISTS (SELECT 1 FROM GAME g WHERE g.COVER_IMAGE_ID = i.ID)
|
||||
AND NOT EXISTS (SELECT 1 FROM GAME g2 WHERE g2.HEADER_IMAGE_ID = i.ID)
|
||||
AND NOT EXISTS (SELECT 1 FROM GAME_IMAGES gi WHERE gi.IMAGES_ID = i.ID)
|
||||
AND NOT EXISTS (SELECT 1 FROM USERS u WHERE u.AVATAR_ID = i.ID);
|
||||
|
||||
-- End of migration.
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
|
||||
import java.nio.file.Files
|
||||
|
||||
group = "org.gameyfin"
|
||||
version = "2.1.1"
|
||||
version = "2.1.2-preview"
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
|
||||
Reference in New Issue
Block a user