Resolve C# subscription filters by schema alias
This commit is contained in:
parent
c0eacb885b
commit
1b9140da3d
2 changed files with 117 additions and 5 deletions
|
|
@ -344,7 +344,10 @@ namespace GameCult.Networking
|
|||
var changeType = change.GetType();
|
||||
var key = (CultRecordKey)(changeType.GetProperty("Key")?.GetValue(change) ?? new CultRecordKey(string.Empty));
|
||||
var schemaId = (string?)changeType.GetProperty("SchemaId")?.GetValue(change) ?? string.Empty;
|
||||
if (!Matches(request, schemaId, key))
|
||||
var documentType = changeType.IsGenericType ? changeType.GetGenericArguments()[0] : null;
|
||||
var descriptor = documentType == null ? null : _database.Cache.Registry.GetRequired(documentType);
|
||||
var binding = documentType == null ? null : _database.Documents.GetByDocumentType(documentType);
|
||||
if (!Matches(request, schemaId, key, descriptor, binding))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
|
@ -387,17 +390,75 @@ namespace GameCult.Networking
|
|||
return ((CultNetDocumentPutRawMessage)message!).Document;
|
||||
}
|
||||
|
||||
private static bool Matches(CultNetDatabaseSubscribeMessage request, string schemaId, CultRecordKey key)
|
||||
private static bool Matches(
|
||||
CultNetDatabaseSubscribeMessage request,
|
||||
string schemaId,
|
||||
CultRecordKey key,
|
||||
CultDocumentDescriptor? descriptor,
|
||||
CultNetDocumentBinding? binding)
|
||||
{
|
||||
var schemaMatches = request.SchemaIds == null ||
|
||||
request.SchemaIds.Length == 0 ||
|
||||
request.SchemaIds.Contains(schemaId, StringComparer.Ordinal);
|
||||
var schemaMatches = MatchesSchema(request.SchemaIds, schemaId, descriptor, binding);
|
||||
var keyMatches = request.RecordKeys == null ||
|
||||
request.RecordKeys.Length == 0 ||
|
||||
request.RecordKeys.Contains(key.Value, StringComparer.Ordinal);
|
||||
return schemaMatches && keyMatches;
|
||||
}
|
||||
|
||||
private static bool MatchesSchema(
|
||||
string[]? requestedSchemaIds,
|
||||
string schemaId,
|
||||
CultDocumentDescriptor? descriptor,
|
||||
CultNetDocumentBinding? binding)
|
||||
{
|
||||
if (requestedSchemaIds == null || requestedSchemaIds.Length == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var requested = requestedSchemaIds.ToHashSet(StringComparer.Ordinal);
|
||||
if (requested.Contains(schemaId))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (descriptor == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (requested.Contains(descriptor.SchemaId) ||
|
||||
requested.Contains(descriptor.SchemaName) ||
|
||||
requested.Contains(descriptor.SchemaVersion) ||
|
||||
(binding != null && requested.Contains(binding.SchemaId)))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (descriptor.ToCatalogEntry().CompatibleSchemaIds.Any(requested.Contains))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return requested
|
||||
.Select(InferSchemaName)
|
||||
.Where(schemaName => !string.IsNullOrWhiteSpace(schemaName))
|
||||
.Any(schemaName => string.Equals(schemaName, descriptor.SchemaName, StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
private static string? InferSchemaName(string schemaVersion)
|
||||
{
|
||||
var marker = schemaVersion.LastIndexOf(".v", StringComparison.Ordinal);
|
||||
if (marker <= 0 || marker + 2 >= schemaVersion.Length)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var version = schemaVersion.Substring(marker + 2);
|
||||
return version.All(char.IsDigit)
|
||||
? schemaVersion.Substring(0, marker)
|
||||
: null;
|
||||
}
|
||||
|
||||
private static string SubscriptionKey(NetPeer peer, string subscriptionId)
|
||||
{
|
||||
return $"{peer.Id}:{subscriptionId}";
|
||||
|
|
|
|||
|
|
@ -4039,6 +4039,57 @@ namespace GameCult.Networking.Tests
|
|||
Assert.That(message.Document!.Payload, Is.EqualTo(SerializePlayerDataPayload(player)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CultNetDatabaseServer_Creates_Filtered_SubscriptionChange_ForSchemaAlias()
|
||||
{
|
||||
var cache = new CultCache();
|
||||
var registry = new CultNetDocumentRegistry(cache.Registry)
|
||||
.Register(CultNetDocumentBinding.ForDocument<NetworkSchemaNote>(cache.Registry));
|
||||
var database = new CultNetDatabase(cache, new CultNetDatabaseOptions
|
||||
{
|
||||
DocumentRegistry = registry
|
||||
});
|
||||
using var server = new Server(cache, DevelopmentServerSecurity);
|
||||
using var databaseServer = new CultNetDatabaseServer(server, database);
|
||||
var key = new CultRecordKey("network-note:alias-change");
|
||||
var note = new NetworkSchemaNote
|
||||
{
|
||||
Schema = "tests.networking_note.v1",
|
||||
Text = "alias change",
|
||||
Revision = 11
|
||||
};
|
||||
var descriptor = cache.Registry.GetRequired<NetworkSchemaNote>();
|
||||
var change = new CultNetDatabaseChange<NetworkSchemaNote>(
|
||||
CultNetDatabaseChangeKind.Added,
|
||||
key,
|
||||
descriptor.SchemaId,
|
||||
database.Shards[0],
|
||||
note,
|
||||
previousDocument: null);
|
||||
var method = typeof(CultNetDatabaseServer).GetMethod(
|
||||
"CreateChangeMessage",
|
||||
BindingFlags.Instance | BindingFlags.NonPublic)!;
|
||||
|
||||
var message = (CultNetDatabaseChangeRawMessage?)method.Invoke(databaseServer, new object[]
|
||||
{
|
||||
change,
|
||||
"sub-alias",
|
||||
new CultNetDatabaseSubscribeMessage
|
||||
{
|
||||
SubscriptionId = "sub-alias",
|
||||
SchemaIds = ["tests.networking_note.v1"],
|
||||
RecordKeys = [key.Value]
|
||||
}
|
||||
});
|
||||
|
||||
Assert.That(message, Is.Not.Null);
|
||||
Assert.That(message!.SubscriptionId, Is.EqualTo("sub-alias"));
|
||||
Assert.That(message.ChangeKind, Is.EqualTo("added"));
|
||||
Assert.That(message.Document, Is.Not.Null);
|
||||
Assert.That(message.Document!.SchemaId, Is.EqualTo(descriptor.SchemaId));
|
||||
Assert.That(message.Document.Payload, Is.EqualTo(CultDocumentMessagePackSerialization.Serialize(note)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CultNetSchemaRegistry_BuiltInCatalog_AdvertisesRawLane_AndSharedGhostlightContract()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in a new issue