135 lines
5.0 KiB
C#
135 lines
5.0 KiB
C#
using Microsoft.EntityFrameworkCore;
|
|
using Nexus.Api.Data;
|
|
|
|
namespace Nexus.Api.Repositories;
|
|
|
|
public sealed class OpenClawConnectionProfileRepository(NexusDbContext db)
|
|
: IOpenClawConnectionProfileRepository
|
|
{
|
|
public Task<OpenClawConnectionProfile?> GetPrimaryAsync(
|
|
CancellationToken cancellationToken = default)
|
|
=> db.Set<OpenClawConnectionProfile>()
|
|
.AsNoTracking()
|
|
.SingleOrDefaultAsync(
|
|
profile => profile.ProfileId == OpenClawConnectionProfile.PrimaryProfileId,
|
|
cancellationToken);
|
|
|
|
public async Task<OpenClawConnectionProfile> SavePrimaryAsync(
|
|
OpenClawConnectionProfile profile,
|
|
int? expectedRevision,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(profile);
|
|
if (!string.Equals(
|
|
profile.ProfileId,
|
|
OpenClawConnectionProfile.PrimaryProfileId,
|
|
StringComparison.Ordinal))
|
|
{
|
|
throw new ArgumentException("Only the primary OpenClaw profile is supported.", nameof(profile));
|
|
}
|
|
|
|
var profiles = db.Set<OpenClawConnectionProfile>();
|
|
var current = await profiles.SingleOrDefaultAsync(
|
|
item => item.ProfileId == OpenClawConnectionProfile.PrimaryProfileId,
|
|
cancellationToken);
|
|
|
|
if (current is null)
|
|
{
|
|
if (expectedRevision is not null and not 0)
|
|
{
|
|
throw new OpenClawConnectionProfileConcurrencyException(
|
|
"The OpenClaw connection profile no longer exists.");
|
|
}
|
|
|
|
profile.Revision = 1;
|
|
profile.CreatedAt = profile.CreatedAt == default
|
|
? DateTimeOffset.UtcNow
|
|
: profile.CreatedAt;
|
|
profile.UpdatedAt = DateTimeOffset.UtcNow;
|
|
profiles.Add(profile);
|
|
await SaveChangesAsync(cancellationToken);
|
|
return Clone(profile);
|
|
}
|
|
|
|
if (expectedRevision is null || expectedRevision.Value != current.Revision)
|
|
{
|
|
throw new OpenClawConnectionProfileConcurrencyException(
|
|
"The OpenClaw connection profile changed since it was loaded.",
|
|
current.Revision);
|
|
}
|
|
|
|
current.Endpoint = profile.Endpoint;
|
|
current.DiscoverySource = profile.DiscoverySource;
|
|
current.RequiredVersion = profile.RequiredVersion;
|
|
current.TlsCertificateFingerprint = profile.TlsCertificateFingerprint;
|
|
current.AdoptionState = profile.AdoptionState;
|
|
current.ManagementEnabled = profile.ManagementEnabled;
|
|
current.CapabilityHash = profile.CapabilityHash;
|
|
current.DeviceId = profile.DeviceId;
|
|
current.LastProbedAt = profile.LastProbedAt;
|
|
current.LastVerifiedAt = profile.LastVerifiedAt;
|
|
current.AdoptedAt = profile.AdoptedAt;
|
|
current.UpdatedAt = DateTimeOffset.UtcNow;
|
|
current.Revision++;
|
|
|
|
await SaveChangesAsync(cancellationToken);
|
|
return Clone(current);
|
|
}
|
|
|
|
public async Task<bool> DeletePrimaryAsync(
|
|
int expectedRevision,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var profiles = db.Set<OpenClawConnectionProfile>();
|
|
var current = await profiles.SingleOrDefaultAsync(
|
|
item => item.ProfileId == OpenClawConnectionProfile.PrimaryProfileId,
|
|
cancellationToken);
|
|
if (current is null)
|
|
return false;
|
|
if (current.Revision != expectedRevision)
|
|
{
|
|
throw new OpenClawConnectionProfileConcurrencyException(
|
|
"The OpenClaw connection profile changed since it was loaded.",
|
|
current.Revision);
|
|
}
|
|
|
|
profiles.Remove(current);
|
|
await SaveChangesAsync(cancellationToken);
|
|
return true;
|
|
}
|
|
|
|
private async Task SaveChangesAsync(CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
await db.SaveChangesAsync(cancellationToken);
|
|
}
|
|
catch (DbUpdateConcurrencyException exception)
|
|
{
|
|
throw new OpenClawConnectionProfileConcurrencyException(
|
|
"The OpenClaw connection profile changed concurrently.",
|
|
innerException: exception);
|
|
}
|
|
}
|
|
|
|
private static OpenClawConnectionProfile Clone(OpenClawConnectionProfile profile)
|
|
=> new()
|
|
{
|
|
ProfileId = profile.ProfileId,
|
|
Endpoint = profile.Endpoint,
|
|
DiscoverySource = profile.DiscoverySource,
|
|
RequiredVersion = profile.RequiredVersion,
|
|
TlsCertificateFingerprint = profile.TlsCertificateFingerprint,
|
|
AdoptionState = profile.AdoptionState,
|
|
ManagementEnabled = profile.ManagementEnabled,
|
|
CapabilityHash = profile.CapabilityHash,
|
|
DeviceId = profile.DeviceId,
|
|
Revision = profile.Revision,
|
|
CreatedAt = profile.CreatedAt,
|
|
UpdatedAt = profile.UpdatedAt,
|
|
LastProbedAt = profile.LastProbedAt,
|
|
LastVerifiedAt = profile.LastVerifiedAt,
|
|
AdoptedAt = profile.AdoptedAt
|
|
};
|
|
}
|