Files
nexus/backend/Repositories/OpenClawConnectionProfileRepository.cs
AzuTear f5552218bc
CI - Build & Test / Backend (.NET) (push) Successful in 42s
CI - Build & Test / Frontend (Vue/TS) (push) Successful in 2m46s
CI - Build & Test / Security Check (push) Successful in 3s
CI - Build & Test / Deploy Nexus (push) Successful in 56s
feat: ship agent-first mission control v0.2.57
2026-07-31 22:39:47 +02:00

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
};
}