Editor/Core/SendCadence.cs
using System;
namespace TeamCreate;
/// <summary>
/// How often an editor talks to the host when nothing has changed. Every message an editor sends is also a message the relay receives, and a free shared
/// relay is billed per message, so sending ten identical presence packets a second is the difference between a session that costs almost nothing and one
/// that uses a day's allowance in hours. The host drops a member after 15 seconds of silence (SessionServer), so every interval here stays far inside that.
/// </summary>
public static class SendCadence
{
/// <summary>The host's own silence limit is 15 seconds; an editor never stays quiet for more than this.</summary>
public static readonly TimeSpan MaxSilence = TimeSpan.FromSeconds(4);
/// <summary>The fastest presence is sent while the camera or selection is changing: ten a second, as before.</summary>
public static readonly TimeSpan PresenceMinimum = TimeSpan.FromMilliseconds(100);
/// <summary>Unchanged presence is repeated at this interval, so a collaborator who arrives late learns where everyone is.</summary>
public static readonly TimeSpan PresenceRefresh = TimeSpan.FromSeconds(2);
/// <summary>The liveness heartbeat.</summary>
public static readonly TimeSpan PingInterval = TimeSpan.FromSeconds(2);
public static bool ShouldSendPresence(bool changed, TimeSpan sinceLastSend, bool isEditing)
{
if (sinceLastSend >= PresenceRefresh)
{
return true;
}
return changed && sinceLastSend >= PresenceMinimum;
}
public static bool ShouldSendPing(TimeSpan sinceLastSend)
{
return sinceLastSend >= PingInterval;
}
/// <summary>Messages per second an idle session sends the relay: every member's refresh and heartbeat.</summary>
public static double MessagesPerSecondIdle(int peers)
{
return peers * (1.0 / PresenceRefresh.TotalSeconds + 1.0 / PingInterval.TotalSeconds);
}
/// <summary>The ceiling while every member is moving: presence at its minimum interval plus the heartbeat.</summary>
public static double MessagesPerSecondMoving(int peers)
{
return peers * (1.0 / PresenceMinimum.TotalSeconds + 1.0 / PingInterval.TotalSeconds);
}
/// <summary>Cloudflare bills incoming WebSocket messages at 20 to 1 against its request allowance.</summary>
public static double BilledRequestsPerHour(double messagesPerSecond)
{
return messagesPerSecond * 3600.0 / 20.0;
}
public const double FreeRequestsPerDay = 100000.0;
public static double FreeHoursPerDay(double messagesPerSecond)
{
return FreeRequestsPerDay / BilledRequestsPerHour(messagesPerSecond);
}
}