Skip to content

Commit

Permalink
feat: refactor version queries, remove platform download table
Browse files Browse the repository at this point in the history
  • Loading branch information
MiniDigger committed Jan 12, 2025
1 parent 0db7ade commit daf3dec
Show file tree
Hide file tree
Showing 13 changed files with 85 additions and 164 deletions.
14 changes: 14 additions & 0 deletions backend/src/main/java/io/papermc/hangar/config/JDBIConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -58,6 +60,18 @@ public Jdbi jdbi(final DataSource dataSource, final List<JdbiPlugin> jdbiPlugins
config.registerCustomType(JobState.class, "job_state");
config.registerCustomType(JSONB.class, "jsonb");

jdbi.registerArrayType(new SqlArrayType<Platform>() {
@Override
public String getTypeName() {
return "integer";
}

@Override
public Integer convertArrayElement(final Platform element) {
return element.ordinal();
}
});

return jdbi;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,71 +2,35 @@

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<ProjectVersionPlatformDownloadTable> 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<ProjectVersionDownloadTable> insertDownloads(@BindBean Collection<ProjectVersionDownloadTable> 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<ProjectVersionDownloadTable> projectVersionDownloadTables);

@SqlQuery("SELECT * FROM project_version_downloads WHERE version_id = :versionId")
List<ProjectVersionDownloadTable> getDownloads(long versionId);

@SqlQuery("SELECT * FROM project_version_downloads")
List<ProjectVersionDownloadTable> getDownloads();

@SqlQuery("SELECT * FROM project_version_platform_downloads WHERE version_id = :versionId")
List<ProjectVersionPlatformDownloadTable> 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<Pair<ProjectVersionPlatformDownloadTable, ProjectVersionDownloadTable>> getPlatformDownloadsFull(long versionId);

@SqlQuery("SELECT * FROM project_version_platform_downloads WHERE version_id = :versionId AND download_id = :downloadId")
List<ProjectVersionPlatformDownloadTable> 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);
}
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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() {
Expand All @@ -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{" +
Expand All @@ -57,6 +76,8 @@ public String toString() {
", hash='" + hash + '\'' +
", fileName='" + fileName + '\'' +
", externalUrl='" + externalUrl + '\'' +
", platforms='" + Arrays.toString(platforms) + '\'' +
", downloadPlatform='" + downloadPlatform + '\'' +
", id=" + id +
'}';
}
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -45,28 +41,19 @@ public DownloadService(final ProjectFiles projectFiles, final ProjectVersionDown

public Map<Platform, PlatformVersionDownload> getDownloads(final String user, final String project, final String version, final long versionId) {
final Map<Platform, PlatformVersionDownload> versionDownloadsMap = new EnumMap<>(Platform.class);
final List<Pair<ProjectVersionPlatformDownloadTable, ProjectVersionDownloadTable>> platformDownloadsFull = this.downloadsDAO.getPlatformDownloadsFull(versionId);
final Map<Long, PlatformVersionDownload> downloads = new HashMap<>();
for (final Pair<ProjectVersionPlatformDownloadTable, ProjectVersionDownloadTable> platformDownloadPair : platformDownloadsFull) {
final ProjectVersionPlatformDownloadTable platformDownload = platformDownloadPair.getLeft();
PlatformVersionDownload download = downloads.get(platformDownload.getDownloadId());
if (download != null) {
versionDownloadsMap.put(platformDownload.getPlatform(), download);
continue;
final List<ProjectVersionDownloadTable> 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);
}
Expand All @@ -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)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
Loading

0 comments on commit daf3dec

Please sign in to comment.