Automate host preparation and speed up game file downloads
This commit is contained in:
@@ -38,6 +38,14 @@ export function newestReadyLibrary(game: string): GameLibraryVersion | null {
|
||||
const row = database().prepare("SELECT v.*, l.game FROM game_file_versions v JOIN game_file_libraries l ON l.id=v.library_id WHERE l.game=? AND v.state='ready' ORDER BY v.created_at DESC, v.rowid DESC LIMIT 1").get(game) as VersionRow | undefined;
|
||||
return row ? versionFromRow(row) : null;
|
||||
}
|
||||
/** Preparation needs only the latest published version of each library, never its full manifest. */
|
||||
export function latestPublishedLibraries() {
|
||||
return database().prepare(`SELECT v.id, l.name, l.game, v.version, v.size_bytes AS sizeBytes, v.manifest_sha256 AS manifestSha256
|
||||
FROM game_file_versions v JOIN game_file_libraries l ON l.id=v.library_id
|
||||
WHERE v.state='ready' AND v.id=(SELECT newest.id FROM game_file_versions newest
|
||||
WHERE newest.library_id=l.id AND newest.state='ready' ORDER BY newest.created_at DESC,newest.rowid DESC LIMIT 1)
|
||||
ORDER BY l.name`).all() as { id: string; name: string; game: GameLibraryGame; version: string; sizeBytes: number; manifestSha256: string }[];
|
||||
}
|
||||
export function listLibraries(): GameLibrary[] {
|
||||
reconcileLibraryOperations();
|
||||
return (database().prepare('SELECT * FROM game_file_libraries ORDER BY name').all() as Array<{ id: string; name: string; game: GameLibraryGame; description: string; created_at: string }>).map(row => ({
|
||||
@@ -315,18 +323,19 @@ export function queueLibraryDownload(hostId: string, versionId: string) {
|
||||
if (!version || version.state !== 'ready') throw new Error('Choose a published library version.');
|
||||
const host = getHost(hostId);
|
||||
if (!host || !host.connected || !host.credentialActive || host.mode === 'disabled') throw new Error('Choose an online, enrolled host.');
|
||||
if (Number(host.inventory.storageAvailable ?? 0) < version.sizeBytes + host.minimumFreeBytes) throw new Error('This host has insufficient storage for this library and its minimum free-space reserve.');
|
||||
const prior = getHostLibraryCache(hostId, versionId);
|
||||
if (prior?.operationId) {
|
||||
const operation = getHostOperation(prior.operationId);
|
||||
if (operation && ['pending', 'accepted', 'running', 'unknown'].includes(operation.state)) return operation;
|
||||
}
|
||||
const retainedBytes = prior?.manifestSha256 === version.manifestSha256 ? prior.bytesDownloaded : 0;
|
||||
if (Number(host.inventory.storageAvailable ?? 0) < version.sizeBytes - retainedBytes + host.minimumFreeBytes) throw new Error('This host has insufficient storage for this library and its minimum free-space reserve.');
|
||||
const operation = queueHostOperation(hostId, 'library.download', {
|
||||
libraryVersionId: versionId, game: version.game, manifestUrl: `/api/agent/libraries/${versionId}/manifest`,
|
||||
filesBaseUrl: `/api/agent/libraries/${versionId}/files`, statusUrl: `/api/agent/libraries/${versionId}/status`,
|
||||
manifestSha256: version.manifestSha256, sizeBytes: version.sizeBytes
|
||||
});
|
||||
updateHostLibraryCaches(hostId, [{ libraryVersionId: versionId, status: 'downloading', bytesDownloaded: 0 }]);
|
||||
updateHostLibraryCaches(hostId, [{ libraryVersionId: versionId, status: 'downloading', bytesDownloaded: retainedBytes, manifestSha256: prior?.manifestSha256 }]);
|
||||
database().prepare('UPDATE host_library_caches SET operation_id=? WHERE host_id=? AND version_id=?').run(operation.id, hostId, versionId);
|
||||
return operation;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user