Skip to content

Commit

Permalink
Fix error creating example project (#1479)
Browse files Browse the repository at this point in the history
* add a test creating an example project, fix error trying to delete project because it was in use

* reorder when writing systems are created for the example project in relation to Entries as entry creation requires writing systems
  • Loading branch information
hahn-kev authored Feb 20, 2025
1 parent cca4032 commit e1ea581
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 30 deletions.
2 changes: 2 additions & 0 deletions backend/FwLite/LcmCrdt.Tests/LcmCrdtTestsKernel.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Logging;

namespace LcmCrdt.Tests;

Expand All @@ -9,6 +10,7 @@ public static class LcmCrdtTestsKernel
public static IServiceCollection AddTestLcmCrdtClient(this IServiceCollection services, CrdtProject? project = null)
{
services.TryAddSingleton<IConfiguration>(new ConfigurationRoot([]));
services.AddLogging(builder => builder.AddDebug());
services.AddLcmCrdtClient();
if (project is not null)
{
Expand Down
13 changes: 13 additions & 0 deletions backend/FwLite/LcmCrdt.Tests/OpenProjectTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ namespace LcmCrdt.Tests;

public class OpenProjectTests
{
[Fact]
public async Task CanCreateExampleProject()
{
var sqliteConnectionString = "ExampleProject.sqlite";
if (File.Exists(sqliteConnectionString)) File.Delete(sqliteConnectionString);
var builder = Host.CreateEmptyApplicationBuilder(null);
builder.Services.AddTestLcmCrdtClient();
using var host = builder.Build();
var services = host.Services;
var asyncScope = services.CreateAsyncScope();
var crdtProjectsService = asyncScope.ServiceProvider.GetRequiredService<CrdtProjectsService>();
await crdtProjectsService.CreateExampleProject("ExampleProject");
}
[Fact]
public async Task OpeningAProjectWorks()
{
Expand Down
90 changes: 60 additions & 30 deletions backend/FwLite/LcmCrdt/CrdtProjectsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using LcmCrdt.Objects;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Migrations;
using MiniLcm.Project;
Expand Down Expand Up @@ -110,15 +111,44 @@ public async Task<CrdtProject> CreateProject(CreateProjectRequest request)
await SeedSystemData(serviceScope.ServiceProvider.GetRequiredService<DataModel>(), projectData.ClientId);
await (request.AfterCreate?.Invoke(serviceScope.ServiceProvider, crdtProject) ?? Task.CompletedTask);
}
catch
catch(Exception e)
{
logger.LogError("Failed to create project {Project}, deleting database", crdtProject.Name);
await db.Database.EnsureDeletedAsync();
logger.LogError(e, "Failed to create project {Project}, deleting database", crdtProject.Name);
await db.Database.CloseConnectionAsync();
EnsureDeleteProject(sqliteFile);
throw;
}
return crdtProject;
}

private void EnsureDeleteProject(string sqliteFile)
{
_ = Task.Run(async () =>
{
var counter = 0;
while (File.Exists(sqliteFile) && counter < 10)
{
await Task.Delay(1000);
try
{
File.Delete(sqliteFile);
return;
}
catch (IOException)
{
//inuse, try again
}
catch (Exception exception)
{
logger.LogError(exception, "Failed to delete sqlite file {SqliteFile}", sqliteFile);
return;
}
counter++;
}
logger.LogError("Failed to delete sqlite file {SqliteFile} after 10 attempts", sqliteFile);
});
}

public async Task DeleteProject(string name)
{
var project = GetProject(name) ?? throw new InvalidOperationException($"Project {name} not found");
Expand Down Expand Up @@ -149,33 +179,6 @@ internal static async Task SeedSystemData(DataModel dataModel, Guid clientId)
public static async Task SampleProjectData(IServiceProvider provider, CrdtProject project)
{
var lexboxApi = provider.GetRequiredService<IMiniLcmApi>();
await lexboxApi.CreateEntry(new()
{
Id = Guid.NewGuid(),
LexemeForm = { Values = { { "en", "Apple" } } },
CitationForm = { Values = { { "en", "Apple" } } },
LiteralMeaning = { Values = { { "en", "Fruit" } } },
Senses =
[
new()
{
Gloss = { Values = { { "en", "Fruit" } } },
Definition =
{
Values =
{
{
"en",
"fruit with red, yellow, or green skin with a sweet or tart crispy white flesh"
}
}
},
SemanticDomains = [],
ExampleSentences = [new() { Sentence = { Values = { { "en", "We ate an apple" } } } }]
}
]
});

await lexboxApi.CreateWritingSystem(WritingSystemType.Vernacular,
new()
{
Expand Down Expand Up @@ -222,5 +225,32 @@ await lexboxApi.CreateWritingSystem(WritingSystemType.Analysis,
Font = "Arial",
Exemplars = WritingSystem.LatinExemplars
});

await lexboxApi.CreateEntry(new()
{
Id = Guid.NewGuid(),
LexemeForm = { Values = { { "en", "Apple" } } },
CitationForm = { Values = { { "en", "Apple" } } },
LiteralMeaning = { Values = { { "en", "Fruit" } } },
Senses =
[
new()
{
Gloss = { Values = { { "en", "Fruit" } } },
Definition =
{
Values =
{
{
"en",
"fruit with red, yellow, or green skin with a sweet or tart crispy white flesh"
}
}
},
SemanticDomains = [],
ExampleSentences = [new() { Sentence = { Values = { { "en", "We ate an apple" } } } }]
}
]
});
}
}

0 comments on commit e1ea581

Please sign in to comment.