118 lines
4.9 KiB
C#
118 lines
4.9 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Security.Cryptography;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Npgsql;
|
|
using PhoenixLib.Logging;
|
|
|
|
namespace Plugin.ResourceLoader.Services
|
|
{
|
|
public class ResourceFilesPostgresSyncService : IHostedService
|
|
{
|
|
private readonly ResourceLoadingConfiguration _configuration;
|
|
|
|
public ResourceFilesPostgresSyncService(ResourceLoadingConfiguration configuration)
|
|
{
|
|
_configuration = configuration;
|
|
}
|
|
|
|
public Task StartAsync(CancellationToken cancellationToken)
|
|
{
|
|
if (string.Equals(Environment.GetEnvironmentVariable("PARSER_DB_SYNC"), "false", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
try
|
|
{
|
|
string host = Environment.GetEnvironmentVariable("DATABASE_IP")
|
|
?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_IP")
|
|
?? "127.0.0.1";
|
|
string port = Environment.GetEnvironmentVariable("DATABASE_PORT")
|
|
?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_PORT")
|
|
?? "5432";
|
|
string db = Environment.GetEnvironmentVariable("DATABASE_NAME")
|
|
?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_NAME")
|
|
?? "game";
|
|
string user = Environment.GetEnvironmentVariable("DATABASE_USER")
|
|
?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_USER")
|
|
?? "postgres";
|
|
string pass = Environment.GetEnvironmentVariable("DATABASE_PASSWORD")
|
|
?? Environment.GetEnvironmentVariable("POSTGRES_DATABASE_PASSWORD")
|
|
?? "postgres";
|
|
|
|
string root = _configuration.ResourcePaths;
|
|
string datPath = _configuration.GameDataPath;
|
|
string langPath = _configuration.GameLanguagePath;
|
|
|
|
string[] datFiles = Directory.Exists(datPath)
|
|
? Directory.GetFiles(datPath, "*", SearchOption.AllDirectories)
|
|
: Array.Empty<string>();
|
|
string[] langFiles = Directory.Exists(langPath)
|
|
? Directory.GetFiles(langPath, "*", SearchOption.AllDirectories)
|
|
: Array.Empty<string>();
|
|
|
|
using var conn = new NpgsqlConnection($"Host={host};Port={port};Database={db};Username={user};Password={pass}");
|
|
conn.Open();
|
|
using var tx = conn.BeginTransaction();
|
|
|
|
using (var cmd = new NpgsqlCommand(@"CREATE TABLE IF NOT EXISTS resource_files (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
category TEXT NOT NULL,
|
|
relative_path TEXT NOT NULL,
|
|
sha256 TEXT NOT NULL,
|
|
content BYTEA NOT NULL,
|
|
size_bytes INT NOT NULL,
|
|
synced_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
UNIQUE(category, relative_path)
|
|
);", conn, tx))
|
|
{
|
|
cmd.ExecuteNonQuery();
|
|
}
|
|
|
|
UpsertFiles(conn, tx, root, "dat", datFiles);
|
|
UpsertFiles(conn, tx, root, "lang", langFiles);
|
|
|
|
tx.Commit();
|
|
Log.Info($"[PARSER_DB_SYNC] Synced resource_files dat={datFiles.Length} lang={langFiles.Length}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.Error("[PARSER_DB_SYNC] Failed to sync resource files", ex);
|
|
}
|
|
|
|
return Task.CompletedTask;
|
|
}
|
|
|
|
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
|
|
|
|
private static void UpsertFiles(NpgsqlConnection conn, NpgsqlTransaction tx, string root, string category, string[] files)
|
|
{
|
|
foreach (string file in files.Where(File.Exists))
|
|
{
|
|
byte[] content = File.ReadAllBytes(file);
|
|
string hash;
|
|
using (SHA256 sha = SHA256.Create())
|
|
{
|
|
hash = Convert.ToHexString(sha.ComputeHash(content));
|
|
}
|
|
|
|
string relative = Path.GetRelativePath(root, file).Replace('\\', '/');
|
|
|
|
using var cmd = new NpgsqlCommand(@"INSERT INTO resource_files(category,relative_path,sha256,content,size_bytes,synced_at)
|
|
VALUES (@category,@path,@sha,@content,@size,NOW())
|
|
ON CONFLICT (category, relative_path)
|
|
DO UPDATE SET sha256=EXCLUDED.sha256, content=EXCLUDED.content, size_bytes=EXCLUDED.size_bytes, synced_at=NOW();", conn, tx);
|
|
cmd.Parameters.AddWithValue("category", category);
|
|
cmd.Parameters.AddWithValue("path", relative);
|
|
cmd.Parameters.AddWithValue("sha", hash);
|
|
cmd.Parameters.AddWithValue("content", content);
|
|
cmd.Parameters.AddWithValue("size", content.Length);
|
|
cmd.ExecuteNonQuery();
|
|
}
|
|
}
|
|
}
|
|
}
|