Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate to new sync error codes #3440

Merged
merged 9 commits into from
Sep 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we get a compensating write instead?

/// 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