using System;
using System.Threading;
using System.Threading.Tasks;
using RudderSdk.Core.Abstractions;
using RudderSdk.Core.Models.Auth;
namespace RudderSdk.Core;
///
/// Entry point of the Rudder SDK. Composes all feature services around one
/// configuration () and owns the session
/// lifecycle: every API call goes through here, a 401 triggers a single-flight
/// token refresh and one transparent retry.
///
public sealed class RudderClient
{
private readonly object _refreshGate = new();
private Task? _pendingRefresh;
/// Authentication: device login, token refresh, logout.
public AuthService Auth { get; }
/// Player profile and wallets.
public PlayerService Player { get; }
/// Remote configuration values.
public RemoteConfigService RemoteConfig { get; }
/// Player key-value storage.
public StorageService Storage { get; }
/// In-game stores and offer purchases.
public StoresService Stores { get; }
/// Leaderboards.
public LeaderboardsService Leaderboards { get; }
/// Player inventory.
public InventoryService Inventory { get; }
/// Battle pass progress and rewards.
public BattlePassService BattlePass { get; }
/// Global quests.
public QuestsService Quests { get; }
/// User-generated content.
public UgcService Ugc { get; }
/// Scenario runtime: triggers, node sessions, persistence.
public ScenarioService Scenario { get; }
/// Realtime websocket channel.
public RealtimeService Realtime { get; }
internal RudderClientOptions Options { get; }
internal IRudderTransport Transport => Options.Transport!;
internal ITokenStore TokenStore => Options.TokenStore!;
internal IDeviceIdProvider DeviceIdProvider => Options.DeviceIdProvider!;
/// Project key from .
public string ProjectKey => Options.ProjectKey!;
/// Realtime URL from .
public string? RealtimeUrl => Options.RealtimeUrl;
/// Time source used by the scenario runtime.
public IClock Clock => Options.Clock ?? SystemClock.Instance;
///
/// Creates the client. and
/// are required; transport,
/// token store and device id provider fall back to defaults.
///
public RudderClient(RudderClientOptions options)
{
Options = options ?? throw new ArgumentNullException(nameof(options));
if (string.IsNullOrEmpty(Options.BaseUrl)) throw new ArgumentException("BaseUrl is required.", nameof(options));
if (string.IsNullOrEmpty(Options.ProjectKey)) throw new ArgumentException("ProjectKey is required.", nameof(options));
Options.Transport ??= new HttpClientTransport(Options.BaseUrl);
Options.TokenStore ??= new InMemoryTokenStore();
Options.DeviceIdProvider ??= new GuidDeviceIdProvider();
Auth = new AuthService(this);
Player = new PlayerService(this);
RemoteConfig = new RemoteConfigService(this);
Storage = new StorageService(this);
Stores = new StoresService(this);
Leaderboards = new LeaderboardsService(this);
Inventory = new InventoryService(this);
Ugc = new UgcService(this);
Scenario = new ScenarioService(this);
BattlePass = new BattlePassService(this);
Quests = new QuestsService(this);
Realtime = new RealtimeService(this);
}
/// Pumps time-dependent services; call every frame.
public void Update(float deltaTime)
{
Scenario.Update(deltaTime);
Realtime.Update(deltaTime);
}
internal Task SendAsync(
string method,
string path,
TRequest? request,
CancellationToken cancellationToken = default)
{
return SendWithRetryAsync(method, path, request, cancellationToken);
}
internal Task SendAsync(
string method,
string path,
CancellationToken cancellationToken = default)
{
return SendWithRetryAsync