Skip to content

Commit

Permalink
Cleanup + more nullability
Browse files Browse the repository at this point in the history
  • Loading branch information
ReubenBond committed Apr 28, 2024
1 parent 3bdd046 commit 588cd19
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 156 deletions.
96 changes: 48 additions & 48 deletions src/Orleans.Core.Abstractions/Runtime/IGrainRuntime.cs
Original file line number Diff line number Diff line change
@@ -1,64 +1,64 @@
#nullable enable
using System;
using Orleans.Core;
using Orleans.Timers;

namespace Orleans.Runtime
namespace Orleans.Runtime;

/// <summary>
/// The gateway of the <see cref="Grain"/> to the Orleans runtime. The <see cref="Grain"/> should only interact with the runtime through this interface.
/// </summary>
public interface IGrainRuntime
{
/// <summary>
/// The gateway of the <see cref="Grain"/> to the Orleans runtime. The <see cref="Grain"/> should only interact with the runtime through this interface.
/// Gets a unique identifier for the current silo.
/// There is no semantic content to this string, but it may be useful for logging.
/// </summary>
public interface IGrainRuntime
{
/// <summary>
/// Gets a unique identifier for the current silo.
/// There is no semantic content to this string, but it may be useful for logging.
/// </summary>
string SiloIdentity { get; }
string SiloIdentity { get; }

/// <summary>
/// Gets the silo address associated with this instance.
/// </summary>
SiloAddress SiloAddress { get; }
/// <summary>
/// Gets the silo address associated with this instance.
/// </summary>
SiloAddress SiloAddress { get; }

/// <summary>
/// Gets the grain factory.
/// </summary>
IGrainFactory GrainFactory { get; }
/// <summary>
/// Gets the grain factory.
/// </summary>
IGrainFactory GrainFactory { get; }

/// <summary>
/// Gets the timer registry.
/// </summary>
ITimerRegistry TimerRegistry { get; }
/// <summary>
/// Gets the timer registry.
/// </summary>
ITimerRegistry TimerRegistry { get; }

/// <summary>
/// Gets the service provider.
/// </summary>
IServiceProvider ServiceProvider { get; }
/// <summary>
/// Gets the service provider.
/// </summary>
IServiceProvider ServiceProvider { get; }

/// <summary>
/// Gets the time provider.
/// </summary>
TimeProvider TimeProvider => TimeProvider.System;
/// <summary>
/// Gets the time provider.
/// </summary>
TimeProvider TimeProvider => TimeProvider.System;

/// <summary>
/// Deactivates the provided grain when it becomes idle.
/// </summary>
/// <param name="grainContext">The grain context.</param>
void DeactivateOnIdle(IGrainContext grainContext);
/// <summary>
/// Deactivates the provided grain when it becomes idle.
/// </summary>
/// <param name="grainContext">The grain context.</param>
void DeactivateOnIdle(IGrainContext grainContext);

/// <summary>
/// Delays idle activation collection of the provided grain due to inactivity until at least the specified time has elapsed.
/// </summary>
/// <param name="grainContext">The grain context.</param>
/// <param name="timeSpan">The time to delay idle activation collection for.</param>
void DelayDeactivation(IGrainContext grainContext, TimeSpan timeSpan);
/// <summary>
/// Delays idle activation collection of the provided grain due to inactivity until at least the specified time has elapsed.
/// </summary>
/// <param name="grainContext">The grain context.</param>
/// <param name="timeSpan">The time to delay idle activation collection for.</param>
void DelayDeactivation(IGrainContext grainContext, TimeSpan timeSpan);

/// <summary>
/// Gets grain storage for the provided grain.
/// </summary>
/// <typeparam name="TGrainState">The grain state type.</typeparam>
/// <param name="grainContext">The grain context.</param>
/// <returns>The grain storage for the provided grain.</returns>
IStorage<TGrainState> GetStorage<TGrainState>(IGrainContext grainContext);
}
/// <summary>
/// Gets grain storage for the provided grain.
/// </summary>
/// <typeparam name="TGrainState">The grain state type.</typeparam>
/// <param name="grainContext">The grain context.</param>
/// <returns>The grain storage for the provided grain.</returns>
IStorage<TGrainState> GetStorage<TGrainState>(IGrainContext grainContext);
}
68 changes: 33 additions & 35 deletions src/Orleans.Core/Providers/GrainStorageHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,49 +1,47 @@
#nullable enable
using System;
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.DependencyInjection;
using Orleans.Providers;
using Orleans.Runtime;

#nullable enable
namespace Orleans.Storage
namespace Orleans.Storage;

/// <summary>
/// Utility functions for grain storage.
/// </summary>
public static class GrainStorageHelpers
{
/// <summary>
/// Utility functions for grain storage.
/// Gets the <see cref="IGrainStorage"/> associated with the specified grain type, which must derive from <see cref="Grain{T}"/>.
/// </summary>
public static class GrainStorageHelpers
/// <param name="grainType">The grain type, which must derive from <see cref="Grain{T}"/>.</param>
/// <param name="services">The service provider.</param>
/// <returns>
/// The <see cref="IGrainStorage"/> associated with the specified grain type, which must derive from <see cref="Grain{T}"/>.
/// </returns>
public static IGrainStorage GetGrainStorage(Type grainType, IServiceProvider services)
{
/// <summary>
/// Gets the <see cref="IGrainStorage"/> associated with the specified grain type, which must derive from <see cref="Grain{T}"/>.
/// </summary>
/// <param name="grainType">The grain type, which must derive from <see cref="Grain{T}"/>.</param>
/// <param name="services">The service provider.</param>
/// <returns>
/// The <see cref="IGrainStorage"/> associated with the specified grain type, which must derive from <see cref="Grain{T}"/>.
/// </returns>
public static IGrainStorage GetGrainStorage(Type grainType, IServiceProvider services)
if (grainType is null) throw new ArgumentNullException(nameof(grainType));
var attrs = grainType.GetCustomAttributes(typeof(StorageProviderAttribute), true);
var attr = attrs.Length > 0 ? (StorageProviderAttribute)attrs[0] : null;
var storageProvider = attr != null
? services.GetKeyedService<IGrainStorage>(attr.ProviderName)
: services.GetService<IGrainStorage>();
if (storageProvider == null)
{
if (grainType is null) throw new ArgumentNullException(nameof(grainType));
var attrs = grainType.GetCustomAttributes(typeof(StorageProviderAttribute), true);
var attr = attrs.Length > 0 ? (StorageProviderAttribute)attrs[0] : null;
var storageProvider = attr != null
? services.GetKeyedService<IGrainStorage>(attr.ProviderName)
: services.GetService<IGrainStorage>();
if (storageProvider == null)
{
ThrowMissingProviderException(grainType, attr?.ProviderName);
}

return storageProvider;
ThrowMissingProviderException(grainType, attr?.ProviderName);
}

[DoesNotReturn]
private static void ThrowMissingProviderException(Type grainType, string? name)
{
var grainTypeName = grainType.FullName;
var errMsg = string.IsNullOrEmpty(name)
? $"No default storage provider found loading grain type {grainTypeName}."
: $"No storage provider named \"{name}\" found loading grain type {grainTypeName}.";
throw new BadProviderConfigException(errMsg);
}
return storageProvider;
}

[DoesNotReturn]
private static void ThrowMissingProviderException(Type grainType, string? name)
{
var grainTypeName = grainType.FullName;
var errMsg = string.IsNullOrEmpty(name)
? $"No default storage provider found loading grain type {grainTypeName}."
: $"No storage provider named \"{name}\" found loading grain type {grainTypeName}.";
throw new BadProviderConfigException(errMsg);
}
}
146 changes: 73 additions & 73 deletions src/Orleans.Runtime/Core/GrainRuntime.cs
Original file line number Diff line number Diff line change
@@ -1,106 +1,106 @@
#nullable enable
using System;
using Orleans.Core;
using Orleans.Timers;
using Orleans.Storage;

namespace Orleans.Runtime
namespace Orleans.Runtime;

internal class GrainRuntime : IGrainRuntime
{
internal class GrainRuntime : IGrainRuntime
{
private readonly IServiceProvider _serviceProvider;
private readonly IServiceProvider _serviceProvider;

private readonly ITimerRegistry _timerRegistry;
private readonly IGrainFactory _grainFactory;
private readonly ITimerRegistry _timerRegistry;
private readonly IGrainFactory _grainFactory;

public GrainRuntime(
ILocalSiloDetails localSiloDetails,
IGrainFactory grainFactory,
ITimerRegistry timerRegistry,
IServiceProvider serviceProvider,
TimeProvider timeProvider)
{
SiloAddress = localSiloDetails.SiloAddress;
SiloIdentity = SiloAddress.ToString();
_grainFactory = grainFactory;
_timerRegistry = timerRegistry;
_serviceProvider = serviceProvider;
TimeProvider = timeProvider;
}
public GrainRuntime(
ILocalSiloDetails localSiloDetails,
IGrainFactory grainFactory,
ITimerRegistry timerRegistry,
IServiceProvider serviceProvider,
TimeProvider timeProvider)
{
SiloAddress = localSiloDetails.SiloAddress;
SiloIdentity = SiloAddress.ToString();
_grainFactory = grainFactory;
_timerRegistry = timerRegistry;
_serviceProvider = serviceProvider;
TimeProvider = timeProvider;
}

public string SiloIdentity { get; }
public string SiloIdentity { get; }

public SiloAddress SiloAddress { get; }
public SiloAddress SiloAddress { get; }

public IGrainFactory GrainFactory
public IGrainFactory GrainFactory
{
get
{
get
{
CheckRuntimeContext(RuntimeContext.Current);
return _grainFactory;
}
CheckRuntimeContext(RuntimeContext.Current);
return _grainFactory;
}
}

public ITimerRegistry TimerRegistry
public ITimerRegistry TimerRegistry
{
get
{
get
{
CheckRuntimeContext(RuntimeContext.Current);
return _timerRegistry;
}
CheckRuntimeContext(RuntimeContext.Current);
return _timerRegistry;
}
}

public IServiceProvider ServiceProvider
public IServiceProvider ServiceProvider
{
get
{
get
{
CheckRuntimeContext(RuntimeContext.Current);
return _serviceProvider;
}
CheckRuntimeContext(RuntimeContext.Current);
return _serviceProvider;
}
}

public TimeProvider TimeProvider { get; }

public TimeProvider TimeProvider { get; }
public void DeactivateOnIdle(IGrainContext grainContext)
{
CheckRuntimeContext(grainContext);
grainContext.Deactivate(new(DeactivationReasonCode.ApplicationRequested, $"{nameof(DeactivateOnIdle)} was called."));
}

public void DeactivateOnIdle(IGrainContext grainContext)
public void DelayDeactivation(IGrainContext grainContext, TimeSpan timeSpan)
{
CheckRuntimeContext(grainContext);
if (grainContext is not ICollectibleGrainContext collectibleContext)
{
CheckRuntimeContext(grainContext);
grainContext.Deactivate(new(DeactivationReasonCode.ApplicationRequested, $"{nameof(DeactivateOnIdle)} was called."));
throw new NotSupportedException($"Grain context {grainContext} does not implement {nameof(ICollectibleGrainContext)} and therefore {nameof(DelayDeactivation)} is not supported");
}

public void DelayDeactivation(IGrainContext grainContext, TimeSpan timeSpan)
{
CheckRuntimeContext(grainContext);
if (grainContext is not ICollectibleGrainContext collectibleContext)
{
throw new NotSupportedException($"Grain context {grainContext} does not implement {nameof(ICollectibleGrainContext)} and therefore {nameof(DelayDeactivation)} is not supported");
}
collectibleContext.DelayDeactivation(timeSpan);
}

collectibleContext.DelayDeactivation(timeSpan);
}
public IStorage<TGrainState> GetStorage<TGrainState>(IGrainContext grainContext)
{
ArgumentNullException.ThrowIfNull(grainContext);
var grainType = grainContext.GrainInstance?.GetType() ?? throw new ArgumentNullException(nameof(IGrainContext.GrainInstance));
IGrainStorage grainStorage = GrainStorageHelpers.GetGrainStorage(grainType, ServiceProvider);
return new StateStorageBridge<TGrainState>("state", grainContext, grainStorage);
}

public IStorage<TGrainState> GetStorage<TGrainState>(IGrainContext grainContext)
public static void CheckRuntimeContext(IGrainContext context)
{
if (context is null)
{
if (grainContext is null) throw new ArgumentNullException(nameof(grainContext));
var grainType = grainContext.GrainInstance?.GetType() ?? throw new ArgumentNullException(nameof(IGrainContext.GrainInstance));
IGrainStorage grainStorage = GrainStorageHelpers.GetGrainStorage(grainType, ServiceProvider);
return new StateStorageBridge<TGrainState>("state", grainContext, grainStorage);
// Move exceptions into local functions to help inlining this method.
ThrowMissingContext();
void ThrowMissingContext() => throw new InvalidOperationException("Activation access violation. A non-activation thread attempted to access activation services.");
}

public static void CheckRuntimeContext(IGrainContext context)
if (context is ActivationData activation
&& (activation.State == ActivationState.Invalid || activation.State == ActivationState.FailedToActivate))
{
if (context is null)
{
// Move exceptions into local functions to help inlining this method.
ThrowMissingContext();
void ThrowMissingContext() => throw new InvalidOperationException("Activation access violation. A non-activation thread attempted to access activation services.");
}

if (context is ActivationData activation
&& (activation.State == ActivationState.Invalid || activation.State == ActivationState.FailedToActivate))
{
// Move exceptions into local functions to help inlining this method.
ThrowInvalidActivation(activation);
void ThrowInvalidActivation(ActivationData activationData) => throw new InvalidOperationException($"Attempt to access an invalid activation: {activationData}");
}
// Move exceptions into local functions to help inlining this method.
ThrowInvalidActivation(activation);
void ThrowInvalidActivation(ActivationData activationData) => throw new InvalidOperationException($"Attempt to access an invalid activation: {activationData}");
}
}
}

0 comments on commit 588cd19

Please sign in to comment.