-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3bdd046
commit 588cd19
Showing
3 changed files
with
154 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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}"); | ||
} | ||
} | ||
} |