2020-05-14 04:08:27 +00:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Threading.Tasks ;
using Dapper ;
using Wabbajack.Common ;
using Wabbajack.Lib ;
using Wabbajack.Lib.AuthorApi ;
using Wabbajack.Lib.Downloaders ;
using Wabbajack.Server.DTOs ;
namespace Wabbajack.Server.DataLayer
{
public partial class SqlService
{
2020-05-20 12:18:47 +00:00
public async Task < Guid > AddKnownDownload ( Archive a , DateTime downloadFinished )
{
await using var conn = await Open ( ) ;
var Id = Guid . NewGuid ( ) ;
await conn . ExecuteAsync (
"INSERT INTO ArchiveDownloads (Id, PrimaryKeyString, Size, Hash, DownloadState, Downloader, DownloadFinished, IsFailed) VALUES (@Id, @PrimaryKeyString, @Size, @Hash, @DownloadState, @Downloader, @DownloadFinished, @IsFailed)" ,
new
{
Id = Id ,
PrimaryKeyString = a . State . PrimaryKeyString ,
Size = a . Size = = 0 ? null : ( long? ) a . Size ,
Hash = a . Hash = = default ? null : ( Hash ? ) a . Hash ,
DownloadState = a . State ,
Downloader = AbstractDownloadState . TypeToName [ a . State . GetType ( ) ] ,
DownloadFinished = downloadFinished ,
IsFailed = false
} ) ;
return Id ;
}
2020-05-14 04:08:27 +00:00
public async Task < Guid > EnqueueDownload ( Archive a )
{
await using var conn = await Open ( ) ;
var Id = Guid . NewGuid ( ) ;
await conn . ExecuteAsync (
"INSERT INTO ArchiveDownloads (Id, PrimaryKeyString, Size, Hash, DownloadState, Downloader) VALUES (@Id, @PrimaryKeyString, @Size, @Hash, @DownloadState, @Downloader)" ,
new
{
Id = Id ,
PrimaryKeyString = a . State . PrimaryKeyString ,
Size = a . Size = = 0 ? null : ( long? ) a . Size ,
Hash = a . Hash = = default ? null : ( Hash ? ) a . Hash ,
DownloadState = a . State ,
2020-05-20 12:18:47 +00:00
Downloader = AbstractDownloadState . TypeToName [ a . State . GetType ( ) ] ,
2020-05-14 04:08:27 +00:00
} ) ;
return Id ;
}
public async Task < HashSet < ( Hash Hash , string PrimaryKeyString ) > > GetAllArchiveDownloads ( )
{
await using var conn = await Open ( ) ;
return ( await conn . QueryAsync < ( Hash , string ) > ( "SELECT Hash, PrimaryKeyString FROM ArchiveDownloads" ) ) . ToHashSet ( ) ;
}
2020-05-19 03:46:33 +00:00
public async Task < ArchiveDownload > GetArchiveDownload ( Guid id )
{
await using var conn = await Open ( ) ;
var result = await conn . QueryFirstOrDefaultAsync < ( Guid , long? , Hash ? , bool? , AbstractDownloadState , DateTime ? ) > (
"SELECT Id, Size, Hash, IsFailed, DownloadState, DownloadFinished FROM dbo.ArchiveDownloads WHERE Id = @id" ,
new { Id = id } ) ;
if ( result = = default )
return null ;
return new ArchiveDownload
{
Id = result . Item1 ,
IsFailed = result . Item4 ,
DownloadFinished = result . Item6 ,
Archive = new Archive ( result . Item5 ) { Size = result . Item2 ? ? 0 , Hash = result . Item3 ? ? default }
} ;
}
2020-05-20 03:25:41 +00:00
public async Task < ArchiveDownload > GetArchiveDownload ( string primaryKeyString , Hash hash , long size )
{
await using var conn = await Open ( ) ;
var result = await conn . QueryFirstOrDefaultAsync < ( Guid , long? , Hash ? , bool? , AbstractDownloadState , DateTime ? ) > (
"SELECT Id, Size, Hash, IsFailed, DownloadState, DownloadFinished FROM dbo.ArchiveDownloads WHERE PrimaryKeyString = @PrimaryKeyString AND Hash = @Hash AND Size = @Size" ,
new
{
PrimaryKeyString = primaryKeyString ,
Hash = hash ,
Size = size
} ) ;
if ( result = = default )
return null ;
return new ArchiveDownload
{
Id = result . Item1 ,
IsFailed = result . Item4 ,
DownloadFinished = result . Item6 ,
Archive = new Archive ( result . Item5 ) { Size = result . Item2 ? ? 0 , Hash = result . Item3 ? ? default }
} ;
}
public async Task < ArchiveDownload > GetOrEnqueueArchive ( Archive a )
{
await using var conn = await Open ( ) ;
2020-06-20 22:51:47 +00:00
await using var trans = await conn . BeginTransactionAsync ( ) ;
2020-05-20 03:25:41 +00:00
var result = await conn . QueryFirstOrDefaultAsync < ( Guid , long? , Hash ? , bool? , AbstractDownloadState , DateTime ? ) > (
"SELECT Id, Size, Hash, IsFailed, DownloadState, DownloadFinished FROM dbo.ArchiveDownloads WHERE PrimaryKeyString = @PrimaryKeyString AND Hash = @Hash AND Size = @Size" ,
new
{
PrimaryKeyString = a . State . PrimaryKeyString ,
Hash = a . Hash ,
Size = a . Size
} , trans ) ;
2020-06-20 22:51:47 +00:00
if ( result . Item1 ! = default )
2020-05-20 03:25:41 +00:00
{
return new ArchiveDownload
{
Id = result . Item1 ,
IsFailed = result . Item4 ,
DownloadFinished = result . Item6 ,
Archive = new Archive ( result . Item5 ) { Size = result . Item2 ? ? 0 , Hash = result . Item3 ? ? default }
} ;
}
var id = Guid . NewGuid ( ) ;
await conn . ExecuteAsync (
"INSERT INTO ArchiveDownloads (Id, PrimaryKeyString, Size, Hash, DownloadState, Downloader) VALUES (@Id, @PrimaryKeyString, @Size, @Hash, @DownloadState, @Downloader)" ,
new
{
Id = id ,
PrimaryKeyString = a . State . PrimaryKeyString ,
Size = a . Size = = 0 ? null : ( long? ) a . Size ,
Hash = a . Hash = = default ? null : ( Hash ? ) a . Hash ,
DownloadState = a . State ,
Downloader = AbstractDownloadState . TypeToName [ a . State . GetType ( ) ]
} , trans ) ;
await trans . CommitAsync ( ) ;
return new ArchiveDownload { Id = id , Archive = a , } ;
}
2020-05-19 03:46:33 +00:00
2020-05-14 04:08:27 +00:00
public async Task < ArchiveDownload > GetNextPendingDownload ( bool ignoreNexus = false )
{
await using var conn = await Open ( ) ;
( Guid , long? , Hash ? , AbstractDownloadState ) result ;
if ( ignoreNexus )
{
result = await conn . QueryFirstOrDefaultAsync < ( Guid , long? , Hash ? , AbstractDownloadState ) > (
2020-06-20 22:51:47 +00:00
"SELECT TOP(1) Id, Size, Hash, DownloadState FROM dbo.ArchiveDownloads WHERE DownloadFinished is NULL AND Downloader != 'NexusDownloader+State'" ) ;
2020-05-14 04:08:27 +00:00
}
else
{
result = await conn . QueryFirstOrDefaultAsync < ( Guid , long? , Hash ? , AbstractDownloadState ) > (
2020-06-20 22:51:47 +00:00
"SELECT TOP(1) Id, Size, Hash, DownloadState FROM dbo.ArchiveDownloads WHERE DownloadFinished is NULL" ) ;
2020-05-14 04:08:27 +00:00
}
if ( result = = default )
return null ;
return new ArchiveDownload
{
Id = result . Item1 ,
Archive = new Archive ( result . Item4 ) { Size = result . Item2 ? ? 0 , Hash = result . Item3 ? ? default , } ,
} ;
}
public async Task UpdatePendingDownload ( ArchiveDownload ad )
{
await using var conn = await Open ( ) ;
await conn . ExecuteAsync (
"UPDATE dbo.ArchiveDownloads SET IsFailed = @IsFailed, DownloadFinished = @DownloadFinished, Hash = @Hash, Size = @Size, FailMessage = @FailMessage WHERE Id = @Id" ,
new
{
Id = ad . Id ,
IsFailed = ad . IsFailed ,
DownloadFinished = ad . DownloadFinished ,
Size = ad . Archive . Size ,
Hash = ad . Archive . Hash ,
FailMessage = ad . FailMessage
} ) ;
}
public async Task < int > EnqueueModListFilesForIndexing ( )
{
await using var conn = await Open ( ) ;
return await conn . ExecuteAsync ( @ "
INSERT INTO dbo . ArchiveDownloads ( Id , PrimaryKeyString , Hash , DownloadState , Size , Downloader )
SELECT DISTINCT NEWID ( ) , mla . PrimaryKeyString , mla . Hash , mla . State , mla . Size , SUBSTRING ( mla . PrimaryKeyString , 0 , CHARINDEX ( '|' , mla . PrimaryKeyString ) )
FROM [ dbo ] . [ ModListArchives ] mla
LEFT JOIN dbo . ArchiveDownloads ad on mla . PrimaryKeyString = ad . PrimaryKeyString AND mla . Hash = ad . Hash
WHERE ad . PrimaryKeyString is null ");
}
2020-06-20 22:51:47 +00:00
public async Task < List < Archive > > GetGameFiles ( Game game , string version )
{
await using var conn = await Open ( ) ;
var files = ( await conn . QueryAsync < ( Hash , long , AbstractDownloadState ) > (
$"SELECT Hash, Size, DownloadState FROM dbo.ArchiveDownloads WHERE PrimaryKeyString like 'GameFileSourceDownloader+State|{game}|{version}|%'" ) )
. Select ( f = > new Archive ( f . Item3 )
{
Hash = f . Item1 ,
Size = f . Item2
} ) . ToList ( ) ;
return files ;
}
2020-06-21 22:03:54 +00:00
public async Task < Archive [ ] > ResolveDownloadStatesByHash ( Hash hash )
{
await using var conn = await Open ( ) ;
var files = ( await conn . QueryAsync < ( long , Hash , AbstractDownloadState ) > (
@"SELECT Size, Hash, DownloadState from dbo.ArchiveDownloads WHERE Hash = @Hash AND IsFailed = 0 AND DownloadFinished IS NOT NULL ORDER BY DownloadFinished DESC" ,
new { Hash = hash } )
) ;
return files . Select ( e = >
new Archive ( e . Item3 ) { Size = e . Item1 , Hash = e . Item2 }
) . ToArray ( ) ;
}
2020-05-14 04:08:27 +00:00
}
}