Skip to content

Commit

Permalink
Expose ReconnectBackoffOptions on SyncTimeoutOptions
Browse files Browse the repository at this point in the history
  • Loading branch information
fealebenpae committed Aug 21, 2024
1 parent 5ae28a6 commit 76ebe6b
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 28 deletions.
38 changes: 29 additions & 9 deletions Realm/Realm/Native/AppConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,34 @@

namespace Realms.Sync.Native
{
[StructLayout(LayoutKind.Sequential)]
internal struct ReconnectBackoffOptions

Check warning on line 25 in Realm/Realm/Native/AppConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (ubuntu-latest, linux-x64)

Check warning on line 25 in Realm/Realm/Native/AppConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (ubuntu-latest, linux-x64)

Check warning on line 25 in Realm/Realm/Native/AppConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (ubuntu-latest, linux-x64)

Check warning on line 25 in Realm/Realm/Native/AppConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (ubuntu-latest, linux-x64)

Check warning on line 25 in Realm/Realm/Native/AppConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (macos-14, osx-arm64)

Check warning on line 25 in Realm/Realm/Native/AppConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (macos-14, osx-arm64)

Check warning on line 25 in Realm/Realm/Native/AppConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (macos-14, osx-arm64)

Check warning on line 25 in Realm/Realm/Native/AppConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (macos-14, osx-arm64)

Check warning on line 25 in Realm/Realm/Native/AppConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test Source Generation

Check warning on line 25 in Realm/Realm/Native/AppConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (windows-latest, win-x64)

Check warning on line 25 in Realm/Realm/Native/AppConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (windows-latest, win-x64)

Check warning on line 25 in Realm/Realm/Native/AppConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (windows-latest, win-x64)

Check warning on line 25 in Realm/Realm/Native/AppConfiguration.cs

View workflow job for this annotation

GitHub Actions / Test Weaver (windows-latest, win-x64)

Check warning on line 25 in Realm/Realm/Native/AppConfiguration.cs

View workflow job for this annotation

GitHub Actions / Analyze C#

Check warning on line 25 in Realm/Realm/Native/AppConfiguration.cs

View workflow job for this annotation

GitHub Actions / Analyze C#

Check warning on line 25 in Realm/Realm/Native/AppConfiguration.cs

View workflow job for this annotation

GitHub Actions / Analyze C#

{
internal UInt64 max_resumption_delay_interval_ms;

internal UInt64 resumption_delay_interval_ms;

internal int resumption_delay_backoff_multiplier;

internal int delay_jitter_divisor;
}

[StructLayout(LayoutKind.Sequential)]
internal struct SyncTimeoutOptions
{
internal UInt64 sync_connect_timeout_ms;

internal UInt64 sync_connection_linger_time_ms;

internal UInt64 sync_ping_keep_alive_period_ms;

internal UInt64 sync_pong_keep_alive_timeout_ms;

internal UInt64 sync_fast_reconnect_limit;

internal ReconnectBackoffOptions reconnect_backoff_options;
}

[StructLayout(LayoutKind.Sequential)]
internal struct AppConfiguration
{
Expand Down Expand Up @@ -83,15 +111,7 @@ internal MetadataPersistenceMode? MetadataPersistence

internal IntPtr managed_websocket_provider;

internal UInt64 sync_connect_timeout_ms;

internal UInt64 sync_connection_linger_time_ms;

internal UInt64 sync_ping_keep_alive_period_ms;

internal UInt64 sync_pong_keep_alive_timeout_ms;

internal UInt64 sync_fast_reconnect_limit;
internal SyncTimeoutOptions sync_timeout_options;

[MarshalAs(UnmanagedType.U1)]
internal bool use_cache;
Expand Down
20 changes: 15 additions & 5 deletions Realm/Realm/Sync/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,11 +174,21 @@ public static App Create(AppConfiguration config)
MetadataPersistence = config.MetadataPersistenceMode,
default_request_timeout_ms = (ulong)config.DefaultRequestTimeout.TotalMilliseconds,
managed_http_client = GCHandle.ToIntPtr(clientHandle),
sync_connection_linger_time_ms = (ulong)syncTimeouts.ConnectionLingerTime.TotalMilliseconds,
sync_connect_timeout_ms = (ulong)syncTimeouts.ConnectTimeout.TotalMilliseconds,
sync_fast_reconnect_limit = (ulong)syncTimeouts.FastReconnectLimit.TotalMilliseconds,
sync_ping_keep_alive_period_ms = (ulong)syncTimeouts.PingKeepAlivePeriod.TotalMilliseconds,
sync_pong_keep_alive_timeout_ms = (ulong)syncTimeouts.PongKeepAliveTimeout.TotalMilliseconds,
sync_timeout_options = new Native.SyncTimeoutOptions
{
sync_connection_linger_time_ms = (ulong)syncTimeouts.ConnectionLingerTime.TotalMilliseconds,
sync_connect_timeout_ms = (ulong)syncTimeouts.ConnectTimeout.TotalMilliseconds,
sync_fast_reconnect_limit = (ulong)syncTimeouts.FastReconnectLimit.TotalMilliseconds,
sync_ping_keep_alive_period_ms = (ulong)syncTimeouts.PingKeepAlivePeriod.TotalMilliseconds,
sync_pong_keep_alive_timeout_ms = (ulong)syncTimeouts.PongKeepAliveTimeout.TotalMilliseconds,
reconnect_backoff_options = new Native.ReconnectBackoffOptions
{
max_resumption_delay_interval_ms = (ulong)syncTimeouts.ReconnectBackoffOptions.MaxReconnectDelayInterval.TotalMilliseconds,
resumption_delay_interval_ms = (ulong)syncTimeouts.ReconnectBackoffOptions.ReconnectDelayInterval.TotalMilliseconds,
resumption_delay_backoff_multiplier = syncTimeouts.ReconnectBackoffOptions.ReconnectDelayBackoffMultiplier,
delay_jitter_divisor = syncTimeouts.ReconnectBackoffOptions.DelayJitterDivisor
}
},
use_cache = config.UseAppCache,
};

Expand Down
80 changes: 80 additions & 0 deletions Realm/Realm/Sync/ReconnectBackoffOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2024 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License")
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

using System;

namespace Realms.Sync
{
/// <summary>
/// Options for configuring the reconnection delay used by the sync client.
/// </summary>
/// <remarks>
/// The sync client employs an exponential backoff delay strategy when reconnecting to the server.
/// In order to not spam the network interface the sync client performs an increasing wait before reconnecting.
/// The wait starts from <see cref="ReconnectDelayInterval"/> and multiplies by <see cref="ReconnectDelayBackoffMultiplier"/>
/// until it reaches <see cref="MaxReconnectDelayInterval"/>.
/// </remarks>
public class ReconnectBackoffOptions
{
/// <summary>
/// Gets or sets the maximum amount of time to wait before a reconnection attempt.
/// </summary>
/// <remarks>
/// Defaults to 5 minutes.
/// </remarks>
/// <value>
/// The maximum amount of time to wait before a reconnection attempt.
/// </value>
public TimeSpan MaxReconnectDelayInterval { get; set; } = TimeSpan.FromMinutes(5);

/// <summary>
/// Gets or sets the initial amount of time to wait before a reconnection attempt.
/// </summary>
/// <remarks>
/// Defaults to 1 second.
/// </remarks>
/// <value>
/// The initial amount of time to wait before a reconnection attempt.
/// </value>
public TimeSpan ReconnectDelayInterval { get; set; } = TimeSpan.FromSeconds(1);

/// <summary>
/// Gets or sets the multiplier to apply to the accumulated reconnection delay before a new reconection attempt.
/// </summary>
/// <remarks>
/// Defaults to 2.
/// </remarks>
/// <value>
/// The delay multiplier.
/// </value>
public int ReconnectDelayBackoffMultiplier { get; set; } = 2;

/// <summary>
/// Gets or sets the jitter randomization factor to apply to the delay.
/// </summary>
/// <remarks>
/// The reconnection delay is subtracted by a value derived from this divisor so that if a lot of clients lose connection and reconnect at the same time the server won't be overwhelmed.
/// <br />
/// Defaults to 4.
/// </remarks>
/// <value>
/// The jitter randomization factor to apply to the delay.
/// </value>
public int DelayJitterDivisor { get; set; } = 4;
}
}
8 changes: 8 additions & 0 deletions Realm/Realm/Sync/SyncTimeoutOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,5 +104,13 @@ public class SyncTimeoutOptions
/// </remarks>
/// <value>The window in which a drop in connectivity is considered transient.</value>
public TimeSpan FastReconnectLimit { get; set; } = TimeSpan.FromMinutes(1);

/// <summary>
/// Gets or sets the options for the reconnection behavior of the sync client.
/// </summary>
/// <value>
/// The options controlling how long the sync client waits before attempting to reconnect.
/// </value>
public ReconnectBackoffOptions ReconnectBackoffOptions { get; set; } = new ();
}
}
49 changes: 35 additions & 14 deletions wrappers/src/app_cs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,28 @@ namespace realm {
std::function<StringCallbackT> s_string_callback;
std::function<ApiKeysCallbackT> s_api_keys_callback;

struct SyncTimeoutOptions {
uint64_t sync_connect_timeout_ms;

uint64_t sync_connection_linger_time_ms;

uint64_t sync_ping_keep_alive_period_ms;

uint64_t sync_pong_keep_alive_timeout_ms;

uint64_t sync_fast_reconnect_limit;

struct {
uint64_t max_resumption_delay_interval_ms;

uint64_t resumption_delay_interval_ms;

int resumption_delay_backoff_multiplier;

int delay_jitter_divisor;
} reconnect_backoff_info;
};

struct AppConfiguration
{
uint16_t* app_id;
Expand All @@ -82,15 +104,7 @@ namespace realm {

void* managed_websocket_provider;

uint64_t sync_connect_timeout_ms;

uint64_t sync_connection_linger_time_ms;

uint64_t sync_ping_keep_alive_period_ms;

uint64_t sync_pong_keep_alive_timeout_ms;

uint64_t sync_fast_reconnect_limit;
SyncTimeoutOptions sync_timeout_options;

bool use_cache;
};
Expand Down Expand Up @@ -149,11 +163,18 @@ extern "C" {
}

config.base_file_path = Utf16StringAccessor(app_config.base_file_path, app_config.base_file_path_len);
config.sync_client_config.timeouts.connection_linger_time = app_config.sync_connection_linger_time_ms;
config.sync_client_config.timeouts.connect_timeout = app_config.sync_connect_timeout_ms;
config.sync_client_config.timeouts.fast_reconnect_limit = app_config.sync_fast_reconnect_limit;
config.sync_client_config.timeouts.ping_keepalive_period = app_config.sync_ping_keep_alive_period_ms;
config.sync_client_config.timeouts.pong_keepalive_timeout = app_config.sync_pong_keep_alive_timeout_ms;

auto& timeout_options = config.sync_client_config.timeouts;
const auto& managed_timeout_options = app_config.sync_timeout_options;
timeout_options.connection_linger_time = managed_timeout_options.sync_connection_linger_time_ms;
timeout_options.connect_timeout = managed_timeout_options.sync_connect_timeout_ms;
timeout_options.fast_reconnect_limit = managed_timeout_options.sync_fast_reconnect_limit;
timeout_options.ping_keepalive_period = managed_timeout_options.sync_ping_keep_alive_period_ms;
timeout_options.pong_keepalive_timeout = managed_timeout_options.sync_pong_keep_alive_timeout_ms;
timeout_options.reconnect_backoff_info.max_resumption_delay_interval = managed_timeout_options.reconnect_backoff_info.max_resumption_delay_interval_ms;
timeout_options.reconnect_backoff_info.resumption_delay_interval = managed_timeout_options.reconnect_backoff_info.resumption_delay_interval_ms;
timeout_options.reconnect_backoff_info.resumption_delay_backoff_multiplier = managed_timeout_options.reconnect_backoff_info.resumption_delay_backoff_multiplier;
timeout_options.reconnect_backoff_info.delay_jitter_divisor = managed_timeout_options.reconnect_backoff_info.delay_jitter_divisor;

if (app_config.managed_websocket_provider) {
config.sync_client_config.socket_provider = make_websocket_provider(app_config.managed_websocket_provider);
Expand Down

0 comments on commit 76ebe6b

Please sign in to comment.