From daf3decbaece7f4a466563b12c24bd94ef136a78 Mon Sep 17 00:00:00 2001 From: MiniDigger | Martin Date: Thu, 9 Jan 2025 19:40:50 +0100 Subject: [PATCH] feat: refactor version queries, remove platform download table --- .../io/papermc/hangar/config/JDBIConfig.java | 14 ++++++ .../downloads/ProjectVersionDownloadsDAO.java | 44 ++----------------- .../ProjectVersionDownloadTable.java | 25 ++++++++++- ...ojectVersionDownloadTableWithPlatform.java | 17 ------- .../ProjectVersionPlatformDownloadTable.java | 40 ----------------- .../internal/versions/DownloadService.java | 29 ++++-------- .../internal/versions/JarScanningService.java | 12 ++--- .../internal/versions/VersionFactory.java | 39 ++++++---------- .../internal/versions/VersionService.java | 9 +--- .../V1.17.0__project_version_cleanup.sql | 3 ++ .../resources/db/migration/V1.17.1__migration | 4 ++ .../resources/db/migration/V1.17.2__cleanup | 5 +++ .../[project]/versions/[version]/scan.vue | 8 +++- 13 files changed, 85 insertions(+), 164 deletions(-) delete mode 100644 backend/src/main/java/io/papermc/hangar/model/db/versions/downloads/ProjectVersionDownloadTableWithPlatform.java delete mode 100644 backend/src/main/java/io/papermc/hangar/model/db/versions/downloads/ProjectVersionPlatformDownloadTable.java create mode 100644 backend/src/main/resources/db/migration/V1.17.0__project_version_cleanup.sql create mode 100644 backend/src/main/resources/db/migration/V1.17.1__migration create mode 100644 backend/src/main/resources/db/migration/V1.17.2__cleanup diff --git a/backend/src/main/java/io/papermc/hangar/config/JDBIConfig.java b/backend/src/main/java/io/papermc/hangar/config/JDBIConfig.java index 460b69bf5..3d9f05673 100644 --- a/backend/src/main/java/io/papermc/hangar/config/JDBIConfig.java +++ b/backend/src/main/java/io/papermc/hangar/config/JDBIConfig.java @@ -5,10 +5,12 @@ import io.papermc.hangar.db.customtypes.JobState; import io.papermc.hangar.db.customtypes.PGLoggedAction; import io.papermc.hangar.db.customtypes.RoleCategory; +import io.papermc.hangar.model.common.Platform; import java.util.List; import java.util.UUID; import javax.sql.DataSource; import org.jdbi.v3.core.Jdbi; +import org.jdbi.v3.core.array.SqlArrayType; import org.jdbi.v3.core.mapper.ColumnMapper; import org.jdbi.v3.core.mapper.RowMapper; import org.jdbi.v3.core.mapper.RowMapperFactory; @@ -58,6 +60,18 @@ public Jdbi jdbi(final DataSource dataSource, final List jdbiPlugins config.registerCustomType(JobState.class, "job_state"); config.registerCustomType(JSONB.class, "jsonb"); + jdbi.registerArrayType(new SqlArrayType() { + @Override + public String getTypeName() { + return "integer"; + } + + @Override + public Integer convertArrayElement(final Platform element) { + return element.ordinal(); + } + }); + return jdbi; } } diff --git a/backend/src/main/java/io/papermc/hangar/db/dao/internal/table/versions/downloads/ProjectVersionDownloadsDAO.java b/backend/src/main/java/io/papermc/hangar/db/dao/internal/table/versions/downloads/ProjectVersionDownloadsDAO.java index 1f722a9e5..244717baa 100644 --- a/backend/src/main/java/io/papermc/hangar/db/dao/internal/table/versions/downloads/ProjectVersionDownloadsDAO.java +++ b/backend/src/main/java/io/papermc/hangar/db/dao/internal/table/versions/downloads/ProjectVersionDownloadsDAO.java @@ -2,35 +2,25 @@ import io.papermc.hangar.model.common.Platform; import io.papermc.hangar.model.db.versions.downloads.ProjectVersionDownloadTable; -import io.papermc.hangar.model.db.versions.downloads.ProjectVersionDownloadTableWithPlatform; -import io.papermc.hangar.model.db.versions.downloads.ProjectVersionPlatformDownloadTable; import java.util.Collection; import java.util.List; -import org.apache.commons.lang3.tuple.Pair; import org.jdbi.v3.core.enums.EnumByOrdinal; import org.jdbi.v3.spring.JdbiRepository; import org.jdbi.v3.sqlobject.config.RegisterConstructorMapper; import org.jdbi.v3.sqlobject.customizer.BindBean; -import org.jdbi.v3.sqlobject.statement.GetGeneratedKeys; import org.jdbi.v3.sqlobject.statement.SqlBatch; import org.jdbi.v3.sqlobject.statement.SqlQuery; import org.jdbi.v3.sqlobject.statement.SqlUpdate; @JdbiRepository -@RegisterConstructorMapper(ProjectVersionPlatformDownloadTable.class) @RegisterConstructorMapper(ProjectVersionDownloadTable.class) -@RegisterConstructorMapper(ProjectVersionDownloadTableWithPlatform.class) public interface ProjectVersionDownloadsDAO { - @SqlBatch("INSERT INTO project_version_platform_downloads (version_id, platform, download_id) VALUES (:versionId, :platform, :downloadId)") - void insertPlatformDownloads(@BindBean Collection projectVersionPlatformDownloadTables); - @SqlUpdate("UPDATE project_version_downloads SET hash = :hash WHERE id = :id") void updateHash(long id, String hash); - @GetGeneratedKeys - @SqlBatch("INSERT INTO project_version_downloads (version_id, file_size, hash, file_name, external_url) VALUES (:versionId, :fileSize, :hash, :fileName, :externalUrl)") - List insertDownloads(@BindBean Collection projectVersionDownloadTables); + @SqlBatch("INSERT INTO project_version_downloads (version_id, file_size, hash, file_name, external_url, platforms, download_platform) VALUES (:versionId, :fileSize, :hash, :fileName, :externalUrl, :platforms, :downloadPlatform)") + void insertDownloads(@BindBean Collection projectVersionDownloadTables); @SqlQuery("SELECT * FROM project_version_downloads WHERE version_id = :versionId") List getDownloads(long versionId); @@ -38,35 +28,9 @@ public interface ProjectVersionDownloadsDAO { @SqlQuery("SELECT * FROM project_version_downloads") List getDownloads(); - @SqlQuery("SELECT * FROM project_version_platform_downloads WHERE version_id = :versionId") - List getPlatformDownloads(long versionId); - - @SqlQuery("SELECT pvpd.*, pvd.file_size, pvd.hash, pvd.file_name, pvd.external_url FROM project_version_platform_downloads pvpd " + - "JOIN project_version_downloads pvd ON pvd.id = pvpd.download_id " + - "WHERE pvpd.version_id = :versionId") - List> getPlatformDownloadsFull(long versionId); - - @SqlQuery("SELECT * FROM project_version_platform_downloads WHERE version_id = :versionId AND download_id = :downloadId") - List getPlatformDownloads(long versionId, long downloadId); - - @SqlQuery("SELECT * FROM project_version_platform_downloads WHERE version_id = :versionId AND platform = :platform") - ProjectVersionPlatformDownloadTable getPlatformDownload(long versionId, @EnumByOrdinal Platform platform); + @SqlQuery("SELECT * FROM project_version_downloads WHERE version_id = :versionId AND :platform = any(platforms)") + ProjectVersionDownloadTable getDownloadByPlatform(long versionId, @EnumByOrdinal Platform platform); @SqlQuery("SELECT * FROM project_version_downloads WHERE version_id = :versionId AND id = :downloadId") ProjectVersionDownloadTable getDownload(long versionId, long downloadId); - - // we need to find the first version platform download for the given download ID, since only that is being uploaded to object storage - // see comment in VersionFactory#processPendingVersionFile - @SqlQuery(""" - SELECT pvd.*, - (SELECT platform - FROM project_version_platform_downloads first - WHERE first.download_id = pvpd.download_id - LIMIT 1) AS platform - FROM project_version_downloads pvd - JOIN project_version_platform_downloads pvpd ON pvd.id = pvpd.download_id - WHERE pvpd.version_id = :versionId - AND pvpd.platform = :platform; - """) - ProjectVersionDownloadTableWithPlatform getDownloadByPlatform(long versionId, @EnumByOrdinal Platform platform); } diff --git a/backend/src/main/java/io/papermc/hangar/model/db/versions/downloads/ProjectVersionDownloadTable.java b/backend/src/main/java/io/papermc/hangar/model/db/versions/downloads/ProjectVersionDownloadTable.java index cb1038302..c76f6ed41 100644 --- a/backend/src/main/java/io/papermc/hangar/model/db/versions/downloads/ProjectVersionDownloadTable.java +++ b/backend/src/main/java/io/papermc/hangar/model/db/versions/downloads/ProjectVersionDownloadTable.java @@ -1,6 +1,10 @@ package io.papermc.hangar.model.db.versions.downloads; +import io.papermc.hangar.model.common.Platform; import io.papermc.hangar.model.db.Table; +import java.util.Arrays; +import java.util.List; +import org.jdbi.v3.core.enums.EnumByOrdinal; import org.jdbi.v3.core.mapper.reflect.JdbiConstructor; public class ProjectVersionDownloadTable extends Table { @@ -10,23 +14,29 @@ public class ProjectVersionDownloadTable extends Table { private final String hash; private final String fileName; private final String externalUrl; + private final Platform[] platforms; + private final Platform downloadPlatform; - public ProjectVersionDownloadTable(final long versionId, final Long fileSize, final String hash, final String fileName, final String externalUrl) { + public ProjectVersionDownloadTable(final long versionId, final Long fileSize, final String hash, final String fileName, final String externalUrl, final Platform[] platforms, final Platform downloadPlatform) { this.versionId = versionId; this.fileSize = fileSize; this.hash = hash; this.fileName = fileName; this.externalUrl = externalUrl; + this.platforms = platforms; + this.downloadPlatform = downloadPlatform; } @JdbiConstructor - public ProjectVersionDownloadTable(final long id, final long versionId, final Long fileSize, final String hash, final String fileName, final String externalUrl) { + public ProjectVersionDownloadTable(final long id, final long versionId, final Long fileSize, final String hash, final String fileName, final String externalUrl, final Platform[] platforms, final @EnumByOrdinal Platform downloadPlatform) { super(id); this.versionId = versionId; this.fileSize = fileSize; this.hash = hash; this.fileName = fileName; this.externalUrl = externalUrl; + this.platforms = platforms; + this.downloadPlatform = downloadPlatform; } public long getVersionId() { @@ -49,6 +59,15 @@ public String getExternalUrl() { return this.externalUrl; } + public Platform[] getPlatforms() { + return platforms; + } + + @EnumByOrdinal + public Platform getDownloadPlatform() { + return downloadPlatform; + } + @Override public String toString() { return "ProjectVersionDownloadTable{" + @@ -57,6 +76,8 @@ public String toString() { ", hash='" + hash + '\'' + ", fileName='" + fileName + '\'' + ", externalUrl='" + externalUrl + '\'' + + ", platforms='" + Arrays.toString(platforms) + '\'' + + ", downloadPlatform='" + downloadPlatform + '\'' + ", id=" + id + '}'; } diff --git a/backend/src/main/java/io/papermc/hangar/model/db/versions/downloads/ProjectVersionDownloadTableWithPlatform.java b/backend/src/main/java/io/papermc/hangar/model/db/versions/downloads/ProjectVersionDownloadTableWithPlatform.java deleted file mode 100644 index 5293c1847..000000000 --- a/backend/src/main/java/io/papermc/hangar/model/db/versions/downloads/ProjectVersionDownloadTableWithPlatform.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.papermc.hangar.model.db.versions.downloads; - -import io.papermc.hangar.model.common.Platform; - -public class ProjectVersionDownloadTableWithPlatform extends ProjectVersionDownloadTable { - - private final Platform platform; - - public ProjectVersionDownloadTableWithPlatform(final long id, final long versionId, final Long fileSize, final String hash, final String fileName, final String externalUrl, final Platform platform) { - super(id, versionId, fileSize, hash, fileName, externalUrl); - this.platform = platform; - } - - public Platform getPlatform() { - return this.platform; - } -} diff --git a/backend/src/main/java/io/papermc/hangar/model/db/versions/downloads/ProjectVersionPlatformDownloadTable.java b/backend/src/main/java/io/papermc/hangar/model/db/versions/downloads/ProjectVersionPlatformDownloadTable.java deleted file mode 100644 index 8385b4c45..000000000 --- a/backend/src/main/java/io/papermc/hangar/model/db/versions/downloads/ProjectVersionPlatformDownloadTable.java +++ /dev/null @@ -1,40 +0,0 @@ -package io.papermc.hangar.model.db.versions.downloads; - -import io.papermc.hangar.model.common.Platform; -import io.papermc.hangar.model.db.Table; -import org.jdbi.v3.core.enums.EnumByOrdinal; -import org.jdbi.v3.core.mapper.reflect.JdbiConstructor; - -public final class ProjectVersionPlatformDownloadTable extends Table { - - private final long versionId; - private final Platform platform; - private final long downloadId; - - public ProjectVersionPlatformDownloadTable(final long versionId, final Platform platform, final long downloadId) { - this.versionId = versionId; - this.platform = platform; - this.downloadId = downloadId; - } - - @JdbiConstructor - public ProjectVersionPlatformDownloadTable(final long id, final long versionId, @EnumByOrdinal final Platform platform, final long downloadId) { - super(id); - this.versionId = versionId; - this.platform = platform; - this.downloadId = downloadId; - } - - public long getVersionId() { - return this.versionId; - } - - @EnumByOrdinal - public Platform getPlatform() { - return this.platform; - } - - public long getDownloadId() { - return this.downloadId; - } -} diff --git a/backend/src/main/java/io/papermc/hangar/service/internal/versions/DownloadService.java b/backend/src/main/java/io/papermc/hangar/service/internal/versions/DownloadService.java index ccf209ff4..b36b5d9b8 100644 --- a/backend/src/main/java/io/papermc/hangar/service/internal/versions/DownloadService.java +++ b/backend/src/main/java/io/papermc/hangar/service/internal/versions/DownloadService.java @@ -9,17 +9,13 @@ import io.papermc.hangar.model.db.projects.ProjectTable; import io.papermc.hangar.model.db.versions.ProjectVersionTable; import io.papermc.hangar.model.db.versions.downloads.ProjectVersionDownloadTable; -import io.papermc.hangar.model.db.versions.downloads.ProjectVersionDownloadTableWithPlatform; -import io.papermc.hangar.model.db.versions.downloads.ProjectVersionPlatformDownloadTable; import io.papermc.hangar.service.internal.file.FileService; import io.papermc.hangar.service.internal.file.S3FileService; import io.papermc.hangar.service.internal.projects.ProjectService; import io.papermc.hangar.service.internal.uploads.ProjectFiles; import java.util.EnumMap; -import java.util.HashMap; import java.util.List; import java.util.Map; -import org.apache.commons.lang3.tuple.Pair; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; @@ -45,28 +41,19 @@ public DownloadService(final ProjectFiles projectFiles, final ProjectVersionDown public Map getDownloads(final String user, final String project, final String version, final long versionId) { final Map versionDownloadsMap = new EnumMap<>(Platform.class); - final List> platformDownloadsFull = this.downloadsDAO.getPlatformDownloadsFull(versionId); - final Map downloads = new HashMap<>(); - for (final Pair platformDownloadPair : platformDownloadsFull) { - final ProjectVersionPlatformDownloadTable platformDownload = platformDownloadPair.getLeft(); - PlatformVersionDownload download = downloads.get(platformDownload.getDownloadId()); - if (download != null) { - versionDownloadsMap.put(platformDownload.getPlatform(), download); - continue; + final List downloads = this.downloadsDAO.getDownloads(versionId); + for (final ProjectVersionDownloadTable download : downloads) { + final FileInfo fileInfo = download.getFileName() != null ? new FileInfo(download.getFileName(), download.getFileSize(), download.getHash()) : null; + final String downloadUrl = fileInfo != null ? this.fileService.getVersionDownloadUrl(user, project, version, download.getDownloadPlatform(), fileInfo.getName()) : null; + for (final Platform platform : download.getPlatforms()) { + versionDownloadsMap.put(platform, new PlatformVersionDownload(fileInfo, download.getExternalUrl(), downloadUrl)); } - - final ProjectVersionDownloadTable downloadTable = platformDownloadPair.getRight(); - final FileInfo fileInfo = downloadTable.getFileName() != null ? new FileInfo(downloadTable.getFileName(), downloadTable.getFileSize(), downloadTable.getHash()) : null; - final String downloadUrl = fileInfo != null ? this.fileService.getVersionDownloadUrl(user, project, version, platformDownload.getPlatform(), fileInfo.getName()) : null; - download = new PlatformVersionDownload(fileInfo, downloadTable.getExternalUrl(), downloadUrl); - downloads.put(platformDownload.getDownloadId(), download); - versionDownloadsMap.put(platformDownload.getPlatform(), download); } return versionDownloadsMap; } public ResponseEntity downloadVersion(final ProjectTable project, final ProjectVersionTable version, final Platform platform) { - final ProjectVersionDownloadTableWithPlatform download = this.downloadsDAO.getDownloadByPlatform(version.getVersionId(), platform); + final ProjectVersionDownloadTable download = this.downloadsDAO.getDownloadByPlatform(version.getVersionId(), platform); if (download == null) { throw new HangarApiException(HttpStatus.NOT_FOUND); } @@ -75,7 +62,7 @@ public ResponseEntity downloadVersion(final ProjectTable project, final Proje if (StringUtils.hasText(download.getExternalUrl())) { return ResponseEntity.status(301).header("Location", download.getExternalUrl()).build(); } else if (this.fileService instanceof S3FileService){ - return ResponseEntity.status(301).header("Location", this.fileService.getVersionDownloadUrl(ownerName, project.getName(), version.getName(), download.getPlatform(), download.getFileName())).build(); + return ResponseEntity.status(301).header("Location", this.fileService.getVersionDownloadUrl(ownerName, project.getName(), version.getName(), download.getDownloadPlatform(), download.getFileName())).build(); } else { final String path = this.projectFiles.getVersionDir(ownerName, project.getName(), version.getName(), platform, download.getFileName()); if (!this.fileService.exists(path)) { diff --git a/backend/src/main/java/io/papermc/hangar/service/internal/versions/JarScanningService.java b/backend/src/main/java/io/papermc/hangar/service/internal/versions/JarScanningService.java index 3052c08cf..c5e98c3ea 100644 --- a/backend/src/main/java/io/papermc/hangar/service/internal/versions/JarScanningService.java +++ b/backend/src/main/java/io/papermc/hangar/service/internal/versions/JarScanningService.java @@ -15,7 +15,6 @@ import io.papermc.hangar.model.db.versions.JarScanResultTable; import io.papermc.hangar.model.db.versions.ProjectVersionTable; import io.papermc.hangar.model.db.versions.downloads.ProjectVersionDownloadTable; -import io.papermc.hangar.model.db.versions.downloads.ProjectVersionPlatformDownloadTable; import io.papermc.hangar.model.internal.versions.JarScanResult; import io.papermc.hangar.scanner.HangarJarScanner; import io.papermc.hangar.scanner.check.Check; @@ -179,23 +178,18 @@ public Severity scanPlatform(final VersionToScan versionToScan, final Platform p private NamedResource getFile(final VersionToScan version, final Platform platform) { final long versionId = version.versionId(); - final ProjectVersionPlatformDownloadTable platformDownload = this.downloadsDAO.getPlatformDownload(versionId, platform); + final ProjectVersionDownloadTable platformDownload = this.downloadsDAO.getDownloadByPlatform(versionId, platform); // TODO Why can platformDownload be null at this stage if (platformDownload == null) { throw new RuntimeException("Couldn't find a download for version " + version + " in platform " + platform); } - final ProjectVersionDownloadTable download = this.downloadsDAO.getDownload(versionId, platformDownload.getDownloadId()); - if (download.getFileName() == null) { - throw new RuntimeException("Couldn't find a file for version " + version + " in download " + download); - } - final ProjectTable project = this.projectsDAO.getById(version.projectId()); - final String path = this.projectFiles.getVersionDir(project.getOwnerName(), project.getSlug(), version.versionString(), platform, download.getFileName()); + final String path = this.projectFiles.getVersionDir(project.getOwnerName(), project.getSlug(), version.versionString(), platformDownload.getDownloadPlatform(), platformDownload.getFileName()); if (!this.fileService.exists(path)) { throw new RuntimeException("Couldn't find a file for version " + version + " in path " + path); } - return new NamedResource(this.fileService.getResource(path), download.getFileName()); + return new NamedResource(this.fileService.getResource(path), platformDownload.getFileName()); } public @Nullable JarScanResult getLastResult(final long versionId, final Platform platform) { diff --git a/backend/src/main/java/io/papermc/hangar/service/internal/versions/VersionFactory.java b/backend/src/main/java/io/papermc/hangar/service/internal/versions/VersionFactory.java index d8f25387a..e8941f801 100644 --- a/backend/src/main/java/io/papermc/hangar/service/internal/versions/VersionFactory.java +++ b/backend/src/main/java/io/papermc/hangar/service/internal/versions/VersionFactory.java @@ -26,7 +26,6 @@ import io.papermc.hangar.model.db.versions.dependencies.ProjectVersionDependencyTable; import io.papermc.hangar.model.db.versions.dependencies.ProjectVersionPlatformDependencyTable; import io.papermc.hangar.model.db.versions.downloads.ProjectVersionDownloadTable; -import io.papermc.hangar.model.db.versions.downloads.ProjectVersionPlatformDownloadTable; import io.papermc.hangar.model.internal.logs.LogAction; import io.papermc.hangar.model.internal.logs.contexts.VersionContext; import io.papermc.hangar.model.internal.versions.LastDependencies; @@ -61,8 +60,6 @@ import java.util.Set; import java.util.SortedSet; import java.util.stream.Collectors; -import org.apache.commons.lang3.tuple.ImmutablePair; -import org.apache.commons.lang3.tuple.Pair; import org.checkerframework.checker.nullness.qual.Nullable; import org.spongepowered.configurate.ConfigurateException; import org.springframework.beans.factory.annotation.Autowired; @@ -155,7 +152,7 @@ public PendingVersion createPendingVersion(final long projectId, final List>> downloadsTables = new ArrayList<>(); + final List downloadsTables = new ArrayList<>(); for (final PendingVersionFile pendingVersionFile : pendingVersion.getFiles()) { this.processPendingVersionFile(pendingVersion, userTempDir, projectVersionTable, versionDir, downloadsTables, pendingVersionFile); } // Insert download data - final List tables = this.downloadsDAO.insertDownloads(downloadsTables.stream().map(Pair::getLeft).toList()); - final List platformDownloadsTables = new ArrayList<>(); - for (int i = 0; i < downloadsTables.size(); i++) { - final ProjectVersionDownloadTable downloadTable = tables.get(i); - for (final Platform platform : downloadsTables.get(i).getRight()) { - platformDownloadsTables.add(new ProjectVersionPlatformDownloadTable(projectVersionTable.getVersionId(), platform, downloadTable.getId())); - } - } - this.downloadsDAO.insertPlatformDownloads(platformDownloadsTables); + this.downloadsDAO.insertDownloads(downloadsTables); // send notifications if (projectChannelTable.getFlags().contains(ChannelFlag.SENDS_NOTIFICATIONS)) { @@ -347,7 +336,7 @@ public ProjectVersionTable publishPendingVersion(final long projectId, final Pen boolean safeLinks = true; for (final PendingVersionFile file : pendingVersion.getFiles()) { if (file.fileInfo() != null) { - platformsToScan.add(file.platforms().get(0)); + platformsToScan.add(file.platforms().getFirst()); continue; } @@ -411,19 +400,19 @@ private void processDependencies(final PendingVersion pendingVersion, final long this.projectVersionDependenciesDAO.insertAll(pluginDependencyTables); } - private void processPendingVersionFile(final PendingVersion pendingVersion, final String userTempDir, final ProjectVersionTable projectVersionTable, final String versionDir, final List>> downloadsTables, final PendingVersionFile pendingVersionFile) throws IOException { + private void processPendingVersionFile(final PendingVersion pendingVersion, final String userTempDir, final ProjectVersionTable projectVersionTable, final String versionDir, final List downloadsTables, final PendingVersionFile pendingVersionFile) throws IOException { + final Platform downloadPlatform = pendingVersionFile.platforms().getFirst(); final FileInfo fileInfo = pendingVersionFile.fileInfo(); if (fileInfo == null) { - final ProjectVersionDownloadTable table = new ProjectVersionDownloadTable(projectVersionTable.getVersionId(), null, null, null, pendingVersionFile.externalUrl()); - downloadsTables.add(ImmutablePair.of(table, pendingVersionFile.platforms())); + final ProjectVersionDownloadTable table = new ProjectVersionDownloadTable(projectVersionTable.getVersionId(), null, null, null, pendingVersionFile.externalUrl(), pendingVersionFile.platforms().toArray(new Platform[0]), downloadPlatform); + downloadsTables.add(table); return; } // Move file for first platform - final Platform platformToResolve = pendingVersionFile.platforms().get(0); - final String tmpVersionJar = this.fileService.resolve(this.fileService.resolve(userTempDir, platformToResolve.name()), fileInfo.getName()); + final String tmpVersionJar = this.fileService.resolve(this.fileService.resolve(userTempDir, downloadPlatform.name()), fileInfo.getName()); - final String newVersionJarPath = this.fileService.resolve(this.fileService.resolve(versionDir, platformToResolve.name()), fileInfo.getName()); + final String newVersionJarPath = this.fileService.resolve(this.fileService.resolve(versionDir, downloadPlatform.name()), fileInfo.getName()); this.fileService.moveFile(tmpVersionJar, newVersionJarPath); // Create links for the other platforms @@ -444,8 +433,8 @@ private void processPendingVersionFile(final PendingVersion pendingVersion, fina } } - final ProjectVersionDownloadTable table = new ProjectVersionDownloadTable(projectVersionTable.getVersionId(), fileInfo.sizeBytes(), fileInfo.sha256Hash(), fileInfo.getName(), null); - downloadsTables.add(ImmutablePair.of(table, pendingVersionFile.platforms())); + final ProjectVersionDownloadTable table = new ProjectVersionDownloadTable(projectVersionTable.getVersionId(), fileInfo.sizeBytes(), fileInfo.sha256Hash(), fileInfo.getName(), null, pendingVersionFile.platforms().toArray(new Platform[0]), downloadPlatform); + downloadsTables.add(table); } private void verifyPendingPlatforms(final PendingVersion pendingVersion, final String userTempDir) { @@ -457,7 +446,7 @@ private void verifyPendingPlatforms(final PendingVersion pendingVersion, final S final FileInfo fileInfo = pendingVersionFile.fileInfo(); if (fileInfo != null) { // verify file - final Platform platform = pendingVersionFile.platforms().get(0); // Use the first platform to resolve + final Platform platform = pendingVersionFile.platforms().getFirst(); // Use the first platform to resolve final String tmpVersionJar = this.fileService.resolve(this.fileService.resolve(userTempDir, platform.name()), fileInfo.getName()); try { if (!this.fileService.exists(tmpVersionJar)) { diff --git a/backend/src/main/java/io/papermc/hangar/service/internal/versions/VersionService.java b/backend/src/main/java/io/papermc/hangar/service/internal/versions/VersionService.java index 4526c05c5..197404962 100644 --- a/backend/src/main/java/io/papermc/hangar/service/internal/versions/VersionService.java +++ b/backend/src/main/java/io/papermc/hangar/service/internal/versions/VersionService.java @@ -11,7 +11,6 @@ import io.papermc.hangar.model.common.projects.Visibility; import io.papermc.hangar.model.db.projects.ProjectTable; import io.papermc.hangar.model.db.versions.ProjectVersionTable; -import io.papermc.hangar.model.db.versions.downloads.ProjectVersionPlatformDownloadTable; import io.papermc.hangar.model.internal.logs.LogAction; import io.papermc.hangar.model.internal.logs.contexts.VersionContext; import io.papermc.hangar.model.internal.versions.HangarVersion; @@ -70,13 +69,7 @@ public List updateFileHashes() { final ProjectVersionTable versionTable = this.projectVersionsDAO.getProjectVersionTable(downloadTable.getVersionId()); final ProjectTable projectTable = this.projectsDAO.getById(versionTable.getProjectId()); - final List platformDownloads = this.projectVersionDownloadsDAO.getPlatformDownloads(versionTable.getVersionId(), downloadTable.getId()); - if (platformDownloads.isEmpty()) { - errors.add("No platform downloads for " + projectTable.getOwnerName() + "/" + projectTable.getSlug() + "/" + versionTable.getVersionString() + "/" + downloadTable.getFileName()); - return; - } - - final Platform platform = platformDownloads.get(0).getPlatform(); + final Platform platform = downloadTable.getDownloadPlatform(); final String versionPath = this.projectFiles.getVersionDir(projectTable.getOwnerName(), projectTable.getSlug(), versionTable.getVersionString(), platform, downloadTable.getFileName()); if (!this.fileService.exists(versionPath)) { diff --git a/backend/src/main/resources/db/migration/V1.17.0__project_version_cleanup.sql b/backend/src/main/resources/db/migration/V1.17.0__project_version_cleanup.sql new file mode 100644 index 000000000..f08507f2c --- /dev/null +++ b/backend/src/main/resources/db/migration/V1.17.0__project_version_cleanup.sql @@ -0,0 +1,3 @@ +ALTER TABLE project_version_downloads + ADD platforms bigint[], + ADD download_platform bigint diff --git a/backend/src/main/resources/db/migration/V1.17.1__migration b/backend/src/main/resources/db/migration/V1.17.1__migration new file mode 100644 index 000000000..9e096bc56 --- /dev/null +++ b/backend/src/main/resources/db/migration/V1.17.1__migration @@ -0,0 +1,4 @@ +UPDATE project_version_downloads pvd +SET download_platform = (SELECT platform FROM project_version_platform_downloads WHERE download_id = pvd.id LIMIT 1), + platforms = (SELECT array_agg(platform) from project_version_platform_downloads WHERE download_id = pvd.id) +WHERE platforms IS NULL; diff --git a/backend/src/main/resources/db/migration/V1.17.2__cleanup b/backend/src/main/resources/db/migration/V1.17.2__cleanup new file mode 100644 index 000000000..d9b817401 --- /dev/null +++ b/backend/src/main/resources/db/migration/V1.17.2__cleanup @@ -0,0 +1,5 @@ +alter table public.project_version_downloads + alter column platforms set not null; + +DROP TABLE project_version_platform_dependencies; // TODO dependency clenaup +DROP TABLE project_version_platform_downloads; diff --git a/frontend/src/pages/[user]/[project]/versions/[version]/scan.vue b/frontend/src/pages/[user]/[project]/versions/[version]/scan.vue index e718a7a92..6f98ef555 100644 --- a/frontend/src/pages/[user]/[project]/versions/[version]/scan.vue +++ b/frontend/src/pages/[user]/[project]/versions/[version]/scan.vue @@ -21,9 +21,13 @@ async function doScan() { continue; } - await useInternalApi(`jarscanning/scan/${props.version?.id}/${platform}`, "POST"); + try { + await useInternalApi(`jarscanning/scan/${props.version?.id}/${platform}`, "POST"); + useNotificationStore().success("Scheduled scan for " + platform); + } catch (err) { + useNotificationStore().error("Failed to schedule scan for " + platform + ": " + err?.response?.data?.message ?? err); + } } - await useNotificationStore().success("Scheduled scan"); } useSeo(