This commit is contained in:
StellaOps Bot
2025-12-13 02:22:15 +02:00
parent 564df71bfb
commit 999e26a48e
395 changed files with 25045 additions and 2224 deletions

View File

@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<!-- Keep Concelier test harness active while trimming Mongo dependencies. Allow opt-out per project. -->
<!-- Keep Concelier test harness active while trimming legacy dependencies. Allow opt-out per project. -->
<UseConcelierTestInfra Condition="'$(UseConcelierTestInfra)'==''">true</UseConcelierTestInfra>
<!-- Suppress noisy warnings from duplicate usings and analyzer fixture hints during Concelier test harness runs. -->
<NoWarn>$(NoWarn);CS0105;CS1591;CS8601;CS8602;CS8604;CS0618;RS1032;RS2007;xUnit1041;xUnit1031;xUnit2013;NU1510;NETSDK1023;SYSLIB0057</NoWarn>

View File

@@ -6,7 +6,7 @@ using StellaOps.Concelier.Storage.Postgres.Advisories;
namespace StellaOps.Concelier.WebService.DualWrite;
/// <summary>
/// Postgres-backed advisory store that implements the legacy Mongo contracts.
/// Postgres-backed advisory store that implements the legacy storage contracts.
/// </summary>
public sealed class DualWriteAdvisoryStore : IAdvisoryStore
{

View File

@@ -7,8 +7,8 @@ namespace StellaOps.Concelier.WebService.Options;
public sealed class ConcelierOptions
{
[Obsolete("Mongo storage has been removed; use PostgresStorage.")]
public StorageOptions Storage { get; set; } = new();
[Obsolete("Legacy storage has been removed; use PostgresStorage.")]
public LegacyStorageOptions LegacyStorage { get; set; } = new();
public PostgresStorageOptions? PostgresStorage { get; set; } = new PostgresStorageOptions
{
@@ -37,10 +37,10 @@ public sealed class ConcelierOptions
/// </summary>
public AirGapOptions AirGap { get; set; } = new();
[Obsolete("Mongo storage has been removed; use PostgresStorage.")]
public sealed class StorageOptions
[Obsolete("Legacy storage has been removed; use PostgresStorage.")]
public sealed class LegacyStorageOptions
{
public string Driver { get; set; } = "mongo";
public string Driver { get; set; } = "postgres";
public string Dsn { get; set; } = string.Empty;
@@ -56,7 +56,6 @@ public sealed class ConcelierOptions
{
/// <summary>
/// Enable PostgreSQL storage for LNM linkset cache.
/// When true, the linkset cache is stored in PostgreSQL instead of MongoDB.
/// </summary>
public bool Enabled { get; set; }

View File

@@ -226,7 +226,7 @@ builder.Services.AddOptions<AdvisoryObservationEventPublisherOptions>()
{
options.Subject ??= "concelier.advisory.observation.updated.v1";
options.Stream ??= "CONCELIER_OBS";
options.Transport = string.IsNullOrWhiteSpace(options.Transport) ? "mongo" : options.Transport;
options.Transport = string.IsNullOrWhiteSpace(options.Transport) ? "inmemory" : options.Transport;
})
.ValidateOnStart();
builder.Services.AddConcelierAocGuards();

View File

@@ -673,7 +673,7 @@ public sealed class AcscConnector : IFeedConnector
private async Task<AcscCursor> GetCursorCoreAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? AcscCursor.Empty : AcscCursor.FromBson(state.Cursor);
return state is null ? AcscCursor.Empty : AcscCursor.FromDocument(state.Cursor);
}
private Task UpdateCursorAsync(AcscCursor cursor, CancellationToken cancellationToken)

View File

@@ -70,7 +70,7 @@ internal sealed record AcscCursor(
return document;
}
public static AcscCursor FromBson(DocumentObject? document)
public static AcscCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -332,8 +332,8 @@ public sealed class CccsConnector : IFeedConnector
}
var dtoJson = JsonSerializer.Serialize(dto, DtoSerializerOptions);
var dtoBson = DocumentObject.Parse(dtoJson);
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, DtoSchemaVersion, dtoBson, now);
var dtoDoc = DocumentObject.Parse(dtoJson);
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, DtoSchemaVersion, dtoDoc, now);
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
@@ -459,7 +459,7 @@ public sealed class CccsConnector : IFeedConnector
private async Task<CccsCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? CccsCursor.Empty : CccsCursor.FromBson(state.Cursor);
return state is null ? CccsCursor.Empty : CccsCursor.FromDocument(state.Cursor);
}
private Task UpdateCursorAsync(CccsCursor cursor, CancellationToken cancellationToken)

View File

@@ -70,7 +70,7 @@ internal sealed record CccsCursor(
return doc;
}
public static CccsCursor FromBson(DocumentObject? document)
public static CccsCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -286,8 +286,8 @@ public sealed class CertBundConnector : IFeedConnector
_diagnostics.ParseSuccess(dto.Products.Count, dto.CveIds.Count);
parsedCount++;
var bson = DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "cert-bund.detail.v1", bson, now);
var doc = DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "cert-bund.detail.v1", doc, now);
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
@@ -423,7 +423,7 @@ public sealed class CertBundConnector : IFeedConnector
private async Task<CertBundCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? CertBundCursor.Empty : CertBundCursor.FromBson(state.Cursor);
return state is null ? CertBundCursor.Empty : CertBundCursor.FromDocument(state.Cursor);
}
private Task UpdateCursorAsync(CertBundCursor cursor, CancellationToken cancellationToken)

View File

@@ -53,7 +53,7 @@ internal sealed record CertBundCursor(
return document;
}
public static CertBundCursor FromBson(DocumentObject? document)
public static CertBundCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -672,7 +672,7 @@ public sealed class CertCcConnector : IFeedConnector
private async Task<CertCcCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var record = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return CertCcCursor.FromBson(record?.Cursor);
return CertCcCursor.FromDocument(record?.Cursor);
}
private async Task UpdateCursorAsync(CertCcCursor cursor, CancellationToken cancellationToken)

View File

@@ -43,7 +43,7 @@ internal sealed record CertCcCursor(
return document;
}
public static CertCcCursor FromBson(DocumentObject? document)
public static CertCcCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{
@@ -124,10 +124,10 @@ internal sealed record CertCcCursor(
{
switch (element)
{
case DocumentString bsonString when !string.IsNullOrWhiteSpace(bsonString.AsString):
results.Add(bsonString.AsString.Trim());
case DocumentString docString when !string.IsNullOrWhiteSpace(docString.AsString):
results.Add(docString.AsString.Trim());
break;
case DocumentObject bsonDocument when bsonDocument.TryGetValue("value", out var inner) && inner.IsString:
case DocumentObject docObject when docObject.TryGetValue("value", out var inner) && inner.IsString:
results.Add(inner.AsString.Trim());
break;
}
@@ -144,7 +144,7 @@ internal sealed record CertCcCursor(
private static bool TryReadGuid(DocumentValue value, out Guid guid)
{
if (value is DocumentString bsonString && Guid.TryParse(bsonString.AsString, out guid))
if (value is DocumentString docString && Guid.TryParse(docString.AsString, out guid))
{
return true;
}

View File

@@ -326,7 +326,7 @@ public sealed class CertFrConnector : IFeedConnector
private async Task<CertFrCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var record = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return CertFrCursor.FromBson(record?.Cursor);
return CertFrCursor.FromDocument(record?.Cursor);
}
private async Task UpdateCursorAsync(CertFrCursor cursor, CancellationToken cancellationToken)

View File

@@ -28,7 +28,7 @@ internal sealed record CertFrCursor(
return document;
}
public static CertFrCursor FromBson(DocumentObject? document)
public static CertFrCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -418,7 +418,7 @@ public sealed class CertInConnector : IFeedConnector
private async Task<CertInCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? CertInCursor.Empty : CertInCursor.FromBson(state.Cursor);
return state is null ? CertInCursor.Empty : CertInCursor.FromDocument(state.Cursor);
}
private Task UpdateCursorAsync(CertInCursor cursor, CancellationToken cancellationToken)

View File

@@ -28,7 +28,7 @@ internal sealed record CertInCursor(
return document;
}
public static CertInCursor FromBson(DocumentObject? document)
public static CertInCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -10,7 +10,7 @@ using System.Text;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using StellaOps.Concelier.Documents;
using MongoContracts = StellaOps.Concelier.Storage;
using LegacyContracts = StellaOps.Concelier.Storage;
using StorageContracts = StellaOps.Concelier.Storage.Contracts;
using StellaOps.Concelier.Connector.Common.Http;
using StellaOps.Concelier.Connector.Common.Telemetry;
@@ -32,12 +32,12 @@ public sealed class SourceFetchService
private readonly IHttpClientFactory _httpClientFactory;
private readonly RawDocumentStorage _rawDocumentStorage;
private readonly MongoContracts.IDocumentStore _documentStore;
private readonly LegacyContracts.IDocumentStore _documentStore;
private readonly StorageContracts.IStorageDocumentStore _storageDocumentStore;
private readonly ILogger<SourceFetchService> _logger;
private readonly TimeProvider _timeProvider;
private readonly IOptionsMonitor<SourceHttpClientOptions> _httpClientOptions;
private readonly IOptions<MongoContracts.StorageOptions> _storageOptions;
private readonly IOptions<LegacyContracts.StorageOptions> _storageOptions;
private readonly IJitterSource _jitterSource;
private readonly IAdvisoryRawWriteGuard _guard;
private readonly IAdvisoryLinksetMapper _linksetMapper;
@@ -47,7 +47,7 @@ public sealed class SourceFetchService
public SourceFetchService(
IHttpClientFactory httpClientFactory,
RawDocumentStorage rawDocumentStorage,
MongoContracts.IDocumentStore documentStore,
LegacyContracts.IDocumentStore documentStore,
StorageContracts.IStorageDocumentStore storageDocumentStore,
ILogger<SourceFetchService> logger,
IJitterSource jitterSource,
@@ -56,7 +56,7 @@ public sealed class SourceFetchService
ICryptoHash hash,
TimeProvider? timeProvider = null,
IOptionsMonitor<SourceHttpClientOptions>? httpClientOptions = null,
IOptions<MongoContracts.StorageOptions>? storageOptions = null)
IOptions<LegacyContracts.StorageOptions>? storageOptions = null)
{
_httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
_rawDocumentStorage = rawDocumentStorage ?? throw new ArgumentNullException(nameof(rawDocumentStorage));
@@ -77,7 +77,7 @@ public sealed class SourceFetchService
public SourceFetchService(
IHttpClientFactory httpClientFactory,
RawDocumentStorage rawDocumentStorage,
MongoContracts.IDocumentStore documentStore,
LegacyContracts.IDocumentStore documentStore,
ILogger<SourceFetchService> logger,
IJitterSource jitterSource,
IAdvisoryRawWriteGuard guard,
@@ -85,7 +85,7 @@ public sealed class SourceFetchService
ICryptoHash hash,
TimeProvider? timeProvider = null,
IOptionsMonitor<SourceHttpClientOptions>? httpClientOptions = null,
IOptions<MongoContracts.StorageOptions>? storageOptions = null)
IOptions<LegacyContracts.StorageOptions>? storageOptions = null)
: this(
httpClientFactory,
rawDocumentStorage,

View File

@@ -2,7 +2,7 @@ using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
using StellaOps.Concelier.Documents;
using StellaOps.Concelier.Connector.Common.Fetch;
using MongoContracts = StellaOps.Concelier.Storage;
using LegacyContracts = StellaOps.Concelier.Storage;
using StellaOps.Cryptography;
namespace StellaOps.Concelier.Connector.Common.State;
@@ -12,17 +12,17 @@ namespace StellaOps.Concelier.Connector.Common.State;
/// </summary>
public sealed class SourceStateSeedProcessor
{
private readonly MongoContracts.IDocumentStore _documentStore;
private readonly LegacyContracts.IDocumentStore _documentStore;
private readonly RawDocumentStorage _rawDocumentStorage;
private readonly MongoContracts.ISourceStateRepository _stateRepository;
private readonly LegacyContracts.ISourceStateRepository _stateRepository;
private readonly TimeProvider _timeProvider;
private readonly ILogger<SourceStateSeedProcessor> _logger;
private readonly ICryptoHash _hash;
public SourceStateSeedProcessor(
MongoContracts.IDocumentStore documentStore,
LegacyContracts.IDocumentStore documentStore,
RawDocumentStorage rawDocumentStorage,
MongoContracts.ISourceStateRepository stateRepository,
LegacyContracts.ISourceStateRepository stateRepository,
ICryptoHash hash,
TimeProvider? timeProvider = null,
ILogger<SourceStateSeedProcessor>? logger = null)
@@ -173,7 +173,7 @@ public sealed class SourceStateSeedProcessor
var metadata = CloneDictionary(document.Metadata);
var record = new MongoContracts.DocumentRecord(
var record = new LegacyContracts.DocumentRecord(
recordId,
source,
document.Uri,

View File

@@ -571,7 +571,7 @@ public sealed class CveConnector : IFeedConnector
private async Task<CveCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? CveCursor.Empty : CveCursor.FromBson(state.Cursor);
return state is null ? CveCursor.Empty : CveCursor.FromDocument(state.Cursor);
}
private async Task UpdateCursorAsync(CveCursor cursor, CancellationToken cancellationToken)

View File

@@ -49,7 +49,7 @@ internal sealed record CveCursor(
return document;
}
public static CveCursor FromBson(DocumentObject? document)
public static CveCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -368,7 +368,7 @@ public sealed class DebianConnector : IFeedConnector
continue;
}
var payload = ToBson(dto);
var payload = ToDocument(dto);
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, SchemaVersion, payload, _timeProvider.GetUtcNow());
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
@@ -414,7 +414,7 @@ public sealed class DebianConnector : IFeedConnector
DebianAdvisoryDto dto;
try
{
dto = FromBson(dtoRecord.Payload);
dto = FromDocument(dtoRecord.Payload);
}
catch (Exception ex)
{
@@ -438,7 +438,7 @@ public sealed class DebianConnector : IFeedConnector
private async Task<DebianCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? DebianCursor.Empty : DebianCursor.FromBson(state.Cursor);
return state is null ? DebianCursor.Empty : DebianCursor.FromDocument(state.Cursor);
}
private async Task UpdateCursorAsync(DebianCursor cursor, CancellationToken cancellationToken)
@@ -508,7 +508,7 @@ public sealed class DebianConnector : IFeedConnector
cveList);
}
private static DocumentObject ToBson(DebianAdvisoryDto dto)
private static DocumentObject ToDocument(DebianAdvisoryDto dto)
{
var packages = new DocumentArray();
foreach (var package in dto.Packages)
@@ -575,15 +575,15 @@ public sealed class DebianConnector : IFeedConnector
};
}
private static DebianAdvisoryDto FromBson(DocumentObject document)
private static DebianAdvisoryDto FromDocument(DocumentObject document)
{
var advisoryId = document.GetValue("advisoryId", "").AsString;
var sourcePackage = document.GetValue("sourcePackage", advisoryId).AsString;
var title = document.GetValue("title", advisoryId).AsString;
var description = document.TryGetValue("description", out var desc) ? desc.AsString : null;
var cves = document.TryGetValue("cves", out var cveArray) && cveArray is DocumentArray cvesBson
? cvesBson.OfType<DocumentValue>()
var cves = document.TryGetValue("cves", out var cveArray) && cveArray is DocumentArray cvesArr
? cvesArr.OfType<DocumentValue>()
.Select(static value => value.ToString())
.Where(static s => !string.IsNullOrWhiteSpace(s))
.Select(static s => s!)
@@ -591,9 +591,9 @@ public sealed class DebianConnector : IFeedConnector
: Array.Empty<string>();
var packages = new List<DebianPackageStateDto>();
if (document.TryGetValue("packages", out var packageArray) && packageArray is DocumentArray packagesBson)
if (document.TryGetValue("packages", out var packageArray) && packageArray is DocumentArray packagesArr)
{
foreach (var element in packagesBson.OfType<DocumentObject>())
foreach (var element in packagesArr.OfType<DocumentObject>())
{
packages.Add(new DebianPackageStateDto(
element.GetValue("package", sourcePackage).AsString,
@@ -614,9 +614,9 @@ public sealed class DebianConnector : IFeedConnector
}
var references = new List<DebianReferenceDto>();
if (document.TryGetValue("references", out var referenceArray) && referenceArray is DocumentArray refBson)
if (document.TryGetValue("references", out var referenceArray) && referenceArray is DocumentArray refArr)
{
foreach (var element in refBson.OfType<DocumentObject>())
foreach (var element in refArr.OfType<DocumentObject>())
{
references.Add(new DebianReferenceDto(
element.GetValue("url", "").AsString,

View File

@@ -19,7 +19,7 @@ internal sealed record DebianCursor(
public static DebianCursor Empty { get; } = new(null, EmptyIds, EmptyGuidList, EmptyGuidList, EmptyCache);
public static DebianCursor FromBson(DocumentObject? document)
public static DebianCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{
@@ -168,7 +168,7 @@ internal sealed record DebianCursor(
{
if (element.Value is DocumentObject entry)
{
cache[element.Name] = DebianFetchCacheEntry.FromBson(entry);
cache[element.Name] = DebianFetchCacheEntry.FromDocument(entry);
}
}

View File

@@ -10,7 +10,7 @@ internal sealed record DebianFetchCacheEntry(string? ETag, DateTimeOffset? LastM
public static DebianFetchCacheEntry FromDocument(StellaOps.Concelier.Storage.DocumentRecord document)
=> new(document.Etag, document.LastModified);
public static DebianFetchCacheEntry FromBson(DocumentObject document)
public static DebianFetchCacheEntry FromDocument(DocumentObject document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -19,7 +19,7 @@ internal sealed record SuseCursor(
public static SuseCursor Empty { get; } = new(null, EmptyStringList, EmptyGuidList, EmptyGuidList, EmptyCache);
public static SuseCursor FromBson(DocumentObject? document)
public static SuseCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{
@@ -168,7 +168,7 @@ internal sealed record SuseCursor(
{
if (element.Value is DocumentObject entry)
{
cache[element.Name] = SuseFetchCacheEntry.FromBson(entry);
cache[element.Name] = SuseFetchCacheEntry.FromDocument(entry);
}
}

View File

@@ -1,6 +1,6 @@
using System;
using StellaOps.Concelier.Documents;
using MongoContracts = StellaOps.Concelier.Storage;
using LegacyContracts = StellaOps.Concelier.Storage;
using StorageContracts = StellaOps.Concelier.Storage.Contracts;
namespace StellaOps.Concelier.Connector.Distro.Suse.Internal;
@@ -12,10 +12,10 @@ internal sealed record SuseFetchCacheEntry(string? ETag, DateTimeOffset? LastMod
public static SuseFetchCacheEntry FromDocument(StorageContracts.StorageDocument document)
=> new(document.Etag, document.LastModified);
public static SuseFetchCacheEntry FromDocument(MongoContracts.DocumentRecord document)
public static SuseFetchCacheEntry FromDocument(LegacyContracts.DocumentRecord document)
=> new(document.Etag, document.LastModified);
public static SuseFetchCacheEntry FromBson(DocumentObject document)
public static SuseFetchCacheEntry FromDocument(DocumentObject document)
{
if (document is null || document.ElementCount == 0)
{
@@ -79,7 +79,7 @@ internal sealed record SuseFetchCacheEntry(string? ETag, DateTimeOffset? LastMod
return !LastModified.HasValue && !document.LastModified.HasValue;
}
public bool Matches(MongoContracts.DocumentRecord document)
public bool Matches(LegacyContracts.DocumentRecord document)
{
if (document is null)
{

View File

@@ -343,7 +343,7 @@ public sealed class SuseConnector : IFeedConnector
var updatedDocument = document with { Metadata = metadata };
await _documentStore.UpsertAsync(updatedDocument, cancellationToken).ConfigureAwait(false);
var payload = ToBson(dto);
var payload = ToDocument(dto);
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "suse.csaf.v1", payload, _timeProvider.GetUtcNow());
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
@@ -390,7 +390,7 @@ public sealed class SuseConnector : IFeedConnector
SuseAdvisoryDto dto;
try
{
dto = FromBson(dtoRecord.Payload);
dto = FromDocument(dtoRecord.Payload);
}
catch (Exception ex)
{
@@ -415,7 +415,7 @@ public sealed class SuseConnector : IFeedConnector
private async Task<SuseCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? SuseCursor.Empty : SuseCursor.FromBson(state.Cursor);
return state is null ? SuseCursor.Empty : SuseCursor.FromDocument(state.Cursor);
}
private async Task UpdateCursorAsync(SuseCursor cursor, CancellationToken cancellationToken)
@@ -424,7 +424,7 @@ public sealed class SuseConnector : IFeedConnector
await _stateRepository.UpdateCursorAsync(SourceName, document, _timeProvider.GetUtcNow(), cancellationToken).ConfigureAwait(false);
}
private static DocumentObject ToBson(SuseAdvisoryDto dto)
private static DocumentObject ToDocument(SuseAdvisoryDto dto)
{
var packages = new DocumentArray();
foreach (var package in dto.Packages)
@@ -493,7 +493,7 @@ public sealed class SuseConnector : IFeedConnector
};
}
private static SuseAdvisoryDto FromBson(DocumentObject document)
private static SuseAdvisoryDto FromDocument(DocumentObject document)
{
var advisoryId = document.GetValue("advisoryId", string.Empty).AsString;
var title = document.GetValue("title", advisoryId).AsString;
@@ -507,8 +507,8 @@ public sealed class SuseConnector : IFeedConnector
}
: DateTimeOffset.UtcNow;
var cves = document.TryGetValue("cves", out var cveArray) && cveArray is DocumentArray bsonCves
? bsonCves.OfType<DocumentValue>()
var cves = document.TryGetValue("cves", out var cveArray) && cveArray is DocumentArray cveArr
? cveArr.OfType<DocumentValue>()
.Select(static value => value?.ToString())
.Where(static value => !string.IsNullOrWhiteSpace(value))
.Select(static value => value!)
@@ -517,9 +517,9 @@ public sealed class SuseConnector : IFeedConnector
: Array.Empty<string>();
var packageList = new List<SusePackageStateDto>();
if (document.TryGetValue("packages", out var packageArray) && packageArray is DocumentArray bsonPackages)
if (document.TryGetValue("packages", out var packageArray) && packageArray is DocumentArray packageArr)
{
foreach (var element in bsonPackages.OfType<DocumentObject>())
foreach (var element in packageArr.OfType<DocumentObject>())
{
var package = element.GetValue("package", string.Empty).AsString;
var platform = element.GetValue("platform", string.Empty).AsString;
@@ -544,9 +544,9 @@ public sealed class SuseConnector : IFeedConnector
}
var referenceList = new List<SuseReferenceDto>();
if (document.TryGetValue("references", out var referenceArray) && referenceArray is DocumentArray bsonReferences)
if (document.TryGetValue("references", out var referenceArray) && referenceArray is DocumentArray referenceArr)
{
foreach (var element in bsonReferences.OfType<DocumentObject>())
foreach (var element in referenceArr.OfType<DocumentObject>())
{
var url = element.GetValue("url", string.Empty).AsString;
if (string.IsNullOrWhiteSpace(url))

View File

@@ -19,7 +19,7 @@ internal sealed record UbuntuCursor(
public static UbuntuCursor Empty { get; } = new(null, EmptyIds, EmptyGuidList, EmptyGuidList, EmptyCache);
public static UbuntuCursor FromBson(DocumentObject? document)
public static UbuntuCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{
@@ -168,7 +168,7 @@ internal sealed record UbuntuCursor(
{
if (element.Value is DocumentObject entryDoc)
{
cache[element.Name] = UbuntuFetchCacheEntry.FromBson(entryDoc);
cache[element.Name] = UbuntuFetchCacheEntry.FromDocument(entryDoc);
}
}

View File

@@ -11,7 +11,7 @@ internal sealed record UbuntuFetchCacheEntry(string? ETag, DateTimeOffset? LastM
public static UbuntuFetchCacheEntry FromDocument(StorageContracts.StorageDocument document)
=> new(document.Etag, document.LastModified);
public static UbuntuFetchCacheEntry FromBson(DocumentObject document)
public static UbuntuFetchCacheEntry FromDocument(DocumentObject document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -144,7 +144,7 @@ public sealed class UbuntuConnector : IFeedConnector
["ubuntu.published"] = notice.Published.ToString("O")
};
var dtoDocument = ToBson(notice);
var dtoDocument = ToDocument(notice);
var sha256 = ComputeNoticeHash(dtoDocument);
var documentId = existing?.Id ?? Guid.NewGuid();
@@ -217,7 +217,7 @@ public sealed class UbuntuConnector : IFeedConnector
UbuntuNoticeDto notice;
try
{
notice = FromBson(dto.Payload);
notice = FromDocument(dto.Payload);
}
catch (Exception ex)
{
@@ -409,7 +409,7 @@ public sealed class UbuntuConnector : IFeedConnector
private async Task<UbuntuCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? UbuntuCursor.Empty : UbuntuCursor.FromBson(state.Cursor);
return state is null ? UbuntuCursor.Empty : UbuntuCursor.FromDocument(state.Cursor);
}
private async Task UpdateCursorAsync(UbuntuCursor cursor, CancellationToken cancellationToken)
@@ -420,12 +420,12 @@ public sealed class UbuntuConnector : IFeedConnector
private string ComputeNoticeHash(DocumentObject document)
{
var bytes = document.ToBson();
var bytes = document.ToDocument();
var hash = _hash.ComputeHash(bytes, HashAlgorithms.Sha256);
return Convert.ToHexString(hash).ToLowerInvariant();
}
private static DocumentObject ToBson(UbuntuNoticeDto notice)
private static DocumentObject ToDocument(UbuntuNoticeDto notice)
{
var packages = new DocumentArray();
foreach (var package in notice.Packages)
@@ -473,7 +473,7 @@ public sealed class UbuntuConnector : IFeedConnector
};
}
private static UbuntuNoticeDto FromBson(DocumentObject document)
private static UbuntuNoticeDto FromDocument(DocumentObject document)
{
var noticeId = document.GetValue("noticeId", string.Empty).AsString;
var published = document.TryGetValue("published", out var publishedValue)
@@ -488,8 +488,8 @@ public sealed class UbuntuConnector : IFeedConnector
var title = document.GetValue("title", noticeId).AsString;
var summary = document.GetValue("summary", string.Empty).AsString;
var cves = document.TryGetValue("cves", out var cveArray) && cveArray is DocumentArray cveBson
? cveBson.OfType<DocumentValue>()
var cves = document.TryGetValue("cves", out var cveArray) && cveArray is DocumentArray cveArr
? cveArr.OfType<DocumentValue>()
.Select(static value => value?.ToString())
.Where(static value => !string.IsNullOrWhiteSpace(value))
.Select(static value => value!)
@@ -497,9 +497,9 @@ public sealed class UbuntuConnector : IFeedConnector
: Array.Empty<string>();
var packages = new List<UbuntuReleasePackageDto>();
if (document.TryGetValue("packages", out var packageArray) && packageArray is DocumentArray packageBson)
if (document.TryGetValue("packages", out var packageArray) && packageArray is DocumentArray packageArr)
{
foreach (var element in packageBson.OfType<DocumentObject>())
foreach (var element in packageArr.OfType<DocumentObject>())
{
packages.Add(new UbuntuReleasePackageDto(
Release: element.GetValue("release", string.Empty).AsString,
@@ -511,9 +511,9 @@ public sealed class UbuntuConnector : IFeedConnector
}
var references = new List<UbuntuReferenceDto>();
if (document.TryGetValue("references", out var referenceArray) && referenceArray is DocumentArray referenceBson)
if (document.TryGetValue("references", out var referenceArray) && referenceArray is DocumentArray referenceArr)
{
foreach (var element in referenceBson.OfType<DocumentObject>())
foreach (var element in referenceArr.OfType<DocumentObject>())
{
var url = element.GetValue("url", string.Empty).AsString;
if (string.IsNullOrWhiteSpace(url))

View File

@@ -422,7 +422,7 @@ public sealed class GhsaConnector : IFeedConnector
private async Task<GhsaCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? GhsaCursor.Empty : GhsaCursor.FromBson(state.Cursor);
return state is null ? GhsaCursor.Empty : GhsaCursor.FromDocument(state.Cursor);
}
private async Task UpdateCursorAsync(GhsaCursor cursor, CancellationToken cancellationToken)

View File

@@ -49,7 +49,7 @@ internal sealed record GhsaCursor(
return document;
}
public static GhsaCursor FromBson(DocumentObject? document)
public static GhsaCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -322,13 +322,13 @@ public sealed class IcsCisaConnector : IFeedConnector
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
WriteIndented = false,
});
var bson = DocumentObject.Parse(json);
var doc = DocumentObject.Parse(json);
var dtoRecord = new DtoRecord(
Guid.NewGuid(),
document.Id,
SourceName,
SchemaVersion,
bson,
doc,
_timeProvider.GetUtcNow());
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
@@ -1411,7 +1411,7 @@ public sealed class IcsCisaConnector : IFeedConnector
private async Task<IcsCisaCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? IcsCisaCursor.Empty : IcsCisaCursor.FromBson(state.Cursor);
return state is null ? IcsCisaCursor.Empty : IcsCisaCursor.FromDocument(state.Cursor);
}
private Task UpdateCursorAsync(IcsCisaCursor cursor, CancellationToken cancellationToken)

View File

@@ -28,7 +28,7 @@ internal sealed record IcsCisaCursor(
return document;
}
public static IcsCisaCursor FromBson(DocumentObject? document)
public static IcsCisaCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -59,7 +59,7 @@ internal sealed record KasperskyCursor(
return document;
}
public static KasperskyCursor FromBson(DocumentObject? document)
public static KasperskyCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -442,7 +442,7 @@ public sealed class KasperskyConnector : IFeedConnector
private async Task<KasperskyCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? KasperskyCursor.Empty : KasperskyCursor.FromBson(state.Cursor);
return state is null ? KasperskyCursor.Empty : KasperskyCursor.FromDocument(state.Cursor);
}
private async Task UpdateCursorAsync(KasperskyCursor cursor, CancellationToken cancellationToken)

View File

@@ -36,7 +36,7 @@ internal sealed record JvnCursor(
return document;
}
public static JvnCursor FromBson(DocumentObject? document)
public static JvnCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -314,7 +314,7 @@ public sealed class JvnConnector : IFeedConnector
private async Task<JvnCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? JvnCursor.Empty : JvnCursor.FromBson(state.Cursor);
return state is null ? JvnCursor.Empty : JvnCursor.FromDocument(state.Cursor);
}
private async Task UpdateCursorAsync(JvnCursor cursor, CancellationToken cancellationToken)

View File

@@ -34,7 +34,7 @@ internal sealed record KevCursor(
return document;
}
public static KevCursor FromBson(DocumentObject? document)
public static KevCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -386,7 +386,7 @@ public sealed class KevConnector : IFeedConnector
private async Task<KevCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? KevCursor.Empty : KevCursor.FromBson(state.Cursor);
return state is null ? KevCursor.Empty : KevCursor.FromDocument(state.Cursor);
}
private Task UpdateCursorAsync(KevCursor cursor, CancellationToken cancellationToken)

View File

@@ -54,7 +54,7 @@ internal sealed record KisaCursor(
return document;
}
public static KisaCursor FromBson(DocumentObject? document)
public static KisaCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -287,8 +287,8 @@ public sealed class KisaConnector : IFeedConnector
_diagnostics.ParseSuccess(category);
_logger.LogDebug("KISA parsed detail for {DocumentId} ({Category})", document.Id, category ?? "unknown");
var dtoBson = DocumentObject.Parse(JsonSerializer.Serialize(parsed, SerializerOptions));
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "kisa.detail.v1", dtoBson, now);
var dtoDoc = DocumentObject.Parse(JsonSerializer.Serialize(parsed, SerializerOptions));
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "kisa.detail.v1", dtoDoc, now);
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
@@ -412,7 +412,7 @@ public sealed class KisaConnector : IFeedConnector
private async Task<KisaCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? KisaCursor.Empty : KisaCursor.FromBson(state.Cursor);
return state is null ? KisaCursor.Empty : KisaCursor.FromDocument(state.Cursor);
}
private Task UpdateCursorAsync(KisaCursor cursor, CancellationToken cancellationToken)

View File

@@ -78,7 +78,7 @@ internal sealed record OsvCursor(
return document;
}
public static OsvCursor FromBson(DocumentObject? document)
public static OsvCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -297,7 +297,7 @@ public sealed class OsvConnector : IFeedConnector
private async Task<OsvCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? OsvCursor.Empty : OsvCursor.FromBson(state.Cursor);
return state is null ? OsvCursor.Empty : OsvCursor.FromDocument(state.Cursor);
}
private async Task UpdateCursorAsync(OsvCursor cursor, CancellationToken cancellationToken)

View File

@@ -36,7 +36,7 @@ internal sealed record RuBduCursor(
return document;
}
public static RuBduCursor FromBson(DocumentObject? document)
public static RuBduCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -268,8 +268,8 @@ public sealed class RuBduConnector : IFeedConnector
continue;
}
var bson = StellaOps.Concelier.Documents.DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "ru-bdu.v1", bson, _timeProvider.GetUtcNow());
var doc = StellaOps.Concelier.Documents.DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "ru-bdu.v1", doc, _timeProvider.GetUtcNow());
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
_diagnostics.ParseSuccess(
@@ -520,7 +520,7 @@ public sealed class RuBduConnector : IFeedConnector
private async Task<RuBduCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? RuBduCursor.Empty : RuBduCursor.FromBson(state.Cursor);
return state is null ? RuBduCursor.Empty : RuBduCursor.FromDocument(state.Cursor);
}
private Task UpdateCursorAsync(RuBduCursor cursor, CancellationToken cancellationToken)

View File

@@ -42,7 +42,7 @@ internal sealed record RuNkckiCursor(
return document;
}
public static RuNkckiCursor FromBson(DocumentObject? document)
public static RuNkckiCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -338,8 +338,8 @@ public sealed class RuNkckiConnector : IFeedConnector
continue;
}
var bson = StellaOps.Concelier.Documents.DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "ru-nkcki.v1", bson, _timeProvider.GetUtcNow());
var doc = StellaOps.Concelier.Documents.DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "ru-nkcki.v1", doc, _timeProvider.GetUtcNow());
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
@@ -871,7 +871,7 @@ public sealed class RuNkckiConnector : IFeedConnector
private async Task<RuNkckiCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? RuNkckiCursor.Empty : RuNkckiCursor.FromBson(state.Cursor);
return state is null ? RuNkckiCursor.Empty : RuNkckiCursor.FromDocument(state.Cursor);
}
private Task UpdateCursorAsync(RuNkckiCursor cursor, CancellationToken cancellationToken)

View File

@@ -52,7 +52,7 @@ internal sealed record StellaOpsMirrorCursor(
return document;
}
public static StellaOpsMirrorCursor FromBson(DocumentObject? document)
public static StellaOpsMirrorCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -275,7 +275,7 @@ public sealed class StellaOpsMirrorConnector : IFeedConnector
private async Task<StellaOpsMirrorCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(Source, cancellationToken).ConfigureAwait(false);
return state is null ? StellaOpsMirrorCursor.Empty : StellaOpsMirrorCursor.FromBson(state.Cursor);
return state is null ? StellaOpsMirrorCursor.Empty : StellaOpsMirrorCursor.FromDocument(state.Cursor);
}
private async Task UpdateCursorAsync(StellaOpsMirrorCursor cursor, CancellationToken cancellationToken)
@@ -422,8 +422,8 @@ public sealed class StellaOpsMirrorConnector : IFeedConnector
continue;
}
var dtoBson = DocumentObject.Parse(json);
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, Source, BundleDtoSchemaVersion, dtoBson, now);
var dtoDoc = DocumentObject.Parse(json);
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, Source, BundleDtoSchemaVersion, dtoDoc, now);
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);

View File

@@ -29,7 +29,7 @@ internal sealed record AdobeCursor(
var cacheDocument = new DocumentObject();
foreach (var (key, entry) in FetchCache)
{
cacheDocument[key] = entry.ToBson();
cacheDocument[key] = entry.ToDocument();
}
document["fetchCache"] = cacheDocument;
@@ -138,7 +138,7 @@ internal sealed record AdobeCursor(
{
if (element.Value is DocumentObject entryDocument)
{
dictionary[element.Name] = AdobeFetchCacheEntry.FromBson(entryDocument);
dictionary[element.Name] = AdobeFetchCacheEntry.FromDocument(entryDocument);
}
}
@@ -150,7 +150,7 @@ internal sealed record AdobeFetchCacheEntry(string Sha256)
{
public static AdobeFetchCacheEntry Empty { get; } = new(string.Empty);
public DocumentObject ToBson()
public DocumentObject ToDocument()
{
var document = new DocumentObject
{
@@ -160,7 +160,7 @@ internal sealed record AdobeFetchCacheEntry(string Sha256)
return document;
}
public static AdobeFetchCacheEntry FromBson(DocumentObject document)
public static AdobeFetchCacheEntry FromDocument(DocumentObject document)
{
var sha = document.TryGetValue("sha256", out var shaValue) ? shaValue.AsString : string.Empty;
return new AdobeFetchCacheEntry(sha);

View File

@@ -428,12 +428,12 @@ public sealed class AppleConnector : IFeedConnector
private async Task<AppleCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? AppleCursor.Empty : AppleCursor.FromBson(state.Cursor);
return state is null ? AppleCursor.Empty : AppleCursor.FromDocument(state.Cursor);
}
private async Task UpdateCursorAsync(AppleCursor cursor, CancellationToken cancellationToken)
{
var document = cursor.ToBson();
var document = cursor.ToDocument();
await _stateRepository.UpdateCursorAsync(SourceName, document, _timeProvider.GetUtcNow(), cancellationToken).ConfigureAwait(false);
}
}

View File

@@ -16,7 +16,7 @@ internal sealed record AppleCursor(
public static AppleCursor Empty { get; } = new(null, EmptyStringCollection, EmptyGuidCollection, EmptyGuidCollection);
public DocumentObject ToBson()
public DocumentObject ToDocument()
{
var document = new DocumentObject
{
@@ -37,7 +37,7 @@ internal sealed record AppleCursor(
return document;
}
public static AppleCursor FromBson(DocumentObject? document)
public static AppleCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -28,7 +28,7 @@ internal sealed record ChromiumCursor(
var cacheDocument = new DocumentObject();
foreach (var (key, entry) in FetchCache)
{
cacheDocument[key] = entry.ToBson();
cacheDocument[key] = entry.ToDocument();
}
document["fetchCache"] = cacheDocument;
@@ -113,7 +113,7 @@ internal sealed record ChromiumCursor(
{
if (element.Value is DocumentObject entryDocument)
{
dictionary[element.Name] = ChromiumFetchCacheEntry.FromBson(entryDocument);
dictionary[element.Name] = ChromiumFetchCacheEntry.FromDocument(entryDocument);
}
}
@@ -125,7 +125,7 @@ internal sealed record ChromiumFetchCacheEntry(string Sha256)
{
public static ChromiumFetchCacheEntry Empty { get; } = new(string.Empty);
public DocumentObject ToBson()
public DocumentObject ToDocument()
{
var document = new DocumentObject
{
@@ -135,7 +135,7 @@ internal sealed record ChromiumFetchCacheEntry(string Sha256)
return document;
}
public static ChromiumFetchCacheEntry FromBson(DocumentObject document)
public static ChromiumFetchCacheEntry FromDocument(DocumentObject document)
{
var sha = document.TryGetValue("sha256", out var shaValue) ? shaValue.AsString : string.Empty;
return new ChromiumFetchCacheEntry(sha);

View File

@@ -325,8 +325,8 @@ public sealed class CiscoConnector : IFeedConnector
try
{
var dtoJson = JsonSerializer.Serialize(dto, DtoSerializerOptions);
var dtoBson = DocumentObject.Parse(dtoJson);
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, DtoSchemaVersion, dtoBson, _timeProvider.GetUtcNow());
var dtoDoc = DocumentObject.Parse(dtoJson);
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, DtoSchemaVersion, dtoDoc, _timeProvider.GetUtcNow());
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
pendingDocuments.Remove(documentId);
@@ -577,12 +577,12 @@ public sealed class CiscoConnector : IFeedConnector
private async Task<CiscoCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? CiscoCursor.Empty : CiscoCursor.FromBson(state.Cursor);
return state is null ? CiscoCursor.Empty : CiscoCursor.FromDocument(state.Cursor);
}
private async Task UpdateCursorAsync(CiscoCursor cursor, CancellationToken cancellationToken)
{
var document = cursor.ToBson();
var document = cursor.ToDocument();
await _stateRepository.UpdateCursorAsync(SourceName, document, _timeProvider.GetUtcNow(), cancellationToken).ConfigureAwait(false);
}

View File

@@ -12,7 +12,7 @@ internal sealed record CiscoCursor(
public static CiscoCursor Empty { get; } = new(null, null, EmptyGuidCollection, EmptyGuidCollection);
public DocumentObject ToBson()
public DocumentObject ToDocument()
{
var document = new DocumentObject
{
@@ -33,7 +33,7 @@ internal sealed record CiscoCursor(
return document;
}
public static CiscoCursor FromBson(DocumentObject? document)
public static CiscoCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -39,7 +39,7 @@ internal sealed record MsrcCursor(
return document;
}
public static MsrcCursor FromBson(DocumentObject? document)
public static MsrcCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{

View File

@@ -293,8 +293,8 @@ public sealed class MsrcConnector : IFeedConnector
}
var dto = _detailParser.Parse(detail);
var bson = DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "msrc.detail.v1", bson, now);
var doc = DocumentObject.Parse(JsonSerializer.Serialize(dto, SerializerOptions));
var dtoRecord = new DtoRecord(Guid.NewGuid(), document.Id, SourceName, "msrc.detail.v1", doc, now);
await _dtoStore.UpsertAsync(dtoRecord, cancellationToken).ConfigureAwait(false);
await _documentStore.UpdateStatusAsync(document.Id, DocumentStatuses.PendingMap, cancellationToken).ConfigureAwait(false);
remainingDocuments.Remove(documentId);
@@ -407,7 +407,7 @@ public sealed class MsrcConnector : IFeedConnector
private async Task<MsrcCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? MsrcCursor.Empty : MsrcCursor.FromBson(state.Cursor);
return state is null ? MsrcCursor.Empty : MsrcCursor.FromDocument(state.Cursor);
}
private async Task FetchCvrfAsync(MsrcVulnerabilitySummary summary, DateTimeOffset fetchedAt, CancellationToken cancellationToken)

View File

@@ -45,7 +45,7 @@ internal sealed record OracleCursor(
return document;
}
public static OracleCursor FromBson(DocumentObject? document)
public static OracleCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{
@@ -140,7 +140,7 @@ internal sealed record OracleCursor(
continue;
}
cache[element.Name] = OracleFetchCacheEntry.FromBson(entryDocument);
cache[element.Name] = OracleFetchCacheEntry.FromDocument(entryDocument);
}
return cache;
@@ -171,7 +171,7 @@ internal sealed record OracleFetchCacheEntry(string? Sha256, string? ETag, DateT
return document;
}
public static OracleFetchCacheEntry FromBson(DocumentObject document)
public static OracleFetchCacheEntry FromDocument(DocumentObject document)
{
var sha = document.TryGetValue("sha256", out var shaValue) ? shaValue.ToString() : string.Empty;
string? etag = null;

View File

@@ -314,7 +314,7 @@ public sealed class OracleConnector : IFeedConnector
private async Task<OracleCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var record = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return OracleCursor.FromBson(record?.Cursor);
return OracleCursor.FromDocument(record?.Cursor);
}
private async Task UpdateCursorAsync(OracleCursor cursor, CancellationToken cancellationToken)

View File

@@ -51,7 +51,7 @@ internal sealed record VmwareCursor(
return document;
}
public static VmwareCursor FromBson(DocumentObject? document)
public static VmwareCursor FromDocument(DocumentObject? document)
{
if (document is null || document.ElementCount == 0)
{
@@ -155,7 +155,7 @@ internal sealed record VmwareCursor(
{
if (element.Value is DocumentObject entryDocument)
{
cache[element.Name] = VmwareFetchCacheEntry.FromBson(entryDocument);
cache[element.Name] = VmwareFetchCacheEntry.FromDocument(entryDocument);
}
}

View File

@@ -28,7 +28,7 @@ internal sealed record VmwareFetchCacheEntry(string? Sha256, string? ETag, DateT
return document;
}
public static VmwareFetchCacheEntry FromBson(DocumentObject document)
public static VmwareFetchCacheEntry FromDocument(DocumentObject document)
{
var sha256 = document.TryGetValue("sha256", out var shaValue) ? shaValue.ToString() : string.Empty;
string? etag = null;

View File

@@ -443,7 +443,7 @@ public sealed class VmwareConnector : IFeedConnector
private async Task<VmwareCursor> GetCursorAsync(CancellationToken cancellationToken)
{
var state = await _stateRepository.TryGetAsync(SourceName, cancellationToken).ConfigureAwait(false);
return state is null ? VmwareCursor.Empty : VmwareCursor.FromBson(state.Cursor);
return state is null ? VmwareCursor.Empty : VmwareCursor.FromDocument(state.Cursor);
}
private async Task UpdateCursorAsync(VmwareCursor cursor, CancellationToken cancellationToken)

View File

@@ -28,11 +28,11 @@ public sealed record AdvisoryLinksetNormalized(
public List<string>? CpesToList()
=> Cpes is null ? null : Cpes.ToList();
public List<DocumentObject>? RangesToBson()
=> Ranges is null ? null : Ranges.Select(BsonDocumentHelper.FromDictionary).ToList();
public List<DocumentObject>? RangesToDocuments()
=> Ranges is null ? null : Ranges.Select(DocumentHelper.FromDictionary).ToList();
public List<DocumentObject>? SeveritiesToBson()
=> Severities is null ? null : Severities.Select(BsonDocumentHelper.FromDictionary).ToList();
public List<DocumentObject>? SeveritiesToDocuments()
=> Severities is null ? null : Severities.Select(DocumentHelper.FromDictionary).ToList();
}
public sealed record AdvisoryLinksetProvenance(
@@ -46,7 +46,7 @@ public sealed record AdvisoryLinksetConflict(
IReadOnlyList<string>? Values,
IReadOnlyList<string>? SourceIds = null);
internal static class BsonDocumentHelper
internal static class DocumentHelper
{
public static DocumentObject FromDictionary(Dictionary<string, object?> dictionary)
{

View File

@@ -22,7 +22,7 @@ public sealed record PolicyDeltaCheckpoint(
/// <summary>Last processed advisory ID (tie-breaker when CreatedAt matches).</summary>
string? LastAdvisoryId,
/// <summary>MongoDB change-stream resume token for real-time delta subscriptions.</summary>
/// <summary>Change-stream resume token for real-time delta subscriptions.</summary>
string? ResumeToken,
/// <summary>Sequence number for ordering events within the same timestamp.</summary>

View File

@@ -11,7 +11,7 @@ namespace StellaOps.Concelier.Core.Linksets;
///
/// Read-through behavior:
/// 1. First queries the configured cache (Postgres via IAdvisoryLinksetLookup)
/// 2. On cache miss, rebuilds from MongoDB observations
/// 2. On cache miss, rebuilds from observations
/// 3. Stores rebuilt linksets in cache
/// 4. Returns results
/// </summary>

View File

@@ -3,7 +3,7 @@ namespace StellaOps.Concelier.Core.Observations;
public sealed class AdvisoryObservationEventPublisherOptions
{
public bool Enabled { get; set; } = false;
public string Transport { get; set; } = "mongo"; // mongo|nats
public string Transport { get; set; } = "inmemory"; // inmemory|nats
public string? NatsUrl { get; set; }
public string Subject { get; set; } = "concelier.advisory.observation.updated.v1";
public string DeadLetterSubject { get; set; } = "concelier.advisory.observation.updated.dead.v1";

View File

@@ -4,7 +4,7 @@ namespace StellaOps.Concelier.Core.Orchestration;
/// <summary>
/// In-memory implementation of orchestrator registry store for testing and development.
/// Production deployments should use a persistent store (MongoDB, etc.).
/// Production deployments should use a persistent store (PostgreSQL, etc.).
/// </summary>
public sealed class InMemoryOrchestratorRegistryStore : IOrchestratorRegistryStore
{

View File

@@ -17,7 +17,7 @@ public static class SignalsServiceCollectionExtensions
/// <returns>The service collection for chaining.</returns>
public static IServiceCollection AddConcelierSignalsServices(this IServiceCollection services)
{
// Register affected symbol store (in-memory by default; replace with MongoDB in production)
// Register affected symbol store (in-memory by default; replace with persistent store in production)
services.TryAddSingleton<IAffectedSymbolStore, InMemoryAffectedSymbolStore>();
// Register affected symbol provider

View File

@@ -1,454 +0,0 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v10.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v10.0": {
"StellaOps.Concelier.Core/1.0.0": {
"dependencies": {
"Cronos": "0.10.0",
"Microsoft.Extensions.Hosting.Abstractions": "10.0.0-rc.2.25502.107",
"Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107",
"Microsoft.Extensions.Options": "10.0.0-rc.2.25502.107",
"MongoDB.Driver": "3.5.0",
"SharpCompress": "0.41.0",
"StellaOps.Aoc": "1.0.0",
"StellaOps.Concelier.Models": "1.0.0",
"StellaOps.Concelier.Normalization": "1.0.0",
"StellaOps.Concelier.RawModels": "1.0.0",
"StellaOps.Ingestion.Telemetry": "1.0.0",
"StellaOps.Plugin": "1.0.0",
"StellaOps.Provenance.Mongo": "1.0.0"
},
"runtime": {
"StellaOps.Concelier.Core.dll": {}
}
},
"Cronos/0.10.0": {
"runtime": {
"lib/net6.0/Cronos.dll": {
"assemblyVersion": "0.10.0.0",
"fileVersion": "0.0.0.0"
}
}
},
"DnsClient/1.6.1": {
"runtime": {
"lib/net5.0/DnsClient.dll": {
"assemblyVersion": "1.6.1.0",
"fileVersion": "1.6.1.0"
}
}
},
"Microsoft.Extensions.Configuration.Abstractions/10.0.0-rc.2.25502.107": {
"dependencies": {
"Microsoft.Extensions.Primitives": "10.0.0-rc.2.25502.107"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Configuration.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.25.50307"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.0-rc.2.25502.107": {
"runtime": {
"lib/net10.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.25.50307"
}
}
},
"Microsoft.Extensions.Diagnostics.Abstractions/10.0.0-rc.2.25502.107": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107",
"Microsoft.Extensions.Options": "10.0.0-rc.2.25502.107"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Diagnostics.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.25.50307"
}
}
},
"Microsoft.Extensions.FileProviders.Abstractions/10.0.0-rc.2.25502.107": {
"dependencies": {
"Microsoft.Extensions.Primitives": "10.0.0-rc.2.25502.107"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.FileProviders.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.25.50307"
}
}
},
"Microsoft.Extensions.Hosting.Abstractions/10.0.0-rc.2.25502.107": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.2.25502.107",
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107",
"Microsoft.Extensions.Diagnostics.Abstractions": "10.0.0-rc.2.25502.107",
"Microsoft.Extensions.FileProviders.Abstractions": "10.0.0-rc.2.25502.107",
"Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Hosting.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.25.50307"
}
}
},
"Microsoft.Extensions.Logging.Abstractions/10.0.0-rc.2.25502.107": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Logging.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.25.50307"
}
}
},
"Microsoft.Extensions.Options/10.0.0-rc.2.25502.107": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107",
"Microsoft.Extensions.Primitives": "10.0.0-rc.2.25502.107"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Options.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.25.50307"
}
}
},
"Microsoft.Extensions.Primitives/10.0.0-rc.2.25502.107": {
"runtime": {
"lib/net10.0/Microsoft.Extensions.Primitives.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.25.50307"
}
}
},
"MongoDB.Bson/3.5.0": {
"runtime": {
"lib/net6.0/MongoDB.Bson.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"MongoDB.Driver/3.5.0": {
"dependencies": {
"DnsClient": "1.6.1",
"Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107",
"MongoDB.Bson": "3.5.0",
"SharpCompress": "0.41.0",
"Snappier": "1.0.0",
"ZstdSharp.Port": "0.8.6"
},
"runtime": {
"lib/net6.0/MongoDB.Driver.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"NuGet.Versioning/6.9.1": {
"runtime": {
"lib/netstandard2.0/NuGet.Versioning.dll": {
"assemblyVersion": "6.9.1.3",
"fileVersion": "6.9.1.3"
}
}
},
"SharpCompress/0.41.0": {
"dependencies": {
"ZstdSharp.Port": "0.8.6"
},
"runtime": {
"lib/net8.0/SharpCompress.dll": {
"assemblyVersion": "0.41.0.0",
"fileVersion": "0.41.0.0"
}
}
},
"Snappier/1.0.0": {
"runtime": {
"lib/net5.0/Snappier.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
},
"ZstdSharp.Port/0.8.6": {
"runtime": {
"lib/net9.0/ZstdSharp.dll": {
"assemblyVersion": "0.8.6.0",
"fileVersion": "0.8.6.0"
}
}
},
"StellaOps.Aoc/1.0.0": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107",
"SharpCompress": "0.41.0"
},
"runtime": {
"StellaOps.Aoc.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
},
"StellaOps.Concelier.Models/1.0.0": {
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107",
"SharpCompress": "0.41.0",
"StellaOps.Concelier.RawModels": "1.0.0"
},
"runtime": {
"StellaOps.Concelier.Models.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
},
"StellaOps.Concelier.Normalization/1.0.0": {
"dependencies": {
"NuGet.Versioning": "6.9.1",
"SharpCompress": "0.41.0",
"StellaOps.Concelier.Models": "1.0.0"
},
"runtime": {
"StellaOps.Concelier.Normalization.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
},
"StellaOps.Concelier.RawModels/1.0.0": {
"dependencies": {
"MongoDB.Bson": "3.5.0",
"SharpCompress": "0.41.0"
},
"runtime": {
"StellaOps.Concelier.RawModels.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
},
"StellaOps.DependencyInjection/1.0.0": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.2.25502.107",
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107",
"SharpCompress": "0.41.0"
},
"runtime": {
"StellaOps.DependencyInjection.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
},
"StellaOps.Ingestion.Telemetry/1.0.0": {
"dependencies": {
"SharpCompress": "0.41.0"
},
"runtime": {
"StellaOps.Ingestion.Telemetry.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
},
"StellaOps.Plugin/1.0.0": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "10.0.0-rc.2.25502.107",
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107",
"Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107",
"SharpCompress": "0.41.0",
"StellaOps.DependencyInjection": "1.0.0"
},
"runtime": {
"StellaOps.Plugin.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
},
"StellaOps.Provenance.Mongo/1.0.0": {
"dependencies": {
"MongoDB.Driver": "3.5.0",
"SharpCompress": "0.41.0"
},
"runtime": {
"StellaOps.Provenance.Mongo.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
}
}
},
"libraries": {
"StellaOps.Concelier.Core/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Cronos/0.10.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-wHL4tr8mWTvrJt/4sI3raympCNVT4F3VJI4SJHA9A/wB+8Lsq84RFGQH9bHEtvNsN1lCBTKNk+uVoDotGcYJZA==",
"path": "cronos/0.10.0",
"hashPath": "cronos.0.10.0.nupkg.sha512"
},
"DnsClient/1.6.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-4H/f2uYJOZ+YObZjpY9ABrKZI+JNw3uizp6oMzTXwDw6F+2qIPhpRl/1t68O/6e98+vqNiYGu+lswmwdYUy3gg==",
"path": "dnsclient/1.6.1",
"hashPath": "dnsclient.1.6.1.nupkg.sha512"
},
"Microsoft.Extensions.Configuration.Abstractions/10.0.0-rc.2.25502.107": {
"type": "package",
"serviceable": true,
"sha512": "sha512-H+i/Qy30Rg/K9BcW2Z6DCHPCzwMH3bCwNOjEz31shWTUDK8GeeeMnrKVusprTcRA2Y6yPST+hg2zc3whPEs14Q==",
"path": "microsoft.extensions.configuration.abstractions/10.0.0-rc.2.25502.107",
"hashPath": "microsoft.extensions.configuration.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.0-rc.2.25502.107": {
"type": "package",
"serviceable": true,
"sha512": "sha512-8jujunpkNNfTkE9PFHp9/aD6GPKVfNCuz8tUbzOcyU5tQOCoIZId4hwQNVx3Tb8XEWw9BYdh0k5vPpqdCM+UtA==",
"path": "microsoft.extensions.dependencyinjection.abstractions/10.0.0-rc.2.25502.107",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
},
"Microsoft.Extensions.Diagnostics.Abstractions/10.0.0-rc.2.25502.107": {
"type": "package",
"serviceable": true,
"sha512": "sha512-x6XVv3RiwOlN2unjyX/Zat0gI0HiRoDDdjkwBCwsMftYWpbJu4SiyRwDbrv2zAF8v8nbEEvcWi3/pUxZfaqLQw==",
"path": "microsoft.extensions.diagnostics.abstractions/10.0.0-rc.2.25502.107",
"hashPath": "microsoft.extensions.diagnostics.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
},
"Microsoft.Extensions.FileProviders.Abstractions/10.0.0-rc.2.25502.107": {
"type": "package",
"serviceable": true,
"sha512": "sha512-dOpmW14MkOZIwV6269iXhoMp6alCHBoxqCR4pJ37GLjFaBIyzsIy+Ra8tsGmjHtFvEHKq0JRDIsb1PUkrK+yxw==",
"path": "microsoft.extensions.fileproviders.abstractions/10.0.0-rc.2.25502.107",
"hashPath": "microsoft.extensions.fileproviders.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
},
"Microsoft.Extensions.Hosting.Abstractions/10.0.0-rc.2.25502.107": {
"type": "package",
"serviceable": true,
"sha512": "sha512-M6zqZFbqjdCx8g5Y2XZKTfYfS0gAh4uJkmdAq/ZRDrpIr3Nd+u74allmw15jX1kM61IXM49EnTbhMzlWw5pGVQ==",
"path": "microsoft.extensions.hosting.abstractions/10.0.0-rc.2.25502.107",
"hashPath": "microsoft.extensions.hosting.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
},
"Microsoft.Extensions.Logging.Abstractions/10.0.0-rc.2.25502.107": {
"type": "package",
"serviceable": true,
"sha512": "sha512-SKKKZjyCpBaDQ7yuFjdk6ELnRBRWeZsbnzUfo59Wc4PGhgf92chE3we/QlT6nk6NqlWcUgH/jogM+B/uq/Qdnw==",
"path": "microsoft.extensions.logging.abstractions/10.0.0-rc.2.25502.107",
"hashPath": "microsoft.extensions.logging.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
},
"Microsoft.Extensions.Options/10.0.0-rc.2.25502.107": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Ib6BCCjisp7ZUdhtNpSulFO0ODhz/IE4ZZd8OCqQWoRs363BQ0QOZi9KwpqpiEWo51S0kIXWqNicDPGXwpt9pQ==",
"path": "microsoft.extensions.options/10.0.0-rc.2.25502.107",
"hashPath": "microsoft.extensions.options.10.0.0-rc.2.25502.107.nupkg.sha512"
},
"Microsoft.Extensions.Primitives/10.0.0-rc.2.25502.107": {
"type": "package",
"serviceable": true,
"sha512": "sha512-9pm2zqqn5u/OsKs2zgkhJEQQeMx9KkVOWPdHrs7Kt5sfpk+eIh/gmpi/mMH/ljS2T/PFsFdCEtm+GS/6l7zoZA==",
"path": "microsoft.extensions.primitives/10.0.0-rc.2.25502.107",
"hashPath": "microsoft.extensions.primitives.10.0.0-rc.2.25502.107.nupkg.sha512"
},
"MongoDB.Bson/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-JGNK6BanLDEifgkvPLqVFCPus5EDCy416pxf1dxUBRSVd3D9+NB3AvMVX190eXlk5/UXuCxpsQv7jWfNKvppBQ==",
"path": "mongodb.bson/3.5.0",
"hashPath": "mongodb.bson.3.5.0.nupkg.sha512"
},
"MongoDB.Driver/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ST90u7psyMkNNOWFgSkexsrB3kPn7Ynl2DlMFj2rJyYuc6SIxjmzu4ufy51yzM+cPVE1SvVcdb5UFobrRw6cMg==",
"path": "mongodb.driver/3.5.0",
"hashPath": "mongodb.driver.3.5.0.nupkg.sha512"
},
"NuGet.Versioning/6.9.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ypnSvEtpNGo48bAWn95J1oHChycCXcevFSbn53fqzLxlXFSZP7dawu8p/7mHAfGufZQSV2sBpW80XQGIfXO8kQ==",
"path": "nuget.versioning/6.9.1",
"hashPath": "nuget.versioning.6.9.1.nupkg.sha512"
},
"SharpCompress/0.41.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-z04dBVdTIAFTRKi38f0LkajaKA++bR+M8kYCbasXePILD2H+qs7CkLpyiippB24CSbTrWIgpBKm6BenZqkUwvw==",
"path": "sharpcompress/0.41.0",
"hashPath": "sharpcompress.0.41.0.nupkg.sha512"
},
"Snappier/1.0.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-rFtK2KEI9hIe8gtx3a0YDXdHOpedIf9wYCEYtBEmtlyiWVX3XlCNV03JrmmAi/Cdfn7dxK+k0sjjcLv4fpHnqA==",
"path": "snappier/1.0.0",
"hashPath": "snappier.1.0.0.nupkg.sha512"
},
"ZstdSharp.Port/0.8.6": {
"type": "package",
"serviceable": true,
"sha512": "sha512-iP4jVLQoQmUjMU88g1WObiNr6YKZGvh4aOXn3yOJsHqZsflwRsxZPcIBvNXgjXO3vQKSLctXGLTpcBPLnWPS8A==",
"path": "zstdsharp.port/0.8.6",
"hashPath": "zstdsharp.port.0.8.6.nupkg.sha512"
},
"StellaOps.Aoc/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"StellaOps.Concelier.Models/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"StellaOps.Concelier.Normalization/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"StellaOps.Concelier.RawModels/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"StellaOps.DependencyInjection/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"StellaOps.Ingestion.Telemetry/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"StellaOps.Plugin/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"StellaOps.Provenance.Mongo/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

View File

@@ -289,7 +289,7 @@ namespace StellaOps.Concelier.Documents
return JsonSerializer.Serialize(ordered, options);
}
public byte[] ToBson() => Encoding.UTF8.GetBytes(ToJson());
public byte[] ToDocument() => Encoding.UTF8.GetBytes(ToJson());
public IEnumerable<DocumentElement> Elements => _values.Select(static kvp => new DocumentElement(kvp.Key, kvp.Value ?? new DocumentValue()));
@@ -349,7 +349,7 @@ namespace StellaOps.Concelier.Documents
return value switch
{
null => new DocumentValue(null),
DocumentValue bson => bson,
DocumentValue dv => dv,
string s => new DocumentValue(s),
Guid g => new DocumentValue(g),
int i => new DocumentValue(i),

View File

@@ -5,17 +5,17 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
namespace StellaOps.Concelier.Storage;
/// <summary>
/// Lightweight compatibility bootstrapper to satisfy legacy Mongo wiring during Postgres migration.
/// Registers in-memory stores only; no MongoDB driver/runtime required.
/// Lightweight compatibility bootstrapper to satisfy legacy wiring during Postgres migration.
/// Registers in-memory stores only; no storage driver/runtime required.
/// </summary>
public sealed class MongoBootstrapper
public sealed class StorageBootstrapper
{
public Task InitializeAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
public static class MongoServiceCollectionExtensions
public static class LegacyServiceCollectionExtensions
{
public static IServiceCollection AddMongoStorage(this IServiceCollection services, Action<StorageOptions>? configure = null)
public static IServiceCollection AddInMemoryStorage(this IServiceCollection services, Action<StorageOptions>? configure = null)
{
var options = new StorageOptions();
configure?.Invoke(options);
@@ -31,7 +31,7 @@ public static class MongoServiceCollectionExtensions
services.TryAddSingleton<MergeEvents.IMergeEventStore, MergeEvents.InMemoryMergeEventStore>();
services.TryAddSingleton<PsirtFlags.IPsirtFlagStore, PsirtFlags.InMemoryPsirtFlagStore>();
services.TryAddSingleton<MongoBootstrapper>();
services.TryAddSingleton<StorageBootstrapper>();
return services;
}
}

View File

@@ -19,32 +19,32 @@ namespace StellaOps.Concelier.InMemoryDriver
public class InMemoryClientSettings
{
public static InMemoryClientSettings FromUrl(MongoUrl url) => new();
public static InMemoryClientSettings FromUrl(StorageUrl url) => new();
public string? ApplicationName { get; set; }
}
public class MongoUrl
public class StorageUrl
{
public MongoUrl(string url) => Url = url;
public StorageUrl(string url) => Url = url;
public string Url { get; }
public string DatabaseName => "default";
}
public interface IMongoClient
public interface IStorageClient
{
IMongoDatabase GetDatabase(string name, MongoDatabaseSettings? settings = null);
IStorageDatabase GetDatabase(string name, StorageDatabaseSettings? settings = null);
Task DropDatabaseAsync(string name, CancellationToken cancellationToken = default);
}
public class InMemoryClient : IMongoClient
public class InMemoryClient : IStorageClient
{
public InMemoryClient(string connectionString) { }
public InMemoryClient(InMemoryClientSettings settings) { }
public IMongoDatabase GetDatabase(string name, MongoDatabaseSettings? settings = null) => new MongoDatabase(name);
public IStorageDatabase GetDatabase(string name, StorageDatabaseSettings? settings = null) => new StorageDatabase(name);
public Task DropDatabaseAsync(string name, CancellationToken cancellationToken = default) => Task.CompletedTask;
}
public class MongoDatabaseSettings { }
public class StorageDatabaseSettings { }
public sealed class DatabaseNamespace
{
@@ -52,9 +52,9 @@ namespace StellaOps.Concelier.InMemoryDriver
public string DatabaseName { get; }
}
public interface IMongoDatabase
public interface IStorageDatabase
{
IMongoCollection<TDocument> GetCollection<TDocument>(string name, MongoCollectionSettings? settings = null);
IStorageCollection<TDocument> GetCollection<TDocument>(string name, StorageCollectionSettings? settings = null);
DatabaseNamespace DatabaseNamespace { get; }
Task DropCollectionAsync(string name, CancellationToken cancellationToken = default);
DocumentObject RunCommand(DocumentObject command, CancellationToken cancellationToken = default);
@@ -65,20 +65,20 @@ namespace StellaOps.Concelier.InMemoryDriver
Task<T> RunCommandAsync<T>(string command, CancellationToken cancellationToken = default);
}
public class MongoDatabase : IMongoDatabase
public class StorageDatabase : IStorageDatabase
{
private readonly ConcurrentDictionary<string, object> _collections = new(StringComparer.Ordinal);
public MongoDatabase(string name)
public StorageDatabase(string name)
{
Name = name;
DatabaseNamespace = new DatabaseNamespace(name);
}
public string Name { get; }
public DatabaseNamespace DatabaseNamespace { get; }
public IMongoCollection<TDocument> GetCollection<TDocument>(string name, MongoCollectionSettings? settings = null)
public IStorageCollection<TDocument> GetCollection<TDocument>(string name, StorageCollectionSettings? settings = null)
{
var collection = (MongoCollection<TDocument>)_collections.GetOrAdd(name, _ => new MongoCollection<TDocument>(name));
var collection = (StorageCollection<TDocument>)_collections.GetOrAdd(name, _ => new StorageCollection<TDocument>(name));
return collection;
}
@@ -95,9 +95,9 @@ namespace StellaOps.Concelier.InMemoryDriver
public Task<T> RunCommandAsync<T>(string command, CancellationToken cancellationToken = default) => Task.FromResult(default(T)!);
}
public class MongoCollectionSettings { }
public class StorageCollectionSettings { }
public interface IMongoCollection<TDocument>
public interface IStorageCollection<TDocument>
{
Task InsertOneAsync(TDocument document, InsertOneOptions? options = null, CancellationToken cancellationToken = default);
Task InsertManyAsync(IEnumerable<TDocument> documents, InsertManyOptions? options = null, CancellationToken cancellationToken = default);
@@ -109,21 +109,21 @@ namespace StellaOps.Concelier.InMemoryDriver
Task<long> CountDocumentsAsync(FilterDefinition<TDocument> filter, CountOptions? options = null, CancellationToken cancellationToken = default);
Task<TProjection?> FindOneAndReplaceAsync<TProjection>(FilterDefinition<TDocument> filter, TDocument replacement, FindOneAndReplaceOptions<TDocument, TProjection>? options = null, CancellationToken cancellationToken = default);
Task<TProjection?> FindOneAndUpdateAsync<TProjection>(FilterDefinition<TDocument> filter, UpdateDefinition<TDocument> update, FindOneAndUpdateOptions<TDocument, TProjection>? options = null, CancellationToken cancellationToken = default);
IMongoIndexManager<TDocument> Indexes { get; }
IStorageIndexManager<TDocument> Indexes { get; }
}
public class MongoCollection<TDocument> : IMongoCollection<TDocument>
public class StorageCollection<TDocument> : IStorageCollection<TDocument>
{
private readonly List<TDocument> _docs = new();
public MongoCollection(string name)
public StorageCollection(string name)
{
Name = name;
Indexes = new MongoIndexManager<TDocument>();
Indexes = new StorageIndexManager<TDocument>();
}
public string Name { get; }
public IMongoIndexManager<TDocument> Indexes { get; }
public IStorageIndexManager<TDocument> Indexes { get; }
public Task InsertOneAsync(TDocument document, InsertOneOptions? options = null, CancellationToken cancellationToken = default)
{
@@ -177,12 +177,12 @@ namespace StellaOps.Concelier.InMemoryDriver
=> Task.FromResult(default(TProjection));
}
public interface IMongoIndexManager<TDocument>
public interface IStorageIndexManager<TDocument>
{
Task<string> CreateOneAsync(IndexKeysDefinition<TDocument> keys, CreateIndexOptions? options = null, CancellationToken cancellationToken = default);
}
public sealed class MongoIndexManager<TDocument> : IMongoIndexManager<TDocument>
public sealed class StorageIndexManager<TDocument> : IStorageIndexManager<TDocument>
{
public Task<string> CreateOneAsync(IndexKeysDefinition<TDocument> keys, CreateIndexOptions? options = null, CancellationToken cancellationToken = default)
=> Task.FromResult("stub-index");
@@ -332,7 +332,7 @@ namespace StellaOps.Concelier.InMemoryDriver
namespace StellaOps.Concelier.InMemoryDriver.Linq
{
public interface IMongoQueryable<out T> : IQueryable<T> { }
public interface IStorageQueryable<out T> : IQueryable<T> { }
}
namespace StellaOps.Concelier.InMemoryRunner

View File

@@ -6,7 +6,7 @@ using StellaOps.Concelier.Models;
namespace StellaOps.Concelier.Storage
{
public static class MongoStorageDefaults
public static class StorageDefaults
{
public const string DefaultDatabaseName = "concelier";
@@ -349,35 +349,6 @@ public sealed record SourceStateRecord(
return Task.CompletedTask;
}
}
public class InMemorySourceStateRepository : ISourceStateRepository
{
private readonly InMemorySourceStateRepository _inner = new();
public InMemorySourceStateRepository()
{
}
public InMemorySourceStateRepository(object? database, StorageOptions? options)
{
}
public InMemorySourceStateRepository(object? database, object? logger)
{
}
public Task<SourceStateRecord?> TryGetAsync(string sourceName, CancellationToken cancellationToken)
=> _inner.TryGetAsync(sourceName, cancellationToken);
public Task UpdateCursorAsync(string sourceName, StellaOps.Concelier.Documents.DocumentObject cursor, DateTimeOffset completedAt, CancellationToken cancellationToken)
=> _inner.UpdateCursorAsync(sourceName, cursor, completedAt, cancellationToken);
public Task MarkFailureAsync(string sourceName, DateTimeOffset now, TimeSpan backoff, string reason, CancellationToken cancellationToken)
=> _inner.MarkFailureAsync(sourceName, now, backoff, reason, cancellationToken);
public Task UpsertAsync(SourceStateRecord record, CancellationToken cancellationToken)
=> _inner.UpsertAsync(record, cancellationToken);
}
}
namespace StellaOps.Concelier.Storage.Advisories

View File

@@ -5,7 +5,7 @@ using System.Text.Json;
namespace StellaOps.Concelier.Storage.Contracts;
/// <summary>
/// Postgres-native storage document contract (Mongo-free).
/// Postgres-native storage document contract.
/// </summary>
public sealed record StorageDocument(
Guid Id,
@@ -53,7 +53,7 @@ public interface IStorageDtoStore
}
/// <summary>
/// Cursor/state contract for ingestion sources without Mongo/Bson dependencies.
/// Cursor/state contract for ingestion sources.
/// </summary>
public sealed record SourceCursorState(
string SourceName,

View File

@@ -1,126 +0,0 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v10.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v10.0": {
"StellaOps.Concelier.Models/1.0.0": {
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107",
"SharpCompress": "0.41.0",
"StellaOps.Concelier.RawModels": "1.0.0"
},
"runtime": {
"StellaOps.Concelier.Models.dll": {}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.0-rc.2.25502.107": {
"runtime": {
"lib/net10.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.25.50307"
}
}
},
"Microsoft.Extensions.Logging.Abstractions/10.0.0-rc.2.25502.107": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Logging.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.25.50307"
}
}
},
"MongoDB.Bson/3.5.0": {
"runtime": {
"lib/net6.0/MongoDB.Bson.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"SharpCompress/0.41.0": {
"dependencies": {
"ZstdSharp.Port": "0.8.6"
},
"runtime": {
"lib/net8.0/SharpCompress.dll": {
"assemblyVersion": "0.41.0.0",
"fileVersion": "0.41.0.0"
}
}
},
"ZstdSharp.Port/0.8.6": {
"runtime": {
"lib/net9.0/ZstdSharp.dll": {
"assemblyVersion": "0.8.6.0",
"fileVersion": "0.8.6.0"
}
}
},
"StellaOps.Concelier.RawModels/1.0.0": {
"dependencies": {
"MongoDB.Bson": "3.5.0",
"SharpCompress": "0.41.0"
},
"runtime": {
"StellaOps.Concelier.RawModels.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
}
}
},
"libraries": {
"StellaOps.Concelier.Models/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.0-rc.2.25502.107": {
"type": "package",
"serviceable": true,
"sha512": "sha512-8jujunpkNNfTkE9PFHp9/aD6GPKVfNCuz8tUbzOcyU5tQOCoIZId4hwQNVx3Tb8XEWw9BYdh0k5vPpqdCM+UtA==",
"path": "microsoft.extensions.dependencyinjection.abstractions/10.0.0-rc.2.25502.107",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
},
"Microsoft.Extensions.Logging.Abstractions/10.0.0-rc.2.25502.107": {
"type": "package",
"serviceable": true,
"sha512": "sha512-SKKKZjyCpBaDQ7yuFjdk6ELnRBRWeZsbnzUfo59Wc4PGhgf92chE3we/QlT6nk6NqlWcUgH/jogM+B/uq/Qdnw==",
"path": "microsoft.extensions.logging.abstractions/10.0.0-rc.2.25502.107",
"hashPath": "microsoft.extensions.logging.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
},
"MongoDB.Bson/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-JGNK6BanLDEifgkvPLqVFCPus5EDCy416pxf1dxUBRSVd3D9+NB3AvMVX190eXlk5/UXuCxpsQv7jWfNKvppBQ==",
"path": "mongodb.bson/3.5.0",
"hashPath": "mongodb.bson.3.5.0.nupkg.sha512"
},
"SharpCompress/0.41.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-z04dBVdTIAFTRKi38f0LkajaKA++bR+M8kYCbasXePILD2H+qs7CkLpyiippB24CSbTrWIgpBKm6BenZqkUwvw==",
"path": "sharpcompress/0.41.0",
"hashPath": "sharpcompress.0.41.0.nupkg.sha512"
},
"ZstdSharp.Port/0.8.6": {
"type": "package",
"serviceable": true,
"sha512": "sha512-iP4jVLQoQmUjMU88g1WObiNr6YKZGvh4aOXn3yOJsHqZsflwRsxZPcIBvNXgjXO3vQKSLctXGLTpcBPLnWPS8A==",
"path": "zstdsharp.port/0.8.6",
"hashPath": "zstdsharp.port.0.8.6.nupkg.sha512"
},
"StellaOps.Concelier.RawModels/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

View File

@@ -1,159 +0,0 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v10.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v10.0": {
"StellaOps.Concelier.Normalization/1.0.0": {
"dependencies": {
"NuGet.Versioning": "6.9.1",
"SharpCompress": "0.41.0",
"StellaOps.Concelier.Models": "1.0.0"
},
"runtime": {
"StellaOps.Concelier.Normalization.dll": {}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.0-rc.2.25502.107": {
"runtime": {
"lib/net10.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.25.50307"
}
}
},
"Microsoft.Extensions.Logging.Abstractions/10.0.0-rc.2.25502.107": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.0-rc.2.25502.107"
},
"runtime": {
"lib/net10.0/Microsoft.Extensions.Logging.Abstractions.dll": {
"assemblyVersion": "10.0.0.0",
"fileVersion": "10.0.25.50307"
}
}
},
"MongoDB.Bson/3.5.0": {
"runtime": {
"lib/net6.0/MongoDB.Bson.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"NuGet.Versioning/6.9.1": {
"runtime": {
"lib/netstandard2.0/NuGet.Versioning.dll": {
"assemblyVersion": "6.9.1.3",
"fileVersion": "6.9.1.3"
}
}
},
"SharpCompress/0.41.0": {
"dependencies": {
"ZstdSharp.Port": "0.8.6"
},
"runtime": {
"lib/net8.0/SharpCompress.dll": {
"assemblyVersion": "0.41.0.0",
"fileVersion": "0.41.0.0"
}
}
},
"ZstdSharp.Port/0.8.6": {
"runtime": {
"lib/net9.0/ZstdSharp.dll": {
"assemblyVersion": "0.8.6.0",
"fileVersion": "0.8.6.0"
}
}
},
"StellaOps.Concelier.Models/1.0.0": {
"dependencies": {
"Microsoft.Extensions.Logging.Abstractions": "10.0.0-rc.2.25502.107",
"SharpCompress": "0.41.0",
"StellaOps.Concelier.RawModels": "1.0.0"
},
"runtime": {
"StellaOps.Concelier.Models.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
},
"StellaOps.Concelier.RawModels/1.0.0": {
"dependencies": {
"MongoDB.Bson": "3.5.0",
"SharpCompress": "0.41.0"
},
"runtime": {
"StellaOps.Concelier.RawModels.dll": {
"assemblyVersion": "1.0.0.0",
"fileVersion": "1.0.0.0"
}
}
}
}
},
"libraries": {
"StellaOps.Concelier.Normalization/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"Microsoft.Extensions.DependencyInjection.Abstractions/10.0.0-rc.2.25502.107": {
"type": "package",
"serviceable": true,
"sha512": "sha512-8jujunpkNNfTkE9PFHp9/aD6GPKVfNCuz8tUbzOcyU5tQOCoIZId4hwQNVx3Tb8XEWw9BYdh0k5vPpqdCM+UtA==",
"path": "microsoft.extensions.dependencyinjection.abstractions/10.0.0-rc.2.25502.107",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
},
"Microsoft.Extensions.Logging.Abstractions/10.0.0-rc.2.25502.107": {
"type": "package",
"serviceable": true,
"sha512": "sha512-SKKKZjyCpBaDQ7yuFjdk6ELnRBRWeZsbnzUfo59Wc4PGhgf92chE3we/QlT6nk6NqlWcUgH/jogM+B/uq/Qdnw==",
"path": "microsoft.extensions.logging.abstractions/10.0.0-rc.2.25502.107",
"hashPath": "microsoft.extensions.logging.abstractions.10.0.0-rc.2.25502.107.nupkg.sha512"
},
"MongoDB.Bson/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-JGNK6BanLDEifgkvPLqVFCPus5EDCy416pxf1dxUBRSVd3D9+NB3AvMVX190eXlk5/UXuCxpsQv7jWfNKvppBQ==",
"path": "mongodb.bson/3.5.0",
"hashPath": "mongodb.bson.3.5.0.nupkg.sha512"
},
"NuGet.Versioning/6.9.1": {
"type": "package",
"serviceable": true,
"sha512": "sha512-ypnSvEtpNGo48bAWn95J1oHChycCXcevFSbn53fqzLxlXFSZP7dawu8p/7mHAfGufZQSV2sBpW80XQGIfXO8kQ==",
"path": "nuget.versioning/6.9.1",
"hashPath": "nuget.versioning.6.9.1.nupkg.sha512"
},
"SharpCompress/0.41.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-z04dBVdTIAFTRKi38f0LkajaKA++bR+M8kYCbasXePILD2H+qs7CkLpyiippB24CSbTrWIgpBKm6BenZqkUwvw==",
"path": "sharpcompress/0.41.0",
"hashPath": "sharpcompress.0.41.0.nupkg.sha512"
},
"ZstdSharp.Port/0.8.6": {
"type": "package",
"serviceable": true,
"sha512": "sha512-iP4jVLQoQmUjMU88g1WObiNr6YKZGvh4aOXn3yOJsHqZsflwRsxZPcIBvNXgjXO3vQKSLctXGLTpcBPLnWPS8A==",
"path": "zstdsharp.port/0.8.6",
"hashPath": "zstdsharp.port.0.8.6.nupkg.sha512"
},
"StellaOps.Concelier.Models/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"StellaOps.Concelier.RawModels/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
}
}
}

View File

@@ -1,75 +0,0 @@
{
"runtimeTarget": {
"name": ".NETCoreApp,Version=v10.0",
"signature": ""
},
"compilationOptions": {},
"targets": {
".NETCoreApp,Version=v10.0": {
"StellaOps.Concelier.RawModels/1.0.0": {
"dependencies": {
"MongoDB.Bson": "3.5.0",
"SharpCompress": "0.41.0"
},
"runtime": {
"StellaOps.Concelier.RawModels.dll": {}
}
},
"MongoDB.Bson/3.5.0": {
"runtime": {
"lib/net6.0/MongoDB.Bson.dll": {
"assemblyVersion": "3.5.0.0",
"fileVersion": "3.5.0.0"
}
}
},
"SharpCompress/0.41.0": {
"dependencies": {
"ZstdSharp.Port": "0.8.6"
},
"runtime": {
"lib/net8.0/SharpCompress.dll": {
"assemblyVersion": "0.41.0.0",
"fileVersion": "0.41.0.0"
}
}
},
"ZstdSharp.Port/0.8.6": {
"runtime": {
"lib/net9.0/ZstdSharp.dll": {
"assemblyVersion": "0.8.6.0",
"fileVersion": "0.8.6.0"
}
}
}
}
},
"libraries": {
"StellaOps.Concelier.RawModels/1.0.0": {
"type": "project",
"serviceable": false,
"sha512": ""
},
"MongoDB.Bson/3.5.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-JGNK6BanLDEifgkvPLqVFCPus5EDCy416pxf1dxUBRSVd3D9+NB3AvMVX190eXlk5/UXuCxpsQv7jWfNKvppBQ==",
"path": "mongodb.bson/3.5.0",
"hashPath": "mongodb.bson.3.5.0.nupkg.sha512"
},
"SharpCompress/0.41.0": {
"type": "package",
"serviceable": true,
"sha512": "sha512-z04dBVdTIAFTRKi38f0LkajaKA++bR+M8kYCbasXePILD2H+qs7CkLpyiippB24CSbTrWIgpBKm6BenZqkUwvw==",
"path": "sharpcompress/0.41.0",
"hashPath": "sharpcompress.0.41.0.nupkg.sha512"
},
"ZstdSharp.Port/0.8.6": {
"type": "package",
"serviceable": true,
"sha512": "sha512-iP4jVLQoQmUjMU88g1WObiNr6YKZGvh4aOXn3yOJsHqZsflwRsxZPcIBvNXgjXO3vQKSLctXGLTpcBPLnWPS8A==",
"path": "zstdsharp.port/0.8.6",
"hashPath": "zstdsharp.port.0.8.6.nupkg.sha512"
}
}
}

View File

@@ -4,7 +4,7 @@ namespace StellaOps.Concelier.Storage.Postgres.Advisories;
/// <summary>
/// PostgreSQL advisory storage interface.
/// This interface mirrors the MongoDB IAdvisoryStore but without MongoDB-specific parameters.
/// This interface mirrors the IAdvisoryStore contract but without legacy-specific parameters.
/// </summary>
/// <remarks>
/// Used by connectors when configured to write to PostgreSQL storage.

View File

@@ -3,7 +3,7 @@ using System.Text.Json;
using Microsoft.Extensions.Logging;
using StellaOps.Concelier.Models;
using StellaOps.Concelier.Storage.Postgres.Conversion;
using MongoContracts = StellaOps.Concelier.Storage.Advisories;
using AdvisoryContracts = StellaOps.Concelier.Storage.Advisories;
using StellaOps.Concelier.Storage.Postgres.Models;
using StellaOps.Concelier.Storage.Postgres.Repositories;
@@ -17,7 +17,7 @@ namespace StellaOps.Concelier.Storage.Postgres.Advisories;
/// <remarks>
/// Tasks: PG-T5b.2.1, PG-T5b.2.2, PG-T5b.2.3 - Enables importers to write to PostgreSQL.
/// </remarks>
public sealed class PostgresAdvisoryStore : IPostgresAdvisoryStore, MongoContracts.IAdvisoryStore
public sealed class PostgresAdvisoryStore : IPostgresAdvisoryStore, AdvisoryContracts.IAdvisoryStore
{
private readonly IAdvisoryRepository _advisoryRepository;
private readonly IAdvisoryAliasRepository _aliasRepository;
@@ -87,8 +87,8 @@ public sealed class PostgresAdvisoryStore : IPostgresAdvisoryStore, MongoContrac
result.TotalChildEntities);
}
/// <inheritdoc cref="MongoContracts.IAdvisoryStore.UpsertAsync" />
Task MongoContracts.IAdvisoryStore.UpsertAsync(Advisory advisory, CancellationToken cancellationToken)
/// <inheritdoc cref="AdvisoryContracts.IAdvisoryStore.UpsertAsync" />
Task AdvisoryContracts.IAdvisoryStore.UpsertAsync(Advisory advisory, CancellationToken cancellationToken)
=> UpsertAsync(advisory, sourceId: null, cancellationToken);
/// <inheritdoc />
@@ -106,7 +106,7 @@ public sealed class PostgresAdvisoryStore : IPostgresAdvisoryStore, MongoContrac
}
/// <inheritdoc />
Task<Advisory?> MongoContracts.IAdvisoryStore.FindAsync(string advisoryKey, CancellationToken cancellationToken)
Task<Advisory?> AdvisoryContracts.IAdvisoryStore.FindAsync(string advisoryKey, CancellationToken cancellationToken)
=> FindAsync(advisoryKey, cancellationToken);
/// <inheritdoc />
@@ -128,7 +128,7 @@ public sealed class PostgresAdvisoryStore : IPostgresAdvisoryStore, MongoContrac
}
/// <inheritdoc />
Task<IReadOnlyList<Advisory>> MongoContracts.IAdvisoryStore.GetRecentAsync(int limit, CancellationToken cancellationToken)
Task<IReadOnlyList<Advisory>> AdvisoryContracts.IAdvisoryStore.GetRecentAsync(int limit, CancellationToken cancellationToken)
=> GetRecentAsync(limit, cancellationToken);
/// <inheritdoc />
@@ -167,7 +167,7 @@ public sealed class PostgresAdvisoryStore : IPostgresAdvisoryStore, MongoContrac
}
/// <inheritdoc />
IAsyncEnumerable<Advisory> MongoContracts.IAdvisoryStore.StreamAsync(CancellationToken cancellationToken)
IAsyncEnumerable<Advisory> AdvisoryContracts.IAdvisoryStore.StreamAsync(CancellationToken cancellationToken)
=> StreamAsync(cancellationToken);
/// <inheritdoc />

View File

@@ -3,7 +3,7 @@ using System.Text.Json;
using StellaOps.Concelier.Documents;
using StellaOps.Concelier.Documents.IO;
using Contracts = StellaOps.Concelier.Storage.Contracts;
using MongoContracts = StellaOps.Concelier.Storage;
using LegacyContracts = StellaOps.Concelier.Storage;
namespace StellaOps.Concelier.Storage.Postgres;
@@ -14,7 +14,7 @@ internal static class ContractsMappingExtensions
OutputMode = JsonOutputMode.RelaxedExtendedJson
};
internal static Contracts.StorageDocument ToStorageDocument(this MongoContracts.DocumentRecord record)
internal static Contracts.StorageDocument ToStorageDocument(this LegacyContracts.DocumentRecord record)
{
return new Contracts.StorageDocument(
record.Id,
@@ -34,9 +34,9 @@ internal static class ContractsMappingExtensions
record.FetchedAt);
}
internal static MongoContracts.DocumentRecord ToMongoDocumentRecord(this Contracts.StorageDocument record)
internal static LegacyContracts.DocumentRecord ToLegacyDocumentRecord(this Contracts.StorageDocument record)
{
return new MongoContracts.DocumentRecord(
return new LegacyContracts.DocumentRecord(
record.Id,
record.SourceName,
record.Uri,
@@ -54,7 +54,7 @@ internal static class ContractsMappingExtensions
record.FetchedAt);
}
internal static Contracts.StorageDto ToStorageDto(this MongoContracts.DtoRecord record)
internal static Contracts.StorageDto ToStorageDto(this LegacyContracts.DtoRecord record)
{
var json = record.Payload.ToJson(RelaxedJsonSettings);
var payload = JsonDocument.Parse(json);
@@ -69,22 +69,22 @@ internal static class ContractsMappingExtensions
record.ValidatedAt);
}
internal static MongoContracts.DtoRecord ToMongoDtoRecord(this Contracts.StorageDto record)
internal static LegacyContracts.DtoRecord ToLegacyDtoRecord(this Contracts.StorageDto record)
{
var json = record.Payload.RootElement.GetRawText();
var bson = DocumentObject.Parse(json);
return new MongoContracts.DtoRecord(
var doc = DocumentObject.Parse(json);
return new LegacyContracts.DtoRecord(
record.Id,
record.DocumentId,
record.SourceName,
record.Format,
bson,
doc,
record.CreatedAt,
record.SchemaVersion,
record.ValidatedAt);
}
internal static Contracts.SourceCursorState ToStorageCursorState(this MongoContracts.SourceStateRecord record)
internal static Contracts.SourceCursorState ToStorageCursorState(this LegacyContracts.SourceStateRecord record)
{
var cursorJson = record.Cursor is null ? null : record.Cursor.ToJson(RelaxedJsonSettings);
var cursor = cursorJson is null ? null : JsonDocument.Parse(cursorJson);
@@ -101,14 +101,14 @@ internal static class ContractsMappingExtensions
record.LastFailureReason);
}
internal static MongoContracts.SourceStateRecord ToMongoSourceStateRecord(this Contracts.SourceCursorState record)
internal static LegacyContracts.SourceStateRecord ToLegacySourceStateRecord(this Contracts.SourceCursorState record)
{
var bsonCursor = record.Cursor is null ? null : DocumentObject.Parse(record.Cursor.RootElement.GetRawText());
return new MongoContracts.SourceStateRecord(
var docCursor = record.Cursor is null ? null : DocumentObject.Parse(record.Cursor.RootElement.GetRawText());
return new LegacyContracts.SourceStateRecord(
record.SourceName,
record.Enabled,
record.Paused,
bsonCursor,
docCursor,
record.LastSuccess,
record.LastFailure,
record.FailCount,

View File

@@ -3,7 +3,7 @@ using StellaOps.Concelier.Storage.Postgres.Models;
namespace StellaOps.Concelier.Storage.Postgres.Conversion;
/// <summary>
/// Result of converting a MongoDB advisory document to PostgreSQL entities.
/// Result of converting an advisory document to PostgreSQL entities.
/// Contains the main advisory entity and all related child entities.
/// </summary>
public sealed class AdvisoryConversionResult

View File

@@ -70,7 +70,7 @@ public sealed class PostgresDocumentStore : IDocumentStore, Contracts.IStorageDo
=> (await FindAsync(id, cancellationToken).ConfigureAwait(false))?.ToStorageDocument();
async Task<Contracts.StorageDocument> Contracts.IStorageDocumentStore.UpsertAsync(Contracts.StorageDocument record, CancellationToken cancellationToken)
=> (await UpsertAsync(record.ToMongoDocumentRecord(), cancellationToken).ConfigureAwait(false)).ToStorageDocument();
=> (await UpsertAsync(record.ToLegacyDocumentRecord(), cancellationToken).ConfigureAwait(false)).ToStorageDocument();
Task Contracts.IStorageDocumentStore.UpdateStatusAsync(Guid id, string status, CancellationToken cancellationToken)
=> UpdateStatusAsync(id, status, cancellationToken);

View File

@@ -96,7 +96,7 @@ internal sealed class PostgresDtoStore : IDtoStore, Contracts.IStorageDtoStore
}
async Task<Contracts.StorageDto> Contracts.IStorageDtoStore.UpsertAsync(Contracts.StorageDto record, CancellationToken cancellationToken)
=> (await UpsertAsync(record.ToMongoDtoRecord(), cancellationToken).ConfigureAwait(false)).ToStorageDto();
=> (await UpsertAsync(record.ToLegacyDtoRecord(), cancellationToken).ConfigureAwait(false)).ToStorageDto();
async Task<Contracts.StorageDto?> Contracts.IStorageDtoStore.FindByDocumentIdAsync(Guid documentId, CancellationToken cancellationToken)
=> (await FindByDocumentIdAsync(documentId, cancellationToken).ConfigureAwait(false))?.ToStorageDto();

View File

@@ -5,12 +5,12 @@ using StellaOps.Concelier.Storage.Postgres.Advisories;
using StellaOps.Infrastructure.Postgres;
using StellaOps.Infrastructure.Postgres.Options;
using StellaOps.Concelier.Core.Linksets;
using MongoContracts = StellaOps.Concelier.Storage;
using MongoAdvisories = StellaOps.Concelier.Storage.Advisories;
using MongoExporting = StellaOps.Concelier.Storage.Exporting;
using MongoJpFlags = StellaOps.Concelier.Storage.JpFlags;
using MongoPsirt = StellaOps.Concelier.Storage.PsirtFlags;
using MongoHistory = StellaOps.Concelier.Storage.ChangeHistory;
using StorageContracts = StellaOps.Concelier.Storage;
using AdvisoryContracts = StellaOps.Concelier.Storage.Advisories;
using ExportingContracts = StellaOps.Concelier.Storage.Exporting;
using JpFlagsContracts = StellaOps.Concelier.Storage.JpFlags;
using PsirtContracts = StellaOps.Concelier.Storage.PsirtFlags;
using HistoryContracts = StellaOps.Concelier.Storage.ChangeHistory;
namespace StellaOps.Concelier.Storage.Postgres;
@@ -46,20 +46,20 @@ public static class ServiceCollectionExtensions
services.AddScoped<IAdvisoryWeaknessRepository, AdvisoryWeaknessRepository>();
services.AddScoped<IKevFlagRepository, KevFlagRepository>();
services.AddScoped<StellaOps.Concelier.Storage.Postgres.Repositories.ISourceStateRepository, SourceStateRepository>();
services.AddScoped<MongoAdvisories.IAdvisoryStore, PostgresAdvisoryStore>();
services.AddScoped<AdvisoryContracts.IAdvisoryStore, PostgresAdvisoryStore>();
services.AddScoped<IDocumentRepository, DocumentRepository>();
services.AddScoped<MongoContracts.ISourceStateRepository, PostgresSourceStateAdapter>();
services.AddScoped<StorageContracts.ISourceStateRepository, PostgresSourceStateAdapter>();
services.AddScoped<IFeedSnapshotRepository, FeedSnapshotRepository>();
services.AddScoped<IAdvisorySnapshotRepository, AdvisorySnapshotRepository>();
services.AddScoped<IMergeEventRepository, MergeEventRepository>();
services.AddScoped<IAdvisoryLinksetStore, AdvisoryLinksetCacheRepository>();
services.AddScoped<IAdvisoryLinksetLookup>(sp => sp.GetRequiredService<IAdvisoryLinksetStore>());
services.AddScoped<MongoContracts.IDocumentStore, PostgresDocumentStore>();
services.AddScoped<MongoContracts.IDtoStore, PostgresDtoStore>();
services.AddScoped<MongoExporting.IExportStateStore, PostgresExportStateStore>();
services.AddScoped<MongoPsirt.IPsirtFlagStore, PostgresPsirtFlagStore>();
services.AddScoped<MongoJpFlags.IJpFlagStore, PostgresJpFlagStore>();
services.AddScoped<MongoHistory.IChangeHistoryStore, PostgresChangeHistoryStore>();
services.AddScoped<StorageContracts.IDocumentStore, PostgresDocumentStore>();
services.AddScoped<StorageContracts.IDtoStore, PostgresDtoStore>();
services.AddScoped<ExportingContracts.IExportStateStore, PostgresExportStateStore>();
services.AddScoped<PsirtContracts.IPsirtFlagStore, PostgresPsirtFlagStore>();
services.AddScoped<JpFlagsContracts.IJpFlagStore, PostgresJpFlagStore>();
services.AddScoped<HistoryContracts.IChangeHistoryStore, PostgresChangeHistoryStore>();
return services;
}
@@ -89,20 +89,20 @@ public static class ServiceCollectionExtensions
services.AddScoped<IAdvisoryWeaknessRepository, AdvisoryWeaknessRepository>();
services.AddScoped<IKevFlagRepository, KevFlagRepository>();
services.AddScoped<StellaOps.Concelier.Storage.Postgres.Repositories.ISourceStateRepository, SourceStateRepository>();
services.AddScoped<MongoAdvisories.IAdvisoryStore, PostgresAdvisoryStore>();
services.AddScoped<AdvisoryContracts.IAdvisoryStore, PostgresAdvisoryStore>();
services.AddScoped<IDocumentRepository, DocumentRepository>();
services.AddScoped<MongoContracts.ISourceStateRepository, PostgresSourceStateAdapter>();
services.AddScoped<StorageContracts.ISourceStateRepository, PostgresSourceStateAdapter>();
services.AddScoped<IFeedSnapshotRepository, FeedSnapshotRepository>();
services.AddScoped<IAdvisorySnapshotRepository, AdvisorySnapshotRepository>();
services.AddScoped<IMergeEventRepository, MergeEventRepository>();
services.AddScoped<IAdvisoryLinksetStore, AdvisoryLinksetCacheRepository>();
services.AddScoped<IAdvisoryLinksetLookup>(sp => sp.GetRequiredService<IAdvisoryLinksetStore>());
services.AddScoped<MongoContracts.IDocumentStore, PostgresDocumentStore>();
services.AddScoped<MongoContracts.IDtoStore, PostgresDtoStore>();
services.AddScoped<MongoExporting.IExportStateStore, PostgresExportStateStore>();
services.AddScoped<MongoPsirt.IPsirtFlagStore, PostgresPsirtFlagStore>();
services.AddScoped<MongoJpFlags.IJpFlagStore, PostgresJpFlagStore>();
services.AddScoped<MongoHistory.IChangeHistoryStore, PostgresChangeHistoryStore>();
services.AddScoped<StorageContracts.IDocumentStore, PostgresDocumentStore>();
services.AddScoped<StorageContracts.IDtoStore, PostgresDtoStore>();
services.AddScoped<ExportingContracts.IExportStateStore, PostgresExportStateStore>();
services.AddScoped<PsirtContracts.IPsirtFlagStore, PostgresPsirtFlagStore>();
services.AddScoped<JpFlagsContracts.IJpFlagStore, PostgresJpFlagStore>();
services.AddScoped<HistoryContracts.IChangeHistoryStore, PostgresChangeHistoryStore>();
return services;
}

View File

@@ -5,14 +5,14 @@ using StellaOps.Concelier.Documents;
using StellaOps.Concelier.Storage.Postgres.Models;
using StellaOps.Concelier.Storage.Postgres.Repositories;
using Contracts = StellaOps.Concelier.Storage.Contracts;
using MongoContracts = StellaOps.Concelier.Storage;
using LegacyContracts = StellaOps.Concelier.Storage;
namespace StellaOps.Concelier.Storage.Postgres;
/// <summary>
/// Adapter that satisfies the legacy source state contract using PostgreSQL storage and provides a Postgres-native cursor contract.
/// </summary>
public sealed class PostgresSourceStateAdapter : MongoContracts.ISourceStateRepository, Contracts.ISourceStateStore
public sealed class PostgresSourceStateAdapter : LegacyContracts.ISourceStateRepository, Contracts.ISourceStateStore
{
private readonly ISourceRepository _sourceRepository;
private readonly Repositories.ISourceStateRepository _stateRepository;
@@ -28,7 +28,7 @@ public sealed class PostgresSourceStateAdapter : MongoContracts.ISourceStateRepo
_timeProvider = timeProvider ?? TimeProvider.System;
}
public async Task<MongoContracts.SourceStateRecord?> TryGetAsync(string sourceName, CancellationToken cancellationToken)
public async Task<LegacyContracts.SourceStateRecord?> TryGetAsync(string sourceName, CancellationToken cancellationToken)
{
ArgumentException.ThrowIfNullOrEmpty(sourceName);
@@ -46,7 +46,7 @@ public sealed class PostgresSourceStateAdapter : MongoContracts.ISourceStateRepo
var cursor = string.IsNullOrWhiteSpace(state.Cursor) ? null : DocumentObject.Parse(state.Cursor);
var backoffUntil = TryParseBackoffUntil(state.Metadata);
return new MongoContracts.SourceStateRecord(
return new LegacyContracts.SourceStateRecord(
sourceName,
Enabled: true,
Paused: false,
@@ -115,7 +115,7 @@ public sealed class PostgresSourceStateAdapter : MongoContracts.ISourceStateRepo
_ = await _stateRepository.UpsertAsync(entity, cancellationToken).ConfigureAwait(false);
}
public async Task UpsertAsync(MongoContracts.SourceStateRecord record, CancellationToken cancellationToken)
public async Task UpsertAsync(LegacyContracts.SourceStateRecord record, CancellationToken cancellationToken)
{
ArgumentNullException.ThrowIfNull(record);
var source = await EnsureSourceAsync(record.SourceName, cancellationToken).ConfigureAwait(false);
@@ -146,7 +146,7 @@ public sealed class PostgresSourceStateAdapter : MongoContracts.ISourceStateRepo
=> MarkFailureAsync(sourceName, now, backoff, reason, cancellationToken);
Task Contracts.ISourceStateStore.UpsertAsync(Contracts.SourceCursorState record, CancellationToken cancellationToken)
=> UpsertAsync(record.ToMongoSourceStateRecord(), cancellationToken);
=> UpsertAsync(record.ToLegacySourceStateRecord(), cancellationToken);
private async Task<SourceEntity> EnsureSourceAsync(string sourceName, CancellationToken cancellationToken)
{

View File

@@ -22,7 +22,7 @@ namespace StellaOps.Concelier.Connector.Common.Tests;
public sealed class SourceFetchServiceGuardTests : IAsyncLifetime
{
private readonly InMemoryDbRunner _runner;
private readonly IMongoDatabase _database;
private readonly IStorageDatabase _database;
private readonly RawDocumentStorage _rawStorage;
private readonly ICryptoHash _hash;

View File

@@ -19,7 +19,7 @@ public sealed class SourceStateSeedProcessorTests : IAsyncLifetime
{
private readonly InMemoryDbRunner _runner;
private readonly InMemoryClient _client;
private readonly IMongoDatabase _database;
private readonly IStorageDatabase _database;
private readonly DocumentStore _documentStore;
private readonly RawDocumentStorage _rawStorage;
private readonly InMemorySourceStateRepository _stateRepository;

View File

@@ -52,7 +52,7 @@ public sealed class TimeWindowCursorPlannerTests
}
[Fact]
public void TimeWindowCursorState_RoundTripThroughBson()
public void TimeWindowCursorState_RoundTripThroughDocument()
{
var state = new TimeWindowCursorState(
new DateTimeOffset(2024, 9, 1, 0, 0, 0, TimeSpan.Zero),

View File

@@ -480,7 +480,7 @@ public sealed class RedHatConnectorTests : IAsyncLifetime
var json = File.ReadAllText(jsonPath);
using var jsonDocument = JsonDocument.Parse(json);
var bson = DocumentObject.Parse(json);
var doc = DocumentObject.Parse(json);
var metadata = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
@@ -501,7 +501,7 @@ public sealed class RedHatConnectorTests : IAsyncLifetime
LastModified: fixture.ValidatedAt,
PayloadId: null);
var dto = new DtoRecord(Guid.NewGuid(), document.Id, RedHatConnectorPlugin.SourceName, "redhat.csaf.v2", bson, fixture.ValidatedAt);
var dto = new DtoRecord(Guid.NewGuid(), document.Id, RedHatConnectorPlugin.SourceName, "redhat.csaf.v2", doc, fixture.ValidatedAt);
var advisory = RedHatMapper.Map(RedHatConnectorPlugin.SourceName, dto, document, jsonDocument);
Assert.NotNull(advisory);

View File

@@ -56,7 +56,7 @@ public sealed class RuBduConnectorSnapshotTests : IAsyncLifetime
var stateRepository = harness.ServiceProvider.GetRequiredService<ISourceStateRepository>();
var initialState = await stateRepository.TryGetAsync(RuBduConnectorPlugin.SourceName, CancellationToken.None);
Assert.NotNull(initialState);
var cursorBeforeParse = initialState!.Cursor is null ? RuBduCursor.Empty : RuBduCursor.FromBson(initialState.Cursor);
var cursorBeforeParse = initialState!.Cursor is null ? RuBduCursor.Empty : RuBduCursor.FromDocument(initialState.Cursor);
Assert.NotEmpty(cursorBeforeParse.PendingDocuments);
var expectedDocumentIds = cursorBeforeParse.PendingDocuments.ToArray();
@@ -217,7 +217,7 @@ public sealed class RuBduConnectorSnapshotTests : IAsyncLifetime
var state = await stateRepository.TryGetAsync(RuBduConnectorPlugin.SourceName, CancellationToken.None);
Assert.NotNull(state);
var cursor = state!.Cursor is null ? RuBduCursor.Empty : RuBduCursor.FromBson(state.Cursor);
var cursor = state!.Cursor is null ? RuBduCursor.Empty : RuBduCursor.FromDocument(state.Cursor);
var snapshot = new
{
PendingDocuments = cursor.PendingDocuments.Select(static guid => guid.ToString()).OrderBy(static id => id, StringComparer.Ordinal).ToArray(),

View File

@@ -89,17 +89,17 @@ public sealed class StellaOpsMirrorConnectorTests : IAsyncLifetime
Assert.NotNull(state);
var cursorDocument = state!.Cursor ?? new DocumentObject();
var digestValue = cursorDocument.TryGetValue("bundleDigest", out var digestBson) ? digestBson.AsString : string.Empty;
var digestValue = cursorDocument.TryGetValue("bundleDigest", out var digestDoc) ? digestDoc.AsString : string.Empty;
Assert.Equal(NormalizeDigest(bundleDigest), NormalizeDigest(digestValue));
var pendingDocumentsArray = cursorDocument.TryGetValue("pendingDocuments", out var pendingDocsBson) && pendingDocsBson is DocumentArray pendingArray
var pendingDocumentsArray = cursorDocument.TryGetValue("pendingDocuments", out var pendingDocsDoc) && pendingDocsDoc is DocumentArray pendingArray
? pendingArray
: new DocumentArray();
Assert.Single(pendingDocumentsArray);
var pendingDocumentId = Guid.Parse(pendingDocumentsArray[0].AsString);
Assert.Equal(bundleDocument.Id, pendingDocumentId);
var pendingMappingsArray = cursorDocument.TryGetValue("pendingMappings", out var pendingMappingsBson) && pendingMappingsBson is DocumentArray mappingsArray
var pendingMappingsArray = cursorDocument.TryGetValue("pendingMappings", out var pendingMappingsDoc) && pendingMappingsDoc is DocumentArray mappingsArray
? mappingsArray
: new DocumentArray();
Assert.Empty(pendingMappingsArray);

View File

@@ -143,7 +143,7 @@ public sealed class OracleConnectorTests : IAsyncLifetime
var stateRepository = provider.GetRequiredService<ISourceStateRepository>();
var state = await stateRepository.TryGetAsync(VndrOracleConnectorPlugin.SourceName, CancellationToken.None);
Assert.NotNull(state);
var cursor = OracleCursor.FromBson(state!.Cursor);
var cursor = OracleCursor.FromDocument(state!.Cursor);
Assert.Empty(cursor.PendingDocuments);
Assert.Empty(cursor.PendingMappings);
Assert.Equal(2, cursor.FetchCache.Count);
@@ -250,7 +250,7 @@ public sealed class OracleConnectorTests : IAsyncLifetime
var stateRepository = provider.GetRequiredService<ISourceStateRepository>();
var state = await stateRepository.TryGetAsync(VndrOracleConnectorPlugin.SourceName, CancellationToken.None);
Assert.NotNull(state);
var cursor = OracleCursor.FromBson(state!.Cursor);
var cursor = OracleCursor.FromDocument(state!.Cursor);
Assert.Empty(cursor.PendingDocuments);
Assert.Empty(cursor.PendingMappings);
}

View File

@@ -101,7 +101,7 @@ public sealed class VmwareConnectorTests : IAsyncLifetime
Assert.NotNull(state);
Assert.Empty(state!.Cursor.TryGetValue("pendingDocuments", out var pendingDocs) ? pendingDocs.AsDocumentArray : new DocumentArray());
Assert.Empty(state.Cursor.TryGetValue("pendingMappings", out var pendingMaps) ? pendingMaps.AsDocumentArray : new DocumentArray());
var cursorSnapshot = VmwareCursor.FromBson(state.Cursor);
var cursorSnapshot = VmwareCursor.FromDocument(state.Cursor);
_output.WriteLine($"Initial fetch cache entries: {cursorSnapshot.FetchCache.Count}");
foreach (var entry in cursorSnapshot.FetchCache)
{

View File

@@ -90,7 +90,7 @@ public sealed class MergePrecedenceIntegrationTests : IAsyncLifetime
{
return Task.CompletedTask;
// {
// await _fixture.Database.DropCollectionAsync(MongoStorageDefaults.Collections.MergeEvent);
// await _fixture.Database.DropCollectionAsync(StorageDefaults.Collections.MergeEvent);
// }
// catch (StorageCommandException ex) when (ex.CodeName == "NamespaceNotFound" || ex.Message.Contains("ns not found", StringComparison.OrdinalIgnoreCase))
// {

View File

@@ -16,12 +16,12 @@ public sealed class HealthWebAppFactory : WebApplicationFactory<Program>
public HealthWebAppFactory()
{
// Ensure options binder sees required storage values before Program.Main executes.
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__DSN", "mongodb://localhost:27017/test-health");
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__DRIVER", "mongo");
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__DSN", "Host=localhost;Port=5432;Database=test-health");
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__DRIVER", "postgres");
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__COMMANDTIMEOUTSECONDS", "30");
Environment.SetEnvironmentVariable("CONCELIER__TELEMETRY__ENABLED", "false");
Environment.SetEnvironmentVariable("CONCELIER_SKIP_OPTIONS_VALIDATION", "1");
Environment.SetEnvironmentVariable("CONCELIER_TEST_STORAGE_DSN", "mongodb://localhost:27017/test-health");
Environment.SetEnvironmentVariable("CONCELIER_TEST_STORAGE_DSN", "Host=localhost;Port=5432;Database=test-health");
Environment.SetEnvironmentVariable("DOTNET_ENVIRONMENT", "Testing");
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Testing");
}
@@ -32,8 +32,8 @@ public sealed class HealthWebAppFactory : WebApplicationFactory<Program>
{
var overrides = new Dictionary<string, string?>
{
{"Storage:Dsn", "mongodb://localhost:27017/test-health"},
{"Storage:Driver", "mongo"},
{"Storage:Dsn", "Host=localhost;Port=5432;Database=test-health"},
{"Storage:Driver", "postgres"},
{"Storage:CommandTimeoutSeconds", "30"},
{"Telemetry:Enabled", "false"}
};
@@ -41,8 +41,8 @@ public sealed class HealthWebAppFactory : WebApplicationFactory<Program>
config.AddInMemoryCollection(overrides);
});
builder.UseSetting("CONCELIER__STORAGE__DSN", "mongodb://localhost:27017/test-health");
builder.UseSetting("CONCELIER__STORAGE__DRIVER", "mongo");
builder.UseSetting("CONCELIER__STORAGE__DSN", "Host=localhost;Port=5432;Database=test-health");
builder.UseSetting("CONCELIER__STORAGE__DRIVER", "postgres");
builder.UseSetting("CONCELIER__STORAGE__COMMANDTIMEOUTSECONDS", "30");
builder.UseSetting("CONCELIER__TELEMETRY__ENABLED", "false");
@@ -54,8 +54,8 @@ public sealed class HealthWebAppFactory : WebApplicationFactory<Program>
{
Storage = new ConcelierOptions.StorageOptions
{
Dsn = "mongodb://localhost:27017/test-health",
Driver = "mongo",
Dsn = "Host=localhost;Port=5432;Database=test-health",
Driver = "postgres",
CommandTimeoutSeconds = 30
},
Telemetry = new ConcelierOptions.TelemetryOptions
@@ -67,8 +67,8 @@ public sealed class HealthWebAppFactory : WebApplicationFactory<Program>
services.AddSingleton<IConfigureOptions<ConcelierOptions>>(sp => new ConfigureOptions<ConcelierOptions>(opts =>
{
opts.Storage ??= new ConcelierOptions.StorageOptions();
opts.Storage.Driver = "mongo";
opts.Storage.Dsn = "mongodb://localhost:27017/test-health";
opts.Storage.Driver = "postgres";
opts.Storage.Dsn = "Host=localhost;Port=5432;Database=test-health";
opts.Storage.CommandTimeoutSeconds = 30;
opts.Telemetry ??= new ConcelierOptions.TelemetryOptions();
@@ -77,8 +77,8 @@ public sealed class HealthWebAppFactory : WebApplicationFactory<Program>
services.PostConfigure<ConcelierOptions>(opts =>
{
opts.Storage ??= new ConcelierOptions.StorageOptions();
opts.Storage.Driver = "mongo";
opts.Storage.Dsn = "mongodb://localhost:27017/test-health";
opts.Storage.Driver = "postgres";
opts.Storage.Dsn = "Host=localhost;Port=5432;Database=test-health";
opts.Storage.CommandTimeoutSeconds = 30;
opts.Telemetry ??= new ConcelierOptions.TelemetryOptions();

View File

@@ -5,7 +5,7 @@ using StellaOps.Concelier.Documents.Serialization.Attributes;
namespace StellaOps.Concelier.WebService.Tests;
/// <summary>
/// Minimal linkset document used only for seeding the Mongo collection in WebService integration tests.
/// Minimal linkset document used for seeding the storage in WebService integration tests.
/// Matches the shape written by the linkset ingestion pipeline.
/// </summary>
internal sealed class AdvisoryLinksetDocument

View File

@@ -22,14 +22,14 @@ public sealed class OrchestratorTestWebAppFactory : WebApplicationFactory<Progra
{
public OrchestratorTestWebAppFactory()
{
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__DSN", "mongodb://localhost:27017/orch-tests");
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__DRIVER", "mongo");
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__DSN", "Host=localhost;Port=5432;Database=orch-tests");
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__DRIVER", "postgres");
Environment.SetEnvironmentVariable("CONCELIER__STORAGE__COMMANDTIMEOUTSECONDS", "30");
Environment.SetEnvironmentVariable("CONCELIER__TELEMETRY__ENABLED", "false");
Environment.SetEnvironmentVariable("CONCELIER__AUTHORITY__ENABLED", "false"); // disable auth so tests can hit endpoints without tokens
Environment.SetEnvironmentVariable("CONCELIER_SKIP_OPTIONS_VALIDATION", "1");
Environment.SetEnvironmentVariable("CONCELIER_TEST_STORAGE_DSN", "mongodb://localhost:27017/orch-tests");
Environment.SetEnvironmentVariable("CONCELIER_BYPASS_MONGO", "1");
Environment.SetEnvironmentVariable("CONCELIER_TEST_STORAGE_DSN", "Host=localhost;Port=5432;Database=orch-tests");
Environment.SetEnvironmentVariable("CONCELIER_BYPASS_EXTERNAL_STORAGE", "1");
Environment.SetEnvironmentVariable("DOTNET_ENVIRONMENT", "Testing");
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", "Testing");
}
@@ -42,8 +42,8 @@ public sealed class OrchestratorTestWebAppFactory : WebApplicationFactory<Progra
{
cfg.AddInMemoryCollection(new Dictionary<string, string?>
{
["Concelier:Storage:Dsn"] = "mongodb://localhost:27017/orch-tests",
["Concelier:Storage:Driver"] = "mongo",
["Concelier:Storage:Dsn"] = "Host=localhost;Port=5432;Database=orch-tests",
["Concelier:Storage:Driver"] = "postgres",
["Concelier:Storage:CommandTimeoutSeconds"] = "30",
["Concelier:Telemetry:Enabled"] = "false",
["Concelier:Authority:Enabled"] = "false"
@@ -62,8 +62,8 @@ public sealed class OrchestratorTestWebAppFactory : WebApplicationFactory<Progra
{
Storage = new ConcelierOptions.StorageOptions
{
Dsn = "mongodb://localhost:27017/orch-tests",
Driver = "mongo",
Dsn = "Host=localhost;Port=5432;Database=orch-tests",
Driver = "postgres",
CommandTimeoutSeconds = 30
},
Telemetry = new ConcelierOptions.TelemetryOptions
@@ -78,10 +78,10 @@ public sealed class OrchestratorTestWebAppFactory : WebApplicationFactory<Progra
services.AddSingleton(forcedOptions);
services.AddSingleton<IOptions<ConcelierOptions>>(_ => Microsoft.Extensions.Options.Options.Create(forcedOptions));
// Force Mongo storage options to a deterministic in-memory test DSN.
// Force storage options to a deterministic in-memory test DSN.
services.PostConfigure<StorageOptions>(opts =>
{
opts.ConnectionString = "mongodb://localhost:27017/orch-tests";
opts.ConnectionString = "Host=localhost;Port=5432;Database=orch-tests";
opts.DatabaseName = "orch-tests";
opts.CommandTimeout = TimeSpan.FromSeconds(30);
});

View File

@@ -64,8 +64,6 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
private readonly ITestOutputHelper _output;
private InMemoryDbRunner _runner = null!;
private Process? _externalMongo;
private string? _externalMongoDataPath;
private ConcelierApplicationFactory _factory = null!;
public WebServiceEndpointsTests(ITestOutputHelper output)
@@ -1735,12 +1733,12 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
private async Task SeedObservationDocumentsAsync(IEnumerable<AdvisoryObservationDocument> documents)
{
var client = new InMemoryClient(_runner.ConnectionString);
var database = client.GetDatabase(MongoStorageDefaults.DefaultDatabaseName);
var collection = database.GetCollection<AdvisoryObservationDocument>(MongoStorageDefaults.Collections.AdvisoryObservations);
var database = client.GetDatabase(StorageDefaults.DefaultDatabaseName);
var collection = database.GetCollection<AdvisoryObservationDocument>(StorageDefaults.Collections.AdvisoryObservations);
try
{
await database.DropCollectionAsync(MongoStorageDefaults.Collections.AdvisoryObservations);
await database.DropCollectionAsync(StorageDefaults.Collections.AdvisoryObservations);
}
catch (StorageCommandException ex) when (ex.CodeName == "NamespaceNotFound" || ex.Message.Contains("ns not found", StringComparison.OrdinalIgnoreCase))
{
@@ -1771,12 +1769,12 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
private async Task SeedLinksetDocumentsAsync(IEnumerable<AdvisoryLinksetDocument> documents)
{
var client = new InMemoryClient(_runner.ConnectionString);
var database = client.GetDatabase(MongoStorageDefaults.DefaultDatabaseName);
var collection = database.GetCollection<AdvisoryLinksetDocument>(MongoStorageDefaults.Collections.AdvisoryLinksets);
var database = client.GetDatabase(StorageDefaults.DefaultDatabaseName);
var collection = database.GetCollection<AdvisoryLinksetDocument>(StorageDefaults.Collections.AdvisoryLinksets);
try
{
await database.DropCollectionAsync(MongoStorageDefaults.Collections.AdvisoryLinksets);
await database.DropCollectionAsync(StorageDefaults.Collections.AdvisoryLinksets);
}
catch (StorageCommandException ex) when (ex.CodeName == "NamespaceNotFound" || ex.Message.Contains("ns not found", StringComparison.OrdinalIgnoreCase))
{
@@ -2004,7 +2002,7 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
IDictionary<string, string?>? environmentOverrides = null)
{
var defaultPostgresDsn = "Host=localhost;Port=5432;Database=concelier_test;Username=postgres;Password=postgres";
_connectionString = string.IsNullOrWhiteSpace(connectionString) || connectionString.StartsWith("mongodb://", StringComparison.OrdinalIgnoreCase)
_connectionString = string.IsNullOrWhiteSpace(connectionString)
? defaultPostgresDsn
: connectionString;
_authorityConfigure = authorityConfigure;
@@ -2098,7 +2096,7 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
services.AddSingleton<IJobCoordinator>(sp => sp.GetRequiredService<StubJobCoordinator>());
services.PostConfigure<ConcelierOptions>(options =>
{
options.Storage.Driver = "mongo";
options.Storage.Driver = "postgres";
options.Storage.Dsn = _connectionString;
options.Storage.CommandTimeoutSeconds = 30;
options.Plugins.Directory ??= Path.Combine(AppContext.BaseDirectory, "StellaOps.Concelier.PluginBinaries");
@@ -2362,8 +2360,8 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
Assert.Equal(HttpStatusCode.Accepted, response.StatusCode);
using var validationScope = _factory.Services.CreateScope();
var database = validationScope.ServiceProvider.GetRequiredService<IMongoDatabase>();
var statements = database.GetCollection<DocumentObject>(MongoStorageDefaults.Collections.AdvisoryStatements);
var database = validationScope.ServiceProvider.GetRequiredService<IStorageDatabase>();
var statements = database.GetCollection<DocumentObject>(StorageDefaults.Collections.AdvisoryStatements);
var stored = await statements
.Find(Builders<DocumentObject>.Filter.Eq("_id", statementId.ToString()))
@@ -2379,8 +2377,8 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
finally
{
using var cleanupScope = _factory.Services.CreateScope();
var database = cleanupScope.ServiceProvider.GetRequiredService<IMongoDatabase>();
var statements = database.GetCollection<DocumentObject>(MongoStorageDefaults.Collections.AdvisoryStatements);
var database = cleanupScope.ServiceProvider.GetRequiredService<IStorageDatabase>();
var statements = database.GetCollection<DocumentObject>(StorageDefaults.Collections.AdvisoryStatements);
await statements.DeleteOneAsync(Builders<DocumentObject>.Filter.Eq("_id", statementId.ToString()));
}
}
@@ -2461,10 +2459,10 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
private async Task SeedCanonicalAdvisoriesAsync(params Advisory[] advisories)
{
using var scope = _factory.Services.CreateScope();
var database = scope.ServiceProvider.GetRequiredService<IMongoDatabase>();
var database = scope.ServiceProvider.GetRequiredService<IStorageDatabase>();
await DropCollectionIfExistsAsync(database, MongoStorageDefaults.Collections.Advisory);
await DropCollectionIfExistsAsync(database, MongoStorageDefaults.Collections.Alias);
await DropCollectionIfExistsAsync(database, StorageDefaults.Collections.Advisory);
await DropCollectionIfExistsAsync(database, StorageDefaults.Collections.Alias);
if (advisories.Length == 0)
{
@@ -2478,7 +2476,7 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
}
}
private static async Task DropCollectionIfExistsAsync(IMongoDatabase database, string collectionName)
private static async Task DropCollectionIfExistsAsync(IStorageDatabase database, string collectionName)
{
try
{
@@ -2576,8 +2574,8 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
private async Task SeedAdvisoryRawDocumentsAsync(params DocumentObject[] documents)
{
var client = new InMemoryClient(_runner.ConnectionString);
var database = client.GetDatabase(MongoStorageDefaults.DefaultDatabaseName);
var collection = database.GetCollection<DocumentObject>(MongoStorageDefaults.Collections.AdvisoryRaw);
var database = client.GetDatabase(StorageDefaults.DefaultDatabaseName);
var collection = database.GetCollection<DocumentObject>(StorageDefaults.Collections.AdvisoryRaw);
await collection.DeleteManyAsync(FilterDefinition<DocumentObject>.Empty);
if (documents.Length > 0)
{
@@ -2705,252 +2703,6 @@ public sealed class WebServiceEndpointsTests : IAsyncLifetime
using var client = factory.CreateClient();
}
/// <summary>
/// Ensure Mongo2Go can start without external downloads by pointing it to cached binaries and OpenSSL 1.1 libs shipped in repo.
/// </summary>
private static void PrepareMongoEnvironment()
{
var repoRoot = FindRepoRoot();
if (repoRoot is null)
{
return;
}
var cacheDir = Path.Combine(repoRoot, ".cache", "mongodb-local");
Directory.CreateDirectory(cacheDir);
Environment.SetEnvironmentVariable("MONGO2GO_CACHE_LOCATION", cacheDir);
Environment.SetEnvironmentVariable("MONGO2GO_DOWNLOADS", cacheDir);
Environment.SetEnvironmentVariable("MONGO2GO_MONGODB_VERSION", "4.4.4");
Environment.SetEnvironmentVariable("MONGO2GO_MONGODB_PLATFORM", "linux");
var opensslPath = Path.Combine(repoRoot, "tests", "native", "openssl-1.1", "linux-x64");
if (Directory.Exists(opensslPath))
{
// Prepend OpenSSL 1.1 path so Mongo2Go binaries find libssl/libcrypto.
var existing = Environment.GetEnvironmentVariable("LD_LIBRARY_PATH");
var combined = string.IsNullOrEmpty(existing) ? opensslPath : $"{opensslPath}:{existing}";
Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", combined);
}
// Also drop the OpenSSL libs next to the mongod binary Mongo2Go will spawn, in case LD_LIBRARY_PATH is ignored.
var repoNuget = Path.Combine(repoRoot, ".nuget", "packages", "mongo2go");
var homeNuget = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages", "mongo2go");
var mongoBin = Directory.Exists(repoNuget)
? Directory.GetFiles(repoNuget, "mongod", SearchOption.AllDirectories)
.FirstOrDefault(path => path.Contains("mongodb-linux-4.4.4", StringComparison.OrdinalIgnoreCase))
: null;
// Prefer globally cached Mongo2Go binaries if repo-local cache is missing.
mongoBin ??= Directory.Exists(homeNuget)
? Directory.GetFiles(homeNuget, "mongod", SearchOption.AllDirectories)
.FirstOrDefault(path => path.Contains("mongodb-linux-4.4.4", StringComparison.OrdinalIgnoreCase))
: null;
if (mongoBin is not null && File.Exists(mongoBin) && Directory.Exists(opensslPath))
{
var binDir = Path.GetDirectoryName(mongoBin)!;
// Create a tiny wrapper so the loader always gets LD_LIBRARY_PATH even if vstest strips it.
var wrapperPath = Path.Combine(cacheDir, "mongod-wrapper.sh");
Directory.CreateDirectory(cacheDir);
var script = $"#!/usr/bin/env bash\nset -euo pipefail\nexport LD_LIBRARY_PATH=\"{opensslPath}:${{LD_LIBRARY_PATH:-}}\"\nexec \"{mongoBin}\" \"$@\"\n";
File.WriteAllText(wrapperPath, script);
if (OperatingSystem.IsLinux())
{
try
{
File.SetUnixFileMode(wrapperPath,
UnixFileMode.UserRead | UnixFileMode.UserWrite | UnixFileMode.UserExecute |
UnixFileMode.GroupRead | UnixFileMode.GroupExecute |
UnixFileMode.OtherRead | UnixFileMode.OtherExecute);
}
catch
{
// Best-effort; if not supported, chmod will fall back to default permissions.
}
}
// Force Mongo2Go to use the wrapper to avoid downloads and inject OpenSSL search path.
Environment.SetEnvironmentVariable("MONGO2GO_MONGODB_BINARY", wrapperPath);
// Keep direct LD_LIBRARY_PATH/PATH hints for any code paths that still honour parent env.
var existing = Environment.GetEnvironmentVariable("LD_LIBRARY_PATH");
var combined = string.IsNullOrEmpty(existing) ? binDir : $"{binDir}:{existing}";
Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", combined);
Environment.SetEnvironmentVariable("PATH", $"{binDir}:{Environment.GetEnvironmentVariable("PATH")}");
foreach (var libName in new[] { "libssl.so.1.1", "libcrypto.so.1.1" })
{
var target = Path.Combine(binDir, libName);
var source = Path.Combine(opensslPath, libName);
if (File.Exists(source) && !File.Exists(target))
{
File.Copy(source, target);
}
}
// If the Mongo2Go global cache is different from the first hit, add its bin dir too.
var globalBin = Directory.Exists(homeNuget)
? Directory.GetFiles(homeNuget, "mongod", SearchOption.AllDirectories)
.FirstOrDefault(path => path.Contains("mongodb-linux-4.4.4", StringComparison.OrdinalIgnoreCase))
: null;
if (globalBin is not null)
{
var globalDir = Path.GetDirectoryName(globalBin)!;
var withGlobal = Environment.GetEnvironmentVariable("LD_LIBRARY_PATH") ?? string.Empty;
if (!withGlobal.Split(':', StringSplitOptions.RemoveEmptyEntries).Contains(globalDir))
{
Environment.SetEnvironmentVariable("LD_LIBRARY_PATH", $"{globalDir}:{withGlobal}".TrimEnd(':'));
}
Environment.SetEnvironmentVariable("PATH", $"{globalDir}:{Environment.GetEnvironmentVariable("PATH")}");
foreach (var libName in new[] { "libssl.so.1.1", "libcrypto.so.1.1" })
{
var target = Path.Combine(globalDir, libName);
var source = Path.Combine(opensslPath, libName);
if (File.Exists(source) && !File.Exists(target))
{
File.Copy(source, target);
}
}
}
}
}
private bool TryStartExternalMongo(out string? connectionString)
{
connectionString = null;
var repoRoot = FindRepoRoot();
if (repoRoot is null)
{
return false;
}
var mongodCandidates = new List<string>();
void AddCandidates(string root)
{
if (Directory.Exists(root))
{
mongodCandidates.AddRange(Directory.GetFiles(root, "mongod", SearchOption.AllDirectories)
.Where(p => p.Contains("mongodb-linux-4.4.4", StringComparison.OrdinalIgnoreCase)));
}
}
AddCandidates(Path.Combine(repoRoot, ".nuget", "packages", "mongo2go"));
AddCandidates(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages", "mongo2go"));
var mongodPath = mongodCandidates.FirstOrDefault();
if (mongodPath is null)
{
return false;
}
var dataDir = Path.Combine(repoRoot, ".cache", "mongodb-local", $"manual-{Guid.NewGuid():N}");
Directory.CreateDirectory(dataDir);
var opensslPath = Path.Combine(repoRoot, "tests", "native", "openssl-1.1", "linux-x64");
var port = GetEphemeralPort();
var psi = new ProcessStartInfo
{
FileName = mongodPath,
ArgumentList =
{
"--dbpath", dataDir,
"--bind_ip", "127.0.0.1",
"--port", port.ToString(),
"--nojournal",
"--quiet",
"--replSet", "rs0"
},
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardOutput = true
};
var existingLd = Environment.GetEnvironmentVariable("LD_LIBRARY_PATH");
var ldCombined = string.IsNullOrEmpty(existingLd) ? opensslPath : $"{opensslPath}:{existingLd}";
psi.Environment["LD_LIBRARY_PATH"] = ldCombined;
psi.Environment["PATH"] = $"{Path.GetDirectoryName(mongodPath)}:{Environment.GetEnvironmentVariable("PATH")}";
_externalMongo = Process.Start(psi);
_externalMongoDataPath = dataDir;
if (_externalMongo is null)
{
return false;
}
// Small ping loop to ensure mongod is ready
var client = new InMemoryClient($"mongodb://127.0.0.1:{port}");
var sw = System.Diagnostics.Stopwatch.StartNew();
while (sw.Elapsed < TimeSpan.FromSeconds(5))
{
try
{
client.GetDatabase("admin").RunCommand<DocumentObject>("{ ping: 1 }");
// Initiate single-node replica set so features expecting replset work.
client.GetDatabase("admin").RunCommand<DocumentObject>(DocumentObject.Parse("{ replSetInitiate: { _id: \"rs0\", members: [ { _id: 0, host: \"127.0.0.1:" + port + "\" } ] } }"));
// Wait for primary
var readySw = System.Diagnostics.Stopwatch.StartNew();
while (readySw.Elapsed < TimeSpan.FromSeconds(5))
{
var status = client.GetDatabase("admin").RunCommand<DocumentObject>(DocumentObject.Parse("{ replSetGetStatus: 1 }"));
var myState = status["members"].AsDocumentArray.FirstOrDefault(x => x["self"].AsBoolean);
if (myState != null && myState["state"].ToInt32() == 1)
{
connectionString = $"mongodb://127.0.0.1:{port}/?replicaSet=rs0";
return true;
}
Thread.Sleep(100);
}
// fallback if primary not reached
connectionString = $"mongodb://127.0.0.1:{port}";
return true;
}
catch
{
Thread.Sleep(100);
}
}
try { _externalMongo.Kill(true); } catch { /* ignore */ }
return false;
}
private static int GetEphemeralPort()
{
var listener = new System.Net.Sockets.TcpListener(IPAddress.Loopback, 0);
listener.Start();
var port = ((IPEndPoint)listener.LocalEndpoint).Port;
listener.Stop();
return port;
}
private static string? FindRepoRoot()
{
var current = AppContext.BaseDirectory;
string? lastMatch = null;
while (!string.IsNullOrEmpty(current))
{
if (File.Exists(Path.Combine(current, "Directory.Build.props")))
{
lastMatch = current;
}
var parent = Directory.GetParent(current);
if (parent is null)
{
break;
}
current = parent.FullName;
}
return lastMatch;
}
private static AdvisoryIngestRequest BuildAdvisoryIngestRequest(
string? contentHash,
string upstreamId,