Updated translation service and finished splitting out responsibilities for now
This commit is contained in:
@@ -29,6 +29,9 @@
|
||||
<Content Include="..\.dockerignore">
|
||||
<Link>.dockerignore</Link>
|
||||
</Content>
|
||||
<Content Update="appsettings.Development.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,14 +1,30 @@
|
||||
using FictionArchive.Common.Enums;
|
||||
using FictionArchive.Service.TranslationService.Models.Database;
|
||||
using FictionArchive.Service.TranslationService.Models.Enums;
|
||||
using FictionArchive.Service.TranslationService.Services.Database;
|
||||
using FictionArchive.Service.TranslationService.Services.TranslationEngines;
|
||||
|
||||
namespace FictionArchive.Service.TranslationService.GraphQL;
|
||||
|
||||
public class Mutation
|
||||
{
|
||||
public async Task<string> TranslateText(string text, Language from, Language to, string translationEngineKey, IEnumerable<ITranslationEngineAdapter> translationEngines)
|
||||
public async Task<string> TranslateText(string text, Language from, Language to, string translationEngineKey, IEnumerable<ITranslationEngine> translationEngines, TranslationServiceDbContext dbContext)
|
||||
{
|
||||
var engine = translationEngines.FirstOrDefault(engine => engine.Descriptor.Key == translationEngineKey);
|
||||
var translation = await engine.GetTranslation(text, from, to);
|
||||
|
||||
dbContext.TranslationRequests.Add(new TranslationRequest()
|
||||
{
|
||||
OriginalText = text,
|
||||
BilledCharacterCount = 0, // FILL ME
|
||||
From = from,
|
||||
To = to,
|
||||
Status = translation != null ? TranslationRequestStatus.Success : TranslationRequestStatus.Failed,
|
||||
TranslatedText = translation,
|
||||
TranslationEngineKey = translationEngineKey
|
||||
});
|
||||
await dbContext.SaveChangesAsync();
|
||||
|
||||
return translation;
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ public class Query
|
||||
{
|
||||
[UseFiltering]
|
||||
[UseSorting]
|
||||
public IEnumerable<TranslationEngineDescriptor> GetTranslationEngines(IEnumerable<ITranslationEngineAdapter> engines)
|
||||
public IEnumerable<TranslationEngineDescriptor> GetTranslationEngines(IEnumerable<ITranslationEngine> engines)
|
||||
{
|
||||
return engines.Select(engine => engine.Descriptor);
|
||||
}
|
||||
|
||||
72
FictionArchive.Service.TranslationService/Migrations/20251118052322_Initial.Designer.cs
generated
Normal file
72
FictionArchive.Service.TranslationService/Migrations/20251118052322_Initial.Designer.cs
generated
Normal file
@@ -0,0 +1,72 @@
|
||||
// <auto-generated />
|
||||
using FictionArchive.Service.TranslationService.Services.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using NodaTime;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace FictionArchive.Service.TranslationService.Migrations
|
||||
{
|
||||
[DbContext(typeof(TranslationServiceDbContext))]
|
||||
[Migration("20251118052322_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "9.0.11")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("FictionArchive.Service.TranslationService.Models.Database.TranslationRequest", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<long>("BilledCharacterCount")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<Instant>("CreatedTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("From")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<Instant>("LastUpdatedTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("OriginalText")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("To")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("TranslatedText")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("TranslationEngineKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("TranslationRequests");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using NodaTime;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace FictionArchive.Service.TranslationService.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "TranslationRequests",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<long>(type: "bigint", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
OriginalText = table.Column<string>(type: "text", nullable: false),
|
||||
TranslatedText = table.Column<string>(type: "text", nullable: true),
|
||||
From = table.Column<int>(type: "integer", nullable: false),
|
||||
To = table.Column<int>(type: "integer", nullable: false),
|
||||
TranslationEngineKey = table.Column<string>(type: "text", nullable: false),
|
||||
Status = table.Column<int>(type: "integer", nullable: false),
|
||||
BilledCharacterCount = table.Column<long>(type: "bigint", nullable: false),
|
||||
CreatedTime = table.Column<Instant>(type: "timestamp with time zone", nullable: false),
|
||||
LastUpdatedTime = table.Column<Instant>(type: "timestamp with time zone", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_TranslationRequests", x => x.Id);
|
||||
});
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "TranslationRequests");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// <auto-generated />
|
||||
using FictionArchive.Service.TranslationService.Services.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using NodaTime;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace FictionArchive.Service.TranslationService.Migrations
|
||||
{
|
||||
[DbContext(typeof(TranslationServiceDbContext))]
|
||||
partial class TranslationServiceDbContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "9.0.11")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("FictionArchive.Service.TranslationService.Models.Database.TranslationRequest", b =>
|
||||
{
|
||||
b.Property<long>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("bigint");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
|
||||
|
||||
b.Property<long>("BilledCharacterCount")
|
||||
.HasColumnType("bigint");
|
||||
|
||||
b.Property<Instant>("CreatedTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("From")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<Instant>("LastUpdatedTime")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<string>("OriginalText")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<int>("Status")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("To")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("TranslatedText")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<string>("TranslationEngineKey")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("TranslationRequests");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using FictionArchive.Common.Enums;
|
||||
using FictionArchive.Service.Shared.Models;
|
||||
using FictionArchive.Service.TranslationService.Models.Enums;
|
||||
|
||||
namespace FictionArchive.Service.TranslationService.Models.Database;
|
||||
|
||||
public class TranslationRequest : BaseEntity<Guid>
|
||||
{
|
||||
public required string OriginalText { get; set; }
|
||||
public string? TranslatedText { get; set; }
|
||||
public Language From { get; set; }
|
||||
public Language To { get; set; }
|
||||
public required string TranslationEngineKey { get; set; }
|
||||
public TranslationRequestStatus Status { get; set; }
|
||||
public uint BilledCharacterCount { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace FictionArchive.Service.TranslationService.Models.Enums;
|
||||
|
||||
public enum TranslationRequestStatus
|
||||
{
|
||||
Failed = -1,
|
||||
Pending = 0,
|
||||
Success = 1,
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
using DeepL;
|
||||
using FictionArchive.Common.Extensions;
|
||||
using FictionArchive.Service.Shared.Extensions;
|
||||
using FictionArchive.Service.Shared.Services.GraphQL;
|
||||
using FictionArchive.Service.TranslationService.GraphQL;
|
||||
using FictionArchive.Service.TranslationService.Services.Database;
|
||||
using FictionArchive.Service.TranslationService.Services.TranslationEngines;
|
||||
using FictionArchive.Service.TranslationService.Services.TranslationEngines.DeepLTranslate;
|
||||
|
||||
@@ -11,19 +14,19 @@ public class Program
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
builder.AddLocalAppsettings();
|
||||
|
||||
builder.Services.AddHealthChecks();
|
||||
|
||||
#region Database
|
||||
|
||||
builder.Services.RegisterDbContext<TranslationServiceDbContext>(builder.Configuration.GetConnectionString("DefaultConnection"));
|
||||
|
||||
#endregion
|
||||
|
||||
#region GraphQL
|
||||
|
||||
builder.Services.AddGraphQLServer()
|
||||
.AddQueryType<Query>()
|
||||
.AddMutationType<Mutation>()
|
||||
.AddType<UnsignedIntType>()
|
||||
.AddMutationConventions(applyToAllMutations: true)
|
||||
.AddFiltering(opt => opt.AddDefaults().BindRuntimeType<uint, UnsignedIntOperationFilterInputType>())
|
||||
.AddSorting()
|
||||
.AddProjections();
|
||||
builder.Services.AddDefaultGraphQl<Query, Mutation>();
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -33,7 +36,7 @@ public class Program
|
||||
{
|
||||
return new DeepLClient(builder.Configuration["DeepL:ApiKey"]);
|
||||
});
|
||||
builder.Services.AddTransient<ITranslationEngineAdapter, DeepLTranslationAdapater>();
|
||||
builder.Services.AddTransient<ITranslationEngine, DeepLTranslationEngine>();
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
using FictionArchive.Service.Shared.Services.Database;
|
||||
using FictionArchive.Service.TranslationService.Models.Database;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
namespace FictionArchive.Service.TranslationService.Services.Database;
|
||||
|
||||
public class TranslationServiceDbContext : FictionArchiveDbContext
|
||||
{
|
||||
public DbSet<TranslationRequest> TranslationRequests { get; set; }
|
||||
|
||||
public TranslationServiceDbContext(DbContextOptions options, ILogger<TranslationServiceDbContext> logger) : base(options, logger)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -5,15 +5,15 @@ using Language = FictionArchive.Common.Enums.Language;
|
||||
|
||||
namespace FictionArchive.Service.TranslationService.Services.TranslationEngines.DeepLTranslate;
|
||||
|
||||
public class DeepLTranslationAdapater : ITranslationEngineAdapter
|
||||
public class DeepLTranslationEngine : ITranslationEngine
|
||||
{
|
||||
private readonly DeepLClient _deepLClient;
|
||||
private readonly ILogger<DeepLTranslationAdapater> _logger;
|
||||
private readonly ILogger<DeepLTranslationEngine> _logger;
|
||||
|
||||
private const string DisplayName = "DeepL";
|
||||
private const string Key = "deepl";
|
||||
|
||||
public DeepLTranslationAdapater(DeepLClient deepLClient, ILogger<DeepLTranslationAdapater> logger)
|
||||
public DeepLTranslationEngine(DeepLClient deepLClient, ILogger<DeepLTranslationEngine> logger)
|
||||
{
|
||||
_deepLClient = deepLClient;
|
||||
_logger = logger;
|
||||
@@ -45,7 +45,8 @@ public class DeepLTranslationAdapater : ITranslationEngineAdapter
|
||||
Language.En => LanguageCode.EnglishAmerican,
|
||||
Language.Kr => LanguageCode.Korean,
|
||||
Language.Ch => LanguageCode.Chinese,
|
||||
Language.Ja => LanguageCode.Japanese
|
||||
Language.Ja => LanguageCode.Japanese,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(language), language, null)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using FictionArchive.Service.TranslationService.Models;
|
||||
|
||||
namespace FictionArchive.Service.TranslationService.Services.TranslationEngines;
|
||||
|
||||
public interface ITranslationEngineAdapter
|
||||
public interface ITranslationEngine
|
||||
{
|
||||
public TranslationEngineDescriptor Descriptor { get; }
|
||||
public Task<string?> GetTranslation(string body, Language from, Language to);
|
||||
@@ -8,5 +8,8 @@
|
||||
"DeepL": {
|
||||
"ApiKey": "REPLACE_ME"
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnection": "Host=localhost;Database=FictionArchive_NovelService;Username=postgres;password=postgres"
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user