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