From e6215f4ff6ccc8bc00bb6714c59434be97a4803e Mon Sep 17 00:00:00 2001 From: Alex Yakunin Date: Tue, 10 Dec 2024 04:34:21 -0800 Subject: [PATCH] feat: MessagePack v3 upgrade (wip) --- Directory.Packages.props | 2 +- samples/HelloCart/Abstractions.cs | 3 ++- samples/TodoApp/UI/Pages/AuthenticationPage.razor | 2 +- src/ActualLab.Core/Time/Moment.cs | 6 ++++-- src/ActualLab.Core/Time/RetryDelaySeq.cs | 2 +- .../Authentication/IAuth.cs | 3 ++- .../Authentication/SessionAuthInfo.cs | 7 ++++--- .../Authentication/SessionInfo.cs | 14 +++++++++++--- src/ActualLab.Rpc/Infrastructure/RpcHeaderKey.cs | 1 + 9 files changed, 27 insertions(+), 13 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index d63a44c8e..3a1712c7e 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -58,7 +58,7 @@ [13.0.3,) [1.21.3,) - [2.5.192,) + [3.0.308,) [2.8.16,) [1.6.4,) diff --git a/samples/HelloCart/Abstractions.cs b/samples/HelloCart/Abstractions.cs index 9b8ebb37c..a0da2aa19 100644 --- a/samples/HelloCart/Abstractions.cs +++ b/samples/HelloCart/Abstractions.cs @@ -21,7 +21,8 @@ public partial record Cart( [property: DataMember, Key(0)] string Id ) : IHasId { - [DataMember] public ImmutableDictionary Items { get; init; } = ImmutableDictionary.Empty; + [DataMember, Key(1)] + public ImmutableDictionary Items { get; init; } = ImmutableDictionary.Empty; } [DataContract, MemoryPackable, MessagePackObject] diff --git a/samples/TodoApp/UI/Pages/AuthenticationPage.razor b/samples/TodoApp/UI/Pages/AuthenticationPage.razor index 2081e13a5..8c4182f54 100644 --- a/samples/TodoApp/UI/Pages/AuthenticationPage.razor +++ b/samples/TodoApp/UI/Pages/AuthenticationPage.razor @@ -164,7 +164,7 @@ var userAgent = UserAgentCache.GetOrAdd(sessionInfo.UserAgent, static ua => Parser.ParseUserAgent(ua)); var model = new SessionInfoModel() { SessionHash = sessionInfo.SessionHash, - IsCurrent = sessionInfo.SessionHash == Session.Hash, + IsCurrent = Equals(sessionInfo.SessionHash, Session.Hash), IPAddress = sessionInfo.IPAddress, UserAgent = $"{userAgent.Family} {userAgent.Major}.{userAgent.Minor}", Created = await FusionTime.GetMomentsAgo(sessionInfo.CreatedAt), diff --git a/src/ActualLab.Core/Time/Moment.cs b/src/ActualLab.Core/Time/Moment.cs index c78320d56..0ab6d4cf0 100644 --- a/src/ActualLab.Core/Time/Moment.cs +++ b/src/ActualLab.Core/Time/Moment.cs @@ -1,12 +1,13 @@ using System.ComponentModel; using System.Globalization; using ActualLab.Time.Internal; +using MessagePack; namespace ActualLab.Time; [StructLayout(LayoutKind.Sequential, Pack = 8)] // Important! // [StructLayout(LayoutKind.Auto)] -[DataContract] +[DataContract, MessagePackObject] [JsonConverter(typeof(MomentJsonConverter))] [Newtonsoft.Json.JsonConverter(typeof(MomentNewtonsoftJsonConverter))] [TypeConverter(typeof(MomentTypeConverter))] @@ -28,9 +29,10 @@ public static Moment CpuNow { } // AKA Unix Time - [DataMember(Order = 0)] + [DataMember(Order = 0), Key(0)] public readonly long EpochOffsetTicks = epochOffsetTicks; + [IgnoreDataMember, MemoryPackIgnore, IgnoreMember] public TimeSpan EpochOffset { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(EpochOffsetTicks); diff --git a/src/ActualLab.Core/Time/RetryDelaySeq.cs b/src/ActualLab.Core/Time/RetryDelaySeq.cs index 894cbdcfa..73437b574 100644 --- a/src/ActualLab.Core/Time/RetryDelaySeq.cs +++ b/src/ActualLab.Core/Time/RetryDelaySeq.cs @@ -2,7 +2,7 @@ namespace ActualLab.Time; -[DataContract, MemoryPackable(GenerateType.VersionTolerant), MessagePackObject] +[DataContract, MemoryPackable(GenerateType.VersionTolerant), MessagePackObject(SuppressSourceGeneration = true)] public partial record RetryDelaySeq( [property: DataMember, MemoryPackOrder(0), Key(0)] TimeSpan Min, [property: DataMember, MemoryPackOrder(1), Key(1)] TimeSpan Max, diff --git a/src/ActualLab.Fusion.Ext.Contracts/Authentication/IAuth.cs b/src/ActualLab.Fusion.Ext.Contracts/Authentication/IAuth.cs index 9ab7e5ca6..071d7f1ca 100644 --- a/src/ActualLab.Fusion.Ext.Contracts/Authentication/IAuth.cs +++ b/src/ActualLab.Fusion.Ext.Contracts/Authentication/IAuth.cs @@ -44,7 +44,7 @@ public partial record Auth_EditUser( public partial record Auth_SignOut: ISessionCommand { [DataMember, MemoryPackOrder(0), Key(0)] - public Session Session { get; init; } = null!; + public Session Session { get; init; } [DataMember, MemoryPackOrder(1), Key(1)] public string? KickUserSessionHash { get; init; } [DataMember, MemoryPackOrder(2), Key(2)] @@ -65,6 +65,7 @@ public Auth_SignOut(Session session, string kickUserSessionHash, bool force = fa Force = force; } + // ReSharper disable once ConvertToPrimaryConstructor [JsonConstructor, Newtonsoft.Json.JsonConstructor, MemoryPackConstructor, SerializationConstructor] public Auth_SignOut( Session session, diff --git a/src/ActualLab.Fusion.Ext.Contracts/Authentication/SessionAuthInfo.cs b/src/ActualLab.Fusion.Ext.Contracts/Authentication/SessionAuthInfo.cs index b783c6cec..5e5895ab1 100644 --- a/src/ActualLab.Fusion.Ext.Contracts/Authentication/SessionAuthInfo.cs +++ b/src/ActualLab.Fusion.Ext.Contracts/Authentication/SessionAuthInfo.cs @@ -10,15 +10,16 @@ public partial record SessionAuthInfo : IRequirementTarget (SessionAuthInfo? i) => i?.IsAuthenticated() ?? false, new("Session is not authenticated.", m => new SecurityException(m))); - [DataMember(Order = 0), MemoryPackOrder(0), Key(0)] public string SessionHash { get; init; } = ""; + [DataMember(Order = 0), MemoryPackOrder(0), Key(0)] public string SessionHash { get => field ?? ""; init; } // Authentication [DataMember(Order = 1), MemoryPackOrder(1), Key(1)] public UserIdentity AuthenticatedIdentity { get; init; } - [DataMember(Order = 2), MemoryPackOrder(2), Key(2)] public Symbol UserId { get; init; } = Symbol.Empty; + [DataMember(Order = 2), MemoryPackOrder(2), Key(2)] public Symbol UserId { get; init; } [DataMember(Order = 3), MemoryPackOrder(3), Key(3)] public bool IsSignOutForced { get; init; } [JsonConstructor, Newtonsoft.Json.JsonConstructor, MemoryPackConstructor, SerializationConstructor] - public SessionAuthInfo() { } + public SessionAuthInfo() + => SessionHash = ""; public SessionAuthInfo(Session? session) => SessionHash = session?.Hash ?? ""; diff --git a/src/ActualLab.Fusion.Ext.Contracts/Authentication/SessionInfo.cs b/src/ActualLab.Fusion.Ext.Contracts/Authentication/SessionInfo.cs index ae92af2c8..fda6cb48c 100644 --- a/src/ActualLab.Fusion.Ext.Contracts/Authentication/SessionInfo.cs +++ b/src/ActualLab.Fusion.Ext.Contracts/Authentication/SessionInfo.cs @@ -14,17 +14,25 @@ public partial record SessionInfo : SessionAuthInfo, IHasVersion [DataMember(Order = 10), MemoryPackOrder(10), Key(10)] public long Version { get; init; } [DataMember(Order = 11), MemoryPackOrder(11), Key(11)] public Moment CreatedAt { get; init; } [DataMember(Order = 12), MemoryPackOrder(12), Key(12)] public Moment LastSeenAt { get; init; } - [DataMember(Order = 13), MemoryPackOrder(13), Key(13)] public string IPAddress { get; init; } = ""; - [DataMember(Order = 14), MemoryPackOrder(14), Key(14)] public string UserAgent { get; init; } = ""; + [DataMember(Order = 13), MemoryPackOrder(13), Key(13)] public string IPAddress { get => field ?? ""; init; } + [DataMember(Order = 14), MemoryPackOrder(14), Key(14)] public string UserAgent { get => field ?? ""; init; } [DataMember(Order = 15), MemoryPackOrder(15), Key(15)] public ImmutableOptionSet Options { get; init; } [JsonConstructor, Newtonsoft.Json.JsonConstructor, MemoryPackConstructor, SerializationConstructor] - public SessionInfo() { } + public SessionInfo() + { + IPAddress = ""; + UserAgent = ""; + } + public SessionInfo(Moment createdAt) : this(null, createdAt) { } + public SessionInfo(Session? session, Moment createdAt = default) : base(session) { CreatedAt = createdAt; LastSeenAt = createdAt; + IPAddress = ""; + UserAgent = ""; } public SessionAuthInfo ToAuthInfo() diff --git a/src/ActualLab.Rpc/Infrastructure/RpcHeaderKey.cs b/src/ActualLab.Rpc/Infrastructure/RpcHeaderKey.cs index ce5e5098d..815c8ff56 100644 --- a/src/ActualLab.Rpc/Infrastructure/RpcHeaderKey.cs +++ b/src/ActualLab.Rpc/Infrastructure/RpcHeaderKey.cs @@ -15,6 +15,7 @@ namespace ActualLab.Rpc.Infrastructure; [DataMember(Order = 0), MemoryPackOrder(0), Key(0)] public readonly ReadOnlyMemory Utf8Name; + [IgnoreDataMember, MemoryPackIgnore, IgnoreMember] public bool IsNone { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => Name.IsEmpty;