Define explicit Eve presentation finality
This commit is contained in:
parent
7f9b5f63ed
commit
f7c79ee784
10 changed files with 72 additions and 14 deletions
|
|
@ -13,7 +13,14 @@ export interface EveCommandReceipt {
|
|||
[k: string]: any;
|
||||
}[];
|
||||
issuedAtUtc?: string;
|
||||
/**
|
||||
* Provider-state generation that causally owns this result. It is not implicitly an Eve surface version.
|
||||
*/
|
||||
sourceVersion: number;
|
||||
/**
|
||||
* Optional advertised base-surface version that a renderer must mount before exposing terminal presentation finality.
|
||||
*/
|
||||
presentationSurfaceVersion?: number;
|
||||
/**
|
||||
* Canonical digest of the immutable invocation envelope finalized by this receipt.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -640,6 +640,12 @@ export declare const eveContractSchemas: {
|
|||
readonly sourceVersion: {
|
||||
readonly type: "integer";
|
||||
readonly minimum: 0;
|
||||
readonly description: "Provider-state generation that causally owns this result. It is not implicitly an Eve surface version.";
|
||||
};
|
||||
readonly presentationSurfaceVersion: {
|
||||
readonly type: "integer";
|
||||
readonly minimum: 1;
|
||||
readonly description: "Optional advertised base-surface version that a renderer must mount before exposing terminal presentation finality.";
|
||||
};
|
||||
readonly invocationHash: {
|
||||
readonly type: "string";
|
||||
|
|
|
|||
|
|
@ -767,7 +767,13 @@ export const eveContractSchemas = {
|
|||
},
|
||||
"sourceVersion": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
"minimum": 0,
|
||||
"description": "Provider-state generation that causally owns this result. It is not implicitly an Eve surface version."
|
||||
},
|
||||
"presentationSurfaceVersion": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "Optional advertised base-surface version that a renderer must mount before exposing terminal presentation finality."
|
||||
},
|
||||
"invocationHash": {
|
||||
"type": "string",
|
||||
|
|
|
|||
|
|
@ -15,7 +15,14 @@ diagnostics?: {
|
|||
[k: string]: any
|
||||
}[]
|
||||
issuedAtUtc?: string
|
||||
/**
|
||||
* Provider-state generation that causally owns this result. It is not implicitly an Eve surface version.
|
||||
*/
|
||||
sourceVersion: number
|
||||
/**
|
||||
* Optional advertised base-surface version that a renderer must mount before exposing terminal presentation finality.
|
||||
*/
|
||||
presentationSurfaceVersion?: number
|
||||
/**
|
||||
* Canonical digest of the immutable invocation envelope finalized by this receipt.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -767,7 +767,13 @@ export const eveContractSchemas = {
|
|||
},
|
||||
"sourceVersion": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
"minimum": 0,
|
||||
"description": "Provider-state generation that causally owns this result. It is not implicitly an Eve surface version."
|
||||
},
|
||||
"presentationSurfaceVersion": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "Optional advertised base-surface version that a renderer must mount before exposing terminal presentation finality."
|
||||
},
|
||||
"invocationHash": {
|
||||
"type": "string",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Description>Portable Eve surface and provider contracts.</Description>
|
||||
<PackageId>GameCult.Eve.Surface</PackageId>
|
||||
<Version>0.3.5</Version>
|
||||
<Version>0.3.6</Version>
|
||||
<Authors>GameCult</Authors>
|
||||
<PackageLicenseExpression>MPL-2.0</PackageLicenseExpression>
|
||||
<PackageProjectUrl>https://github.com/GameCult/Eve</PackageProjectUrl>
|
||||
|
|
|
|||
|
|
@ -367,8 +367,9 @@ namespace GameCult.Eve.Surface
|
|||
string issuedAtUtc,
|
||||
long sourceVersion,
|
||||
EveSurfaceNavigationTarget? navigation = null,
|
||||
string invocationHash = "")
|
||||
: this(SchemaId, receiptId, commandId, command, state, ownerRepo, authority, providerId, surfaceId, message, issuedAtUtc, sourceVersion, navigation, invocationHash)
|
||||
string invocationHash = "",
|
||||
long presentationSurfaceVersion = 0)
|
||||
: this(SchemaId, receiptId, commandId, command, state, ownerRepo, authority, providerId, surfaceId, message, issuedAtUtc, sourceVersion, navigation, invocationHash, presentationSurfaceVersion)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -387,7 +388,8 @@ namespace GameCult.Eve.Surface
|
|||
string issuedAtUtc,
|
||||
long sourceVersion,
|
||||
EveSurfaceNavigationTarget? navigation = null,
|
||||
string invocationHash = "")
|
||||
string invocationHash = "",
|
||||
long presentationSurfaceVersion = 0)
|
||||
{
|
||||
Schema = string.IsNullOrWhiteSpace(schema) ? SchemaId : schema;
|
||||
ReceiptId = receiptId ?? "";
|
||||
|
|
@ -403,6 +405,7 @@ namespace GameCult.Eve.Surface
|
|||
SourceVersion = sourceVersion;
|
||||
Navigation = navigation;
|
||||
InvocationHash = invocationHash ?? "";
|
||||
PresentationSurfaceVersion = presentationSurfaceVersion;
|
||||
}
|
||||
|
||||
[Key(0)] public string Schema { get; }
|
||||
|
|
@ -419,6 +422,7 @@ namespace GameCult.Eve.Surface
|
|||
[Key(11)] public long SourceVersion { get; }
|
||||
[Key(12)] public EveSurfaceNavigationTarget? Navigation { get; }
|
||||
[Key(13)] public string InvocationHash { get; }
|
||||
[Key(14)] public long PresentationSurfaceVersion { get; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -428,7 +432,7 @@ namespace GameCult.Eve.Surface
|
|||
public sealed class EveCommandReceiptCompatibilityFormatter :
|
||||
IMessagePackFormatter<EveCommandReceiptDocument?>
|
||||
{
|
||||
private const int LegacyFieldCount = 14;
|
||||
private const int LegacyFieldCount = 15;
|
||||
private const int RequiredAndScalarFieldCount = 12;
|
||||
|
||||
public void Serialize(
|
||||
|
|
@ -439,7 +443,8 @@ namespace GameCult.Eve.Surface
|
|||
if (value == null) { writer.WriteNil(); return; }
|
||||
|
||||
var optionalFields = (value.Navigation == null ? 0 : 1) +
|
||||
(string.IsNullOrWhiteSpace(value.InvocationHash) ? 0 : 1);
|
||||
(string.IsNullOrWhiteSpace(value.InvocationHash) ? 0 : 1) +
|
||||
(value.PresentationSurfaceVersion <= 0 ? 0 : 1);
|
||||
writer.WriteMapHeader(RequiredAndScalarFieldCount + optionalFields);
|
||||
Write(ref writer, "schema", value.Schema);
|
||||
Write(ref writer, "receiptId", value.ReceiptId);
|
||||
|
|
@ -460,6 +465,11 @@ namespace GameCult.Eve.Surface
|
|||
}
|
||||
if (!string.IsNullOrWhiteSpace(value.InvocationHash))
|
||||
Write(ref writer, "invocationHash", value.InvocationHash);
|
||||
if (value.PresentationSurfaceVersion > 0)
|
||||
{
|
||||
writer.Write("presentationSurfaceVersion");
|
||||
writer.Write(value.PresentationSurfaceVersion);
|
||||
}
|
||||
}
|
||||
|
||||
public EveCommandReceiptDocument? Deserialize(
|
||||
|
|
@ -490,10 +500,12 @@ namespace GameCult.Eve.Surface
|
|||
var sourceVersion = fields > 11 ? reader.ReadInt64() : 0;
|
||||
var navigation = fields > 12 ? ReadNavigation(ref reader, options) : null;
|
||||
var invocationHash = ReadString(ref reader, fields, 13);
|
||||
var presentationSurfaceVersion = fields > 14 ? reader.ReadInt64() : 0;
|
||||
for (var index = LegacyFieldCount; index < fields; index++) reader.Skip();
|
||||
return new EveCommandReceiptDocument(
|
||||
schema, receiptId, commandId, command, state, ownerRepo, authority,
|
||||
providerId, surfaceId, message, issuedAtUtc, sourceVersion, navigation, invocationHash);
|
||||
providerId, surfaceId, message, issuedAtUtc, sourceVersion, navigation, invocationHash,
|
||||
presentationSurfaceVersion);
|
||||
}
|
||||
finally { reader.Depth--; }
|
||||
}
|
||||
|
|
@ -519,6 +531,7 @@ namespace GameCult.Eve.Surface
|
|||
long sourceVersion = 0;
|
||||
EveSurfaceNavigationTarget? navigation = null;
|
||||
var invocationHash = "";
|
||||
long presentationSurfaceVersion = 0;
|
||||
var fields = reader.ReadMapHeader();
|
||||
for (var index = 0; index < fields; index++)
|
||||
{
|
||||
|
|
@ -538,13 +551,15 @@ namespace GameCult.Eve.Surface
|
|||
case "sourceVersion": sourceVersion = reader.ReadInt64(); break;
|
||||
case "navigation": navigation = ReadNavigation(ref reader, options); break;
|
||||
case "invocationHash": invocationHash = ReadString(ref reader); break;
|
||||
case "presentationSurfaceVersion": presentationSurfaceVersion = reader.ReadInt64(); break;
|
||||
default: reader.Skip(); break;
|
||||
}
|
||||
}
|
||||
|
||||
return new EveCommandReceiptDocument(
|
||||
schema, receiptId, commandId, command, state, ownerRepo, authority,
|
||||
providerId, surfaceId, message, issuedAtUtc, sourceVersion, navigation, invocationHash);
|
||||
providerId, surfaceId, message, issuedAtUtc, sourceVersion, navigation, invocationHash,
|
||||
presentationSurfaceVersion);
|
||||
}
|
||||
finally { reader.Depth--; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "org.gamecult.eve.surface",
|
||||
"displayName": "Eve Surface Contract",
|
||||
"version": "0.3.5",
|
||||
"version": "0.3.6",
|
||||
"unity": "2021.3",
|
||||
"description": "Renderer-neutral C# contracts and builders for gamecult.eve.surface.v1 documents.",
|
||||
"dependencies": {
|
||||
|
|
|
|||
|
|
@ -67,7 +67,13 @@
|
|||
},
|
||||
"sourceVersion": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
"minimum": 0,
|
||||
"description": "Provider-state generation that causally owns this result. It is not implicitly an Eve surface version."
|
||||
},
|
||||
"presentationSurfaceVersion": {
|
||||
"type": "integer",
|
||||
"minimum": 1,
|
||||
"description": "Optional advertised base-surface version that a renderer must mount before exposing terminal presentation finality."
|
||||
},
|
||||
"invocationHash": {
|
||||
"type": "string",
|
||||
|
|
|
|||
|
|
@ -266,7 +266,8 @@ public sealed class EveSurfaceSerializationCompatibilityTests
|
|||
"interactive-world",
|
||||
new[] { "cultnet+tcp://odin.gamecult.example:3076" },
|
||||
"commander-daemon"),
|
||||
"sha256:launch-envelope");
|
||||
"sha256:launch-envelope",
|
||||
presentationSurfaceVersion: 77);
|
||||
|
||||
var bytes = MessagePackSerializer.Serialize(document, Options);
|
||||
var reader = new MessagePackReader(bytes);
|
||||
|
|
@ -274,7 +275,7 @@ public sealed class EveSurfaceSerializationCompatibilityTests
|
|||
var restored = MessagePackSerializer.Deserialize<EveCommandReceiptDocument>(bytes, Options);
|
||||
|
||||
Assert.That(reader.NextMessagePackType, Is.EqualTo(MessagePackType.Map));
|
||||
Assert.That(reader.ReadMapHeader(), Is.EqualTo(14));
|
||||
Assert.That(reader.ReadMapHeader(), Is.EqualTo(15));
|
||||
Assert.That(wireJson.RootElement.GetProperty("navigation").ValueKind, Is.EqualTo(JsonValueKind.Object));
|
||||
Assert.That(restored.Navigation, Is.Not.Null);
|
||||
Assert.That(restored.Navigation!.VerseId, Is.EqualTo("gamecult.aetheria"));
|
||||
|
|
@ -283,6 +284,7 @@ public sealed class EveSurfaceSerializationCompatibilityTests
|
|||
Assert.That(restored.Navigation.SurfaceKind, Is.EqualTo("interactive-world"));
|
||||
Assert.That(restored.Navigation.RendezvousEndpoints, Is.EqualTo(new[] { "cultnet+tcp://odin.gamecult.example:3076" }));
|
||||
Assert.That(restored.InvocationHash, Is.EqualTo("sha256:launch-envelope"));
|
||||
Assert.That(restored.PresentationSurfaceVersion, Is.EqualTo(77));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
|
@ -322,6 +324,7 @@ public sealed class EveSurfaceSerializationCompatibilityTests
|
|||
Assert.That(restored.Navigation!.SurfaceId, Is.EqualTo("aetheria.pilot"));
|
||||
Assert.That(restored.Navigation.AuthorityRuntimeId, Is.Empty);
|
||||
Assert.That(restored.InvocationHash, Is.Empty);
|
||||
Assert.That(restored.PresentationSurfaceVersion, Is.Zero);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -349,8 +352,10 @@ public sealed class EveSurfaceSerializationCompatibilityTests
|
|||
{
|
||||
Assert.That(wireJson.RootElement.TryGetProperty("navigation", out _), Is.False);
|
||||
Assert.That(wireJson.RootElement.TryGetProperty("invocationHash", out _), Is.False);
|
||||
Assert.That(wireJson.RootElement.TryGetProperty("presentationSurfaceVersion", out _), Is.False);
|
||||
Assert.That(restored.Navigation, Is.Null);
|
||||
Assert.That(restored.InvocationHash, Is.Empty);
|
||||
Assert.That(restored.PresentationSurfaceVersion, Is.Zero);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue