Skip to content

Commit

Permalink
Migrate to new sync error codes (#3440)
Browse files Browse the repository at this point in the history
  • Loading branch information
nirinchev authored Sep 15, 2023
1 parent 1efc569 commit 11ab212
Show file tree
Hide file tree
Showing 16 changed files with 261 additions and 214 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy-baas.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
apiKey: ${{ secrets.AtlasPublicKey}}
privateApiKey: ${{ secrets.AtlasPrivateKey }}
clusterName: ${{ steps.generate-cluster-name.outputs.clusterName }}-${{ matrix.differentiator }}
clusterSize: M20
clusterSize: M5
deploy-apps:
name: Deploy Apps
needs: deploy-baas
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
## vNext (TBD)

### Enhancements
* None
* Streamlined some of the error codes reported in `SessionException`. A few error codes have been combined and some have been deprecated since they are no longer reported by the server. (Issue [#3295](https://github.com/realm/realm-dotnet/issues/3295))

### Fixed
* Fixed the message of the `MissingMemberException` being thrown when attempting to access a non-existent property with the dynamic API. (PR [#3432](https://github.com/realm/realm-dotnet/pull/3432))
Expand Down
6 changes: 0 additions & 6 deletions Realm/Realm/Exceptions/Sync/ClientError.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,6 @@ internal enum ClientError
AutoClientResetFailed = 132,
}

internal enum SessionErrorCategory : byte
{
ClientError = 0,
SessionError = 1
}

internal enum ServerRequestsAction
{
NoAction = 0,
Expand Down
314 changes: 195 additions & 119 deletions Realm/Realm/Exceptions/Sync/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,125 +16,201 @@
//
////////////////////////////////////////////////////////////////////////////

namespace Realms.Sync.Exceptions
using System;
using Realms.Sync.ErrorHandling;
using static System.Net.WebRequestMethods;

namespace Realms.Sync.Exceptions;

/// <summary>
/// Error code enumeration, indicating the type of the session error.
/// </summary>
/// <seealso cref="SessionException"/>
public enum ErrorCode
{
/// <summary>
/// Error code enumeration, indicating the type of the session error.
/// </summary>
/// <seealso cref="SessionException"/>
public enum ErrorCode
{
/// <summary>
/// Unrecognized error code. It usually indicates incompatibility between the authentication server and client SDK versions.
/// </summary>
Unknown = -1,

/// <summary>
/// Other session level error has occurred.
/// </summary>
OtherSessionError = 201,

/// <summary>
/// Path to Realm is invalid.
/// </summary>
IllegalRealmPath = 204,

/// <summary>
/// Permission to Realm has been denied.
/// </summary>
PermissionDenied = 206,

/// <summary>
/// The client file identifier is invalid.
/// </summary>
BadClientFileIdentifier = 208,

/// <summary>
/// The server version is invalid.
/// </summary>
BadServerVersion = 209,

/// <summary>
/// The client version is invalid.
/// </summary>
BadClientVersion = 210,

/// <summary>
/// Histories have diverged and cannot be merged.
/// </summary>
DivergingHistories = 211,

/// <summary>
/// The changeset is invalid.
/// </summary>
BadChangeset = 212,

/// <summary>
/// The client file is invalid.
/// </summary>
BadClientFile = 217,

/// <summary>
/// Client file has expired likely due to history compaction on the server.
/// </summary>
ClientFileExpired = 222,

/// <summary>
/// The user for this session doesn't match the user who originally created the file. This can happen
/// if you explicitly specify the Realm file path in the configuration and you open the Realm first with
/// user A, then with user B without changing the on-disk path.
/// </summary>
UserMismatch = 223,

/// <summary>
/// The server has received too many sessions from this client. This is typically a transient error
/// but can also indicate that the client has too many Realms open at the same time.
/// </summary>
TooManySessions = 224,

/// <summary>
/// The client attempted to upload an invalid schema change - either an additive schema change
/// when developer mode is <c>off</c> or a destructive schema change.
/// </summary>
InvalidSchemaChange = 225,

/// <summary>
/// The client attempted to create a subscription for a query is invalid/malformed.
/// </summary>
BadQuery = 226,

/// <summary>
/// The client attempted to create an object that already exists outside their view.
/// </summary>
ObjectAlreadyExists = 227,

/// <summary>
/// The server permissions for this file have changed since the last time it was used.
/// </summary>
ServerPermissionsChanged = 228,

/// <summary>
/// The client tried to synchronize before initial sync has completed. Please wait for
/// the server process to complete and try again.
/// </summary>
InitialSyncNotCompleted = 229,

/// <summary>
/// Client attempted a write that is disallowed by permissions, or modifies an object
/// outside the current query - requires client reset.
/// </summary>
WriteNotAllowed = 230,

/// <summary>
/// Client attempted a write that is disallowed by permissions, or modifies an
/// object outside the current query, and the server undid the modification.
/// </summary>
CompensatingWrite = 231,

/// <summary>
/// An error sent by the server when its data structures used to track client progress
/// become corrupted.
/// </summary>
BadProgress = 233,
}
/// Unrecognized error code. It usually indicates incompatibility between the App Services server and client SDK versions.
/// </summary>
RuntimeError = 1000,

/// <summary>
/// The partition value specified by the user is not valid - i.e. its the wrong type or is encoded incorrectly.
/// </summary>
BadPartitionValue = 1029,

/// <summary>
/// A fundamental invariant in the communication between the client and the server was not upheld. This typically indicates
/// a bug in the synchronization layer and should be reported at https://github.com/realm/realm-core/issues.
/// </summary>
ProtocolInvariantFailed = 1038,

/// <summary>
/// The changeset is invalid.
/// </summary>
BadChangeset = 1015,

/// <summary>
/// The client attempted to create a subscription for a query is invalid/malformed.
/// </summary>
BadQuery = 1031,

/// <summary>
/// A client reset has occurred. This error code will only be reported via a <see cref="ClientResetException"/> and only
/// in the case manual client reset handling is required - either via <see cref="ManualRecoveryHandler"/> or when
/// <c>ManualResetFallback</c> is invoked on one of the automatic client reset handlers.
/// </summary>
/// <seealso cref="SyncConfigurationBase.ClientResetHandler"/>
/// <seealso href="https://docs.mongodb.com/realm/sdk/dotnet/advanced-guides/client-reset"/>
ClientReset = 1032,

/// <summary>
/// The client attempted to upload an invalid schema change - either an additive schema change
/// when developer mode is <c>off</c> or a destructive schema change.
/// </summary>
InvalidSchemaChange = 1036,

/// <summary>
/// Permission to Realm has been denied.
/// </summary>
PermissionDenied = 1037,

/// <summary>
/// The server permissions for this file have changed since the last time it was used.
/// </summary>
ServerPermissionsChanged = 1040,

/// <summary>
/// The user for this session doesn't match the user who originally created the file. This can happen
/// if you explicitly specify the Realm file path in the configuration and you open the Realm first with
/// user A, then with user B without changing the on-disk path.
/// </summary>
UserMismatch = 1041,

/// <summary>
/// Client attempted a write that is disallowed by permissions, or modifies an object
/// outside the current query - this will result in a <see cref="CompensatingWriteException"/>.
/// </summary>
WriteNotAllowed = 1044,

/// <summary>
/// Automatic client reset has failed. This will only be reported via <see cref="ClientResetException"/>
/// when an automatic client reset handler was used but it failed to perform the client reset operation -
/// typically due to a breaking schema change in the server schema or due to an exception occurring in the
/// before or after client reset callbacks.
/// </summary>
AutoClientResetFailed = 1028,

/// <summary>
/// The wrong sync type was used to connect to the server. This means that you're using <see cref="PartitionSyncConfiguration"/>
/// to connect to an app configured for flexible sync or that you're using <see cref="FlexibleSyncConfiguration"/> to connect
/// to an app configured to use partition sync.
/// </summary>
WrongSyncType = 1043,

/// <summary>
/// Unrecognized error code. It usually indicates incompatibility between the App Services server and client SDK versions.
/// </summary>
[Obsolete("Use RuntimeError instead.")]
Unknown = RuntimeError,

/// <summary>
/// Other session level error has occurred.
/// </summary>
/// <remarks>
/// Sync error reporting has been simplified and some errors have been unified. See the obsoletion message for details on the new error code.
/// </remarks>
[Obsolete("Use RuntimeError instead.")]
OtherSessionError = RuntimeError,

/// <summary>
/// Path to Realm is invalid.
/// </summary>
/// <remarks>
/// Sync error reporting has been simplified and some errors have been unified. See the obsoletion message for details on the new error code.
/// </remarks>
[Obsolete("Use BadPartitionValue instead")]
IllegalRealmPath = BadPartitionValue,

/// <summary>
/// The client file identifier is invalid.
/// </summary>
/// <seealso cref="ClientResetException"/>
[Obsolete("Use ClientReset instead")]
BadClientFileIdentifier = ClientReset,

/// <summary>
/// The server version is invalid.
/// </summary>
/// <remarks>
/// Sync error reporting has been simplified and some errors have been unified. See the obsoletion message for details on the new error code.
/// </remarks>
[Obsolete("Use ProtocolInvariantFailed instead")]
BadServerVersion = ProtocolInvariantFailed,

/// <summary>
/// The client version is invalid.
/// </summary>
/// <remarks>
/// Sync error reporting has been simplified and some errors have been unified. See the obsoletion message for details on the new error code.
/// </remarks>
[Obsolete("Use ProtocolInvariantFailed instead")]
BadClientVersion = ProtocolInvariantFailed,

/// <summary>
/// Histories have diverged and cannot be merged.
/// </summary>
/// <seealso cref="ClientResetException"/>
[Obsolete("Use ClientReset instead")]
DivergingHistories = ClientReset,

/// <summary>
/// The client file is invalid.
/// </summary>
/// <seealso cref="ClientResetException"/>
[Obsolete("Use ClientReset instead")]
BadClientFile = ClientReset,

/// <summary>
/// Client file has expired likely due to history compaction on the server.
/// </summary>
/// <seealso cref="ClientResetException"/>
[Obsolete("Use ClientReset instead")]
ClientFileExpired = ClientReset,

/// <summary>
/// The server has received too many sessions from this client. This is typically a transient error
/// but can also indicate that the client has too many Realms open at the same time.
/// </summary>
[Obsolete("This error code is no longer reported")]
TooManySessions = -2,

/// <summary>
/// The client attempted to create an object that already exists outside their view.
/// </summary>
[Obsolete("This error code is no longer reported")]
ObjectAlreadyExists = -3,

/// <summary>
/// The client tried to synchronize before initial sync has completed. Please wait for
/// the server process to complete and try again.
/// </summary>
[Obsolete("This error code is no longer reported")]
InitialSyncNotCompleted = -4,

/// <summary>
/// Client attempted a write that is disallowed by permissions, or modifies an
/// object outside the current query, and the server undid the modification.
/// </summary>
/// <seealso cref="CompensatingWriteException"/>
CompensatingWrite = 1033,

/// <summary>
/// An error sent by the server when its data structures used to track client progress
/// become corrupted.
/// </summary>
/// <remarks>
/// Sync error reporting has been simplified and some errors have been unified. See the obsoletion message for details on the new error code.
/// </remarks>
[Obsolete("Use ProtocolInvariantFailed instead")]
BadProgress = ProtocolInvariantFailed,
}
2 changes: 1 addition & 1 deletion Realm/Realm/Extensions/TestingExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public static void SimulateError(this Session session, ErrorCode errorCode, stri
Argument.NotNull(session, nameof(session));
Argument.NotNull(message, nameof(message));

session.ReportErrorForTesting((int)errorCode, SessionErrorCategory.SessionError, message, isFatal, ServerRequestsAction.ApplicationBug);
session.ReportErrorForTesting((int)errorCode, message, isFatal, ServerRequestsAction.ApplicationBug);
}
}
}
6 changes: 3 additions & 3 deletions Realm/Realm/Handles/SessionHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ public static extern ulong register_progress_notifier(SessionHandle session,
public static extern void wait(SessionHandle session, IntPtr task_completion_source, ProgressDirection direction, out NativeException ex);

[DllImport(InteropConfig.DLL_NAME, EntryPoint = "realm_syncsession_report_error_for_testing", CallingConvention = CallingConvention.Cdecl)]
public static extern void report_error_for_testing(SessionHandle session, int error_code, SessionErrorCategory error_category, [MarshalAs(UnmanagedType.LPWStr)] string message, IntPtr message_len, [MarshalAs(UnmanagedType.U1)] bool is_fatal, int action);
public static extern void report_error_for_testing(SessionHandle session, int error_code, [MarshalAs(UnmanagedType.LPWStr)] string message, IntPtr message_len, [MarshalAs(UnmanagedType.U1)] bool is_fatal, int action);

[DllImport(InteropConfig.DLL_NAME, EntryPoint = "realm_syncsession_stop", CallingConvention = CallingConvention.Cdecl)]
public static extern void stop(SessionHandle session, out NativeException ex);
Expand Down Expand Up @@ -246,9 +246,9 @@ public IntPtr GetRawPointer()
return NativeMethods.get_raw_pointer(this);
}

public void ReportErrorForTesting(int errorCode, SessionErrorCategory errorCategory, string errorMessage, bool isFatal, ServerRequestsAction action)
public void ReportErrorForTesting(int errorCode, string errorMessage, bool isFatal, ServerRequestsAction action)
{
NativeMethods.report_error_for_testing(this, errorCode, errorCategory, errorMessage, (IntPtr)errorMessage.Length, isFatal, (int)action);
NativeMethods.report_error_for_testing(this, errorCode, errorMessage, (IntPtr)errorMessage.Length, isFatal, (int)action);
}

public void Stop()
Expand Down
3 changes: 2 additions & 1 deletion Realm/Realm/Sync/Session.cs
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,8 @@ internal void CloseHandle(bool waitForShutdown = false)
}
}

internal void ReportErrorForTesting(int errorCode, SessionErrorCategory sessionErrorCategory, string errorMessage, bool isFatal, ServerRequestsAction action) => Handle.ReportErrorForTesting(errorCode, sessionErrorCategory, errorMessage, isFatal, action);
internal void ReportErrorForTesting(int errorCode, string errorMessage, bool isFatal, ServerRequestsAction action)
=> Handle.ReportErrorForTesting(errorCode, errorMessage, isFatal, action);

internal void RaisePropertyChanged(string propertyName)
{
Expand Down
Loading

0 comments on commit 11ab212

Please sign in to comment.