Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions backend/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@
<PackageVersion Include="SIL.Chorus.LibChorus" Version="6.0.0-beta0064" />
<PackageVersion Include="SIL.Chorus.Mercurial" Version="6.5.1.43" />
<PackageVersion Include="SIL.ChorusPlugin.LfMergeBridge" Version="4.3.0-beta0048" />
<PackageVersion Include="SIL.Harmony" Version="0.2.1-rc.202" />
<PackageVersion Include="SIL.Harmony.Core" Version="0.2.1-rc.202" />
<PackageVersion Include="SIL.Harmony.Linq2db" Version="0.2.1-rc.202" />
<PackageVersion Include="SIL.Harmony" Version="0.2.1-rc.211" />
<PackageVersion Include="SIL.Harmony.Core" Version="0.2.1-rc.211" />
<PackageVersion Include="SIL.Harmony.Linq2db" Version="0.2.1-rc.211" />
<PackageVersion Include="SIL.Core" Version="17.0.0" />
<PackageVersion Include="SIL.LCModel" Version="11.0.0-beta0165" />
<PackageVersion Include="SIL.LCModel.FixData" Version="11.0.0-beta0165" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -943,17 +943,37 @@
{
"$type": "uploaded:RemoteResource",
"RemoteId": "withdrawal",
"Metadata": null,
"EntityId": "9c8b252c-d342-dfe8-c1dd-5899471ecbd1"
},
{
"$type": "uploaded:RemoteResource",
"RemoteId": "Identity",
"Metadata": {},
"EntityId": "c0fe5fa7-76ba-de0c-2a94-316fbbb84b0c"
},
{
"$type": "create:remote-resource",
"RemoteId": "Buckinghamshire",
"Metadata": null,
"EntityId": "188a57e7-7d61-8742-59eb-c0bfbf959737"
},
{
"$type": "create:remote-resource",
"RemoteId": "back-end",
"Metadata": {},
"EntityId": "0aace990-edd6-295c-2538-7611f0622e6e"
},
{
"$type": "create:pendingUpload",
"Metadata": null,
"EntityId": "52d7432c-ad4f-430c-8304-925603b3fefa"
},
{
"$type": "create:pendingUpload",
"Metadata": {},
"EntityId": "f58a4713-11d6-999e-d355-0344e4fcd7b3"
},
{
"$type": "delete:RemoteResource",
"EntityId": "e14de071-3ed0-b12a-7865-da43fbfe8f84"
Expand Down Expand Up @@ -1293,5 +1313,10 @@
{
"$type": "SetMainPublicationChange",
"EntityId": "c775e310-fc5c-6d01-5a02-146d579a88e5"
},
{
"$type": "set:remote-resource-metadata",
"Metadata": {},
"EntityId": "ef64afaa-972e-34b2-b57f-ae99e543b5ea"
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -625,5 +625,42 @@
],
"EntityId": "f27a032b-e0f6-f389-b466-959bdb17086d"
}
},
{
"Input": {
"$type": "uploaded:RemoteResource",
"RemoteId": "withdrawal",
"EntityId": "9c8b252c-d342-dfe8-c1dd-5899471ecbd1"
},
"Output": {
"$type": "uploaded:RemoteResource",
"RemoteId": "withdrawal",
"Metadata": null,
"EntityId": "9c8b252c-d342-dfe8-c1dd-5899471ecbd1"
}
},
{
"Input": {
"$type": "create:remote-resource",
"RemoteId": "Buckinghamshire",
"EntityId": "188a57e7-7d61-8742-59eb-c0bfbf959737"
},
"Output": {
"$type": "create:remote-resource",
"RemoteId": "Buckinghamshire",
"Metadata": null,
"EntityId": "188a57e7-7d61-8742-59eb-c0bfbf959737"
}
},
{
"Input": {
"$type": "create:pendingUpload",
"EntityId": "52d7432c-ad4f-430c-8304-925603b3fefa"
},
"Output": {
"$type": "create:pendingUpload",
"Metadata": null,
"EntityId": "52d7432c-ad4f-430c-8304-925603b3fefa"
}
}
]
13 changes: 10 additions & 3 deletions backend/FwLite/LcmCrdt.Tests/Changes/UseChangesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -280,12 +280,19 @@ private static IEnumerable<ChangeWithDependencies> GetAllChanges()
var removePublicationChange = new RemovePublicationChange(entry.Id, publication2.Id);
yield return new ChangeWithDependencies(removePublicationChange, [replacePublicationChange]);

yield return new ChangeWithDependencies(new CreateRemoteResourceChange(Guid.NewGuid(), "test-remote-id"));
var createRemoteResourcePendingUploadChange = new CreateRemoteResourcePendingUploadChange(Guid.NewGuid());
var createRemoteResourceChange = new CreateRemoteResourceChange<NoMetadata>(Guid.NewGuid(), "test-remote-id");
yield return new ChangeWithDependencies(createRemoteResourceChange);
var createRemoteResourcePendingUploadChange = new CreateRemoteResourcePendingUploadChange<NoMetadata>(Guid.NewGuid());
yield return new ChangeWithDependencies(createRemoteResourcePendingUploadChange);
yield return new ChangeWithDependencies(
new RemoteResourceUploadedChange(createRemoteResourcePendingUploadChange.EntityId, "test-remote-id"),
new RemoteResourceUploadedChange<NoMetadata>(createRemoteResourcePendingUploadChange.EntityId, "test-remote-id"),
[createRemoteResourcePendingUploadChange]);
yield return new ChangeWithDependencies(
new SetRemoteResourceMetadataChange<NoMetadata>(createRemoteResourceChange.EntityId, new NoMetadata()),
[createRemoteResourceChange]);
yield return new ChangeWithDependencies(
new DeleteRemoteResourceChange<NoMetadata>(createRemoteResourceChange.EntityId),
[createRemoteResourceChange]);

var customView = new CustomView
{
Expand Down
3 changes: 2 additions & 1 deletion backend/FwLite/LcmCrdt.Tests/ConfigRegistrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,11 @@ public class ConfigRegistrationTests
private readonly HashSet<Type> _excludedChangeTypes =
[
typeof(JsonPatchChange<ComplexFormComponent>), //not supported
typeof(JsonPatchChange<RemoteResource>), //not supported
typeof(JsonPatchChange<RemoteResource<NoMetadata>>), //not supported
typeof(JsonPatchChange<ExampleSentence>), //replaced by JsonPatchExampleSentenceChange
typeof(JsonPatchChange<CustomView>), //not supported. Use EditCustomViewChange
typeof(DeleteChange<MorphType>), //MorphTypes cannot be deleted
typeof(DeleteChange<RemoteResource<NoMetadata>>), //replaced by DeleteRemoteResourceChange<NoMetadata>
];

private readonly CrdtConfig _config;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3828,7 +3828,15 @@
"$type": "RemoteResource",
"Id": "fce4cb31-93bd-f380-fd73-3fb0d09c0fa5",
"DeletedAt": "2025-09-17T23:53:03.6147633+02:00",
"RemoteId": "end-to-end"
"RemoteId": "end-to-end",
"Metadata": null
},
{
"$type": "RemoteResource",
"Id": "666023e2-5d9e-58e1-15ba-d47562be1752",
"DeletedAt": "2026-07-01T14:13:37.7894421+02:00",
"RemoteId": "4th generation",
"Metadata": {}
},
{
"$type": "MiniLcmCrdtAdapter",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3900,5 +3900,20 @@
"Id": "853b91e6-d738-7d5d-cc98-e62904160c35",
"DeletedAt": null
}
},
{
"Input": {
"$type": "RemoteResource",
"Id": "fce4cb31-93bd-f380-fd73-3fb0d09c0fa5",
"DeletedAt": "2025-09-17T23:53:03.6147633+02:00",
"RemoteId": "end-to-end"
},
"Output": {
"$type": "RemoteResource",
"Id": "fce4cb31-93bd-f380-fd73-3fb0d09c0fa5",
"DeletedAt": "2025-09-17T23:53:03.6147633+02:00",
"RemoteId": "end-to-end",
"Metadata": null
}
}
]
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
{
DerivedTypes: [
{
DerivedType: RemoteResourceUploadedChange,
DerivedType: RemoteResourceUploadedChange<NoMetadata>,
TypeDiscriminator: uploaded:RemoteResource
},
{
DerivedType: CreateRemoteResourceChange,
DerivedType: CreateRemoteResourceChange<NoMetadata>,
TypeDiscriminator: create:remote-resource
},
{
DerivedType: CreateRemoteResourcePendingUploadChange,
DerivedType: CreateRemoteResourcePendingUploadChange<NoMetadata>,
TypeDiscriminator: create:pendingUpload
},
{
DerivedType: DeleteChange<RemoteResource>,
DerivedType: SetRemoteResourceMetadataChange<NoMetadata>,
TypeDiscriminator: set:remote-resource-metadata
},
{
DerivedType: DeleteRemoteResourceChange<NoMetadata>,
TypeDiscriminator: delete:RemoteResource
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -466,16 +466,19 @@
Relational:TableName: LocalResource
Relational:ViewName:
Relational:ViewSchema:
EntityType: RemoteResource
EntityType: RemoteResource<NoMetadata>
Properties:
Id (Guid) Required PK AfterSave:Throw ValueGenerated.OnAdd
DeletedAt (DateTimeOffset?)
Metadata (NoMetadata)
Annotations:
Relational:ColumnType: jsonb
RemoteId (string)
SnapshotId (no field, Guid?) Shadow FK Index
Keys:
Id PK
Foreign keys:
RemoteResource {'SnapshotId'} -> ObjectSnapshot {'Id'} Unique SetNull
RemoteResource<NoMetadata> {'SnapshotId'} -> ObjectSnapshot {'Id'} Unique SetNull
Indexes:
SnapshotId Unique
Annotations:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
TypeDiscriminator: MiniLcmCrdtAdapter
},
{
DerivedType: RemoteResource,
DerivedType: RemoteResource<NoMetadata>,
TypeDiscriminator: RemoteResource
}
],
Expand Down
2 changes: 1 addition & 1 deletion backend/FwLite/LcmCrdt.Tests/EntityCopyMethodTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public static IEnumerable<object[]> GetEntityTypes()
var crdtConfig = new CrdtConfig();
LcmCrdtKernel.ConfigureCrdt(crdtConfig);
return crdtConfig.ObjectTypes
.Except([typeof(RemoteResource)])//exclude remote resource as it's a harmony defined type, not miniLcm
.Except([typeof(RemoteResource<NoMetadata>)])//exclude remote resource as it's a harmony defined type, not miniLcm
.Select(t => new object[] { t });
}

Expand Down
7 changes: 6 additions & 1 deletion backend/FwLite/LcmCrdt/LcmCrdtKernel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using SIL.Harmony.Linq2db;
using SIL.Harmony.Core;
using SIL.Harmony.Changes;
using SIL.Harmony.Resource;
using LcmCrdt.Changes;
using LcmCrdt.Changes.CustomJsonPatches;
using LcmCrdt.Changes.Entries;
Expand Down Expand Up @@ -61,6 +62,10 @@ public static IServiceCollection AddLcmCrdtClientCore(this IServiceCollection se
services.RemoveAll<LcmCrdtDbContext>();//we don't want to be able to inject these directly as they will leak.
services.AddOptions<LcmCrdtConfig>().BindConfiguration("LcmCrdt");

// Order matters: AddCrdtRemoteResources' Configure<CrdtConfig> delegate must run before
// ConfigureCrdt so the RemoteResourcesEnabled guard in ConfigureCrdt sees enabled=true and
// skips its own AddRemoteResourceEntity call. Configure delegates run in registration order.
services.AddCrdtRemoteResources<NoMetadata>();
services.AddCrdtDataDbFactory<LcmCrdtDbContext>(
ConfigureCrdt
);
Expand Down Expand Up @@ -307,7 +312,7 @@ public static void ConfigureCrdt(CrdtConfig config)
}).IsUnique().HasFilter($"{componentSenseId} IS NULL");
});

config.AddRemoteResourceEntity();
if (!config.RemoteResourcesEnabled) config.AddRemoteResourceEntity<NoMetadata>();

config.ChangeTypeListBuilder.Add<JsonPatchChange<Entry>>()
.Add<JsonPatchChange<Sense>>()
Expand Down
16 changes: 8 additions & 8 deletions backend/FwLite/LcmCrdt/MediaServer/LcmMediaService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
namespace LcmCrdt.MediaServer;

public class LcmMediaService(
ResourceService resourceService,
ResourceService<NoMetadata> resourceService,
CurrentProjectService currentProjectService,
IOptions<CrdtConfig> options,
IRefitHttpServiceFactory refitFactory,
IServerHttpClientProvider httpClientProvider,
ILogger<LcmMediaService> logger
) : IRemoteResourceService
) : IRemoteResourceService<NoMetadata>
{
public async Task<HarmonyResource[]> AllResources()
public async Task<HarmonyResource<NoMetadata>[]> AllResources()
{
return await resourceService.AllResources();
}
Expand Down Expand Up @@ -87,7 +87,7 @@ private async Task<IMediaServerClient> MediaServerClient()
return mediaClient;
}

async Task<DownloadResult> IRemoteResourceService.DownloadResource(string remoteId, string localResourceCachePath)
async Task<DownloadResult> IRemoteResourceService<NoMetadata>.DownloadResource(string remoteId, string localResourceCachePath)
{
var projectResourceCachePath = ProjectResourceCachePath;
Directory.CreateDirectory(projectResourceCachePath);
Expand All @@ -112,7 +112,7 @@ public static string ProjectCachePath(CrdtProject project, CrdtConfig options)
}


async Task<UploadResult> IRemoteResourceService.UploadResource(Guid resourceId, string localPath)
async Task<UploadResult<NoMetadata>> IRemoteResourceService<NoMetadata>.UploadResource(Guid resourceId, string localPath, NoMetadata? metadata)
{
var mediaClient = await MediaServerClient();
var fileName = Path.GetFileName(localPath);
Expand All @@ -121,10 +121,10 @@ await mediaClient.UploadFile(
projectId: currentProjectService.ProjectData.Id,
fileId: resourceId.ToString("D"),
filename: fileName);
return new UploadResult(resourceId.ToString("N"));
return new UploadResult<NoMetadata>(resourceId.ToString("N"));
}

public async Task<(HarmonyResource resource, bool newResource)> SaveFile(Stream stream, LcmFileMetadata metadata)
public async Task<(HarmonyResource<NoMetadata> resource, bool newResource)> SaveFile(Stream stream, LcmFileMetadata metadata)
{
var projectResourceCachePath = ProjectResourceCachePath;
Directory.CreateDirectory(projectResourceCachePath);
Expand All @@ -138,7 +138,7 @@ await mediaClient.UploadFile(

try
{
IRemoteResourceService? remoteResourceService = null;
IRemoteResourceService<NoMetadata>? remoteResourceService = null;
if (await httpClientProvider.ConnectionStatus() == ConnectionStatus.Online) remoteResourceService = this;
return (await resourceService.AddLocalResource(
localPath,
Expand Down
Loading
Loading