How do I correctly call the DeactivateOnIdle() method within the Grain? Getting error!
mstfcck opened this issue · 3 comments
I'm trying to make a simple application that will run time-based processes with Orleans.
All the codes of the application I am working on are as follows.
I create 1 Grain (ExecutorGrain) on 1 Silo. This will be a logic that will run a time-based business within Grain.
PS: ExecutorGrainV2 is a different example, I just added it to the code, ExecutorGrain and ExecutorGrainV2 are not active at the same time at run time.
For example; process data from a specific Event for 10 minutes and completely Dispose of the Grain when the time is up (like Kafka/RabbitMQ consumer).
After this Grain is Disposed, I want it to be cleared from the system until it is called again, and when it is created again, I want it to run a completely new process (with the same business code).
NOTE: Ideally, of course, my goal will be more than 1 Silo and more than 1 Grain.
DeactivateOnIdle(); No matter where I call the method, I get an error. You can see the entire log of the error I received after running the code sample I gave below.
- I reviewed the documentation and could not find sufficient information.
- I reviewed other issues opened on the subject and tried similar things.
- I couldn't find a method on StackOverflow.
- I also checked the sample application codes, but I could not find a suitable reference for such a scenario.
The Dispose() operation seems to cause an error at runtime, but I couldn't understand why and how.
I request your support regarding the code.
Packages
Packages
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0"/>
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0"/>
<PackageReference Include="Microsoft.Orleans.Server" Version="8.0.0"/>
<PackageReference Include="OrleansDashboard" Version="7.2.2"/>
</ItemGroup>
Code
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Orleans.Configuration;
class Program
{
static async Task Main(string[] args)
{
var builder = Host.CreateDefaultBuilder(args)
.UseOrleans(silo =>
{
silo.UseLocalhostClustering()
.UseDashboard(x => x.HostSelf = true)
.Configure<ClusterOptions>(options =>
{
options.ClusterId = "dev";
options.ServiceId = "Orleans";
})
.ConfigureLogging(logging => logging.AddConsole());
})
.UseConsoleLifetime()
.ConfigureServices((hostContext, services) => { });
using var host = builder.Build();
await host.StartAsync();
var client = host.Services.GetRequiredService<IClusterClient>();
var executorGrain = client.GetGrain<IExecutorGrain>(new Random().Next());
await executorGrain.Execute();
}
}
public interface IExecutorGrain : IGrainWithIntegerKey
{
Task Execute();
}
public class ExecutorGrain : Grain, IExecutorGrain
{
public async Task Execute()
{
Console.WriteLine($">>> Executing");
var counter = 0;
while (counter < 5)
{
// Here; there will be time-based processes
await Task.Delay(1000);
Console.WriteLine($">>> Execute Counter: {counter++}");
}
Console.WriteLine($">>> Executed");
DeactivateOnIdle();
}
}
public class ExecutorGrainV2 : Grain, IExecutorGrain
{
private IDisposable? _timer;
public override Task OnActivateAsync(CancellationToken cancellationToken)
{
_timer = RegisterTimer(TimerAsync, null, TimeSpan.FromMilliseconds(10), TimeSpan.FromMilliseconds(10));
return base.OnActivateAsync(cancellationToken);
}
public async Task Execute()
{
Console.WriteLine($">>> Executing");
var counter = 0;
while (counter < 5)
{
// Here; there will be time-based processes
await Task.Delay(1000);
Console.WriteLine($">>> Execute Counter: {counter++}");
}
Console.WriteLine($">>> Executed");
}
private Task TimerAsync(object state = null)
{
Console.WriteLine($">>> Timer Executed");
_timer?.Dispose();
_timer = null;
DeactivateOnIdle();
return Task.CompletedTask;
}
}
Console Logs after Run
Logs
info: Orleans.Runtime.Silo[100404]
Silo starting with GC settings: ServerGC=False GCLatencyMode=Interactive
warn: Orleans.Runtime.Silo[100405]
Note: Silo not running with ServerGC turned on - recommend checking app config : <configuration>-<runtime>-<gcServer enabled="true">
warn: Orleans.Runtime.Silo[100405]
Note: ServerGC only kicks in on multi-core systems (settings enabling ServerGC have no effect on single-core machines).
info: Orleans.Runtime.Silo[100403]
-------------- Initializing silo on host MSTFCCK.local MachineName MSTFCCK at 127.0.0.1:11111, gen 68851927 --------------
info: Orleans.Runtime.Silo[100415]
Starting silo Silo_61487
warn: Orleans.Runtime.NoOpHostEnvironmentStatistics[100708]
No implementation of IHostEnvironmentStatistics was found. Load shedding will not work yet
info: Orleans.Runtime.Silo[100422]
-------------- Started silo S127.0.0.1:11111:68851927, ConsistentHashCode 9DED6DA9 --------------
info: Orleans.Hosting.SiloHostedService[0]
Starting Orleans Silo.
info: Orleans.Runtime.SiloOptionsLogger[0]
Configuration Orleans.Configuration.ActivationCountBasedPlacementOptions:
ChooseOutOf: 2
info: Orleans.Runtime.SiloOptionsLogger[0]
Configuration Orleans.Configuration.ClusterMembershipOptions:
NumMissedTableIAmAliveLimit: 2
LivenessEnabled: True
ProbeTimeout: 00:00:05
TableRefreshTimeout: 00:01:00
DeathVoteExpirationTimeout: 00:02:00
IAmAliveTablePublishTimeout: 00:05:00
MaxJoinAttemptTime: 00:05:00
UseLivenessGossip: True
NumProbedSilos: 3
NumMissedProbesLimit: 3
NumVotesForDeathDeclaration: 2
DefunctSiloExpiration: 7.00:00:00
DefunctSiloCleanupPeriod: 01:00:00
LocalHealthDegradationMonitoringPeriod: 00:00:10
ExtendProbeTimeoutDuringDegradation: True
EnableIndirectProbes: True
info: Orleans.Runtime.SiloOptionsLogger[0]
Configuration Orleans.Configuration.ClusterOptions:
ClusterId: dev
ServiceId: Orleans
info: Orleans.Runtime.SiloOptionsLogger[0]
Configuration Orleans.Configuration.ConnectionOptions:
ProtocolVersion: Version1
ConnectionsPerEndpoint: 1
ConnectionRetryDelay: 00:00:01
OpenConnectionTimeout: 00:00:05
info: Orleans.Runtime.SiloOptionsLogger[0]
Configuration Orleans.Configuration.ConsistentRingOptions:
NumVirtualBucketsConsistentRing: 30
UseVirtualBucketsConsistentRing: True
info: Orleans.Runtime.SiloOptionsLogger[0]
Configuration Orleans.Configuration.DevelopmentClusterMembershipOptions:
PrimarySiloEndpoint: 127.0.0.1:11111
info: Orleans.Runtime.SiloOptionsLogger[0]
Configuration Orleans.Configuration.EndpointOptions:
AdvertisedIPAddress: 127.0.0.1
SiloPort: 11111
GatewayPort: 30000
SiloListeningEndpoint:
GatewayListeningEndpoint:
info: Orleans.Runtime.SiloOptionsLogger[0]
Configuration Orleans.Configuration.GrainCollectionOptions:
CollectionQuantum: 00:01:00
CollectionAge: 00:15:00
ActivationTimeout: 00:00:30
DeactivationTimeout: 00:00:30
info: Orleans.Runtime.SiloOptionsLogger[0]
Configuration Orleans.Configuration.GrainDirectoryOptions:
CachingStrategy: Adaptive
CacheSize: 1000000
InitialCacheTTL: 00:00:30
MaximumCacheTTL: 00:04:00
CacheTTLExtensionFactor: 2
LazyDeregistrationDelay: 00:01:00
info: Orleans.Runtime.SiloOptionsLogger[0]
Configuration Orleans.Configuration.GrainVersioningOptions:
DefaultCompatibilityStrategy: BackwardCompatible
DefaultVersionSelectorStrategy: AllCompatibleVersions
info: Orleans.Runtime.SiloOptionsLogger[0]
Configuration Orleans.Configuration.LoadSheddingOptions:
LoadSheddingEnabled: False
LoadSheddingLimit: 95
info: Orleans.Runtime.SiloOptionsLogger[0]
Configuration Orleans.Configuration.SchedulingOptions:
DelayWarningThreshold: 00:00:10
ActivationSchedulingQuantum: 00:00:00.1000000
TurnWarningLengthThreshold: 00:00:01
MaxPendingWorkItemsSoftLimit: 0
StoppedActivationWarningInterval: 00:01:00
info: Orleans.Runtime.SiloOptionsLogger[0]
Configuration Orleans.Configuration.SiloMessagingOptions:
SiloSenderQueues: 0
GatewaySenderQueues: 0
MaxForwardCount: 2
ClientDropTimeout: 00:01:00
ClientRegistrationRefresh: 00:05:00
ClientGatewayShutdownNotificationTimeout: 00:00:05
MaxEnqueuedRequestsSoftLimit: 0
MaxEnqueuedRequestsHardLimit: 0
MaxEnqueuedRequestsSoftLimit_StatelessWorker: 0
MaxEnqueuedRequestsHardLimit_StatelessWorker: 0
MaxRequestProcessingTime: 02:00:00
AssumeHomogenousSilosForTesting: False
ShutdownRerouteTimeout: 00:00:10
SystemResponseTimeout: 00:30:00
GrainWorkloadAnalysisPeriod: 00:00:05
RequestProcessingWarningTime: 00:00:05
RequestQueueDelayWarningTime: 00:00:10
WaitForMessageToBeQueuedForOutboundTime: 00:00:02
ResponseTimeout: 00:30:00
ResponseTimeoutWithDebugger: 00:30:00
DropExpiredMessages: True
MaxMessageHeaderSize: 10485760
MaxMessageBodySize: 104857600
info: Orleans.Runtime.SiloOptionsLogger[0]
Configuration Orleans.Configuration.SiloOptions:
SiloName: Silo_61487
info: Orleans.Runtime.Silo[100401]
Silo Start()
info: Orleans.Runtime.Silo[100452]
Start local grain directory took 0 milliseconds to finish
info: Orleans.Runtime.MembershipService.MembershipTableManager[100603]
MembershipOracle starting on host MSTFCCK.local with SiloAddress S127.0.0.1:11111:68851927 at 2024-03-07 21:32:07.987 GMT
info: Orleans.Runtime.MembershipService.SystemTargetBasedMembershipTable[100635]
Creating in-memory membership table
info: Orleans.Runtime.MembershipService.MembershipTableSystemTarget[100637]
GrainBasedMembershipTable Activated.
info: Orleans.Runtime.Silo[0]
Grain Service OrleansDashboard.SiloGrainService registered successfully.
info: Orleans.Runtime.Silo[100452]
Init grain services took 9 milliseconds to finish
info: Orleans.Runtime.Silo[100452]
Start deployment load collector took 5 milliseconds to finish
info: Orleans.Runtime.MembershipService.SystemTargetBasedMembershipTable[100631]
Connected to membership table provider.
info: Orleans.Runtime.MembershipService.MembershipAgent[100663]
Joining
info: Orleans.Runtime.MembershipService.MembershipAgent[100604]
-BecomeActive
info: Orleans.Runtime.MembershipService.MembershipAgent[100605]
-Finished BecomeActive.
info: OrleansDashboard.Dashboard[0]
Dashboard listening on 8080
info: OrleansDashboard.SiloGrainService[102925]
Starting OrleansDashboard.SiloGrainService grain service on: S127.0.0.1:11111:68851927 x9DED6DA9, with range <(0 0], Size=x100000000, %Ring=100%>
info: Orleans.Runtime.Silo[0]
Grain Service OrleansDashboard.SiloGrainService started successfully.
info: OrleansDashboard.SiloGrainService[102934]
My range changed from <(0 0], Size=x100000000, %Ring=100%> to <(0 0], Size=x100000000, %Ring=100%> increased = True
info: Orleans.Hosting.SiloHostedService[0]
Orleans Silo started.
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Production
info: Microsoft.Hosting.Lifetime[0]
Content root path: /Users/mustafacicek/Workplace/SWDev/DynamicEventManager/DynamicConsumerGenerator/bin/Debug/net8.0
>>> Executing
info: Orleans.Runtime.Management.ManagementGrain[0]
GetDetailedHosts OnlyActive=True
>>> Execute Counter: 0
>>> Execute Counter: 1
info: Orleans.Runtime.Management.ManagementGrain[0]
GetDetailedHosts OnlyActive=True
info: Orleans.Runtime.SiloControl[0]
GetSimpleGrainStatistics
>>> Execute Counter: 2
>>> Execute Counter: 3
info: Orleans.Runtime.Management.ManagementGrain[0]
GetDetailedHosts OnlyActive=True
info: Orleans.Runtime.SiloControl[0]
GetSimpleGrainStatistics
>>> Execute Counter: 4
>>> Executed
warn: Orleans.Grain[0]
Exception disposing activation [Activation: S127.0.0.1:11111:68851927/executor/562D707F@f18269b47f5340dda15ecd34342c0049#GrainType=ExecutorGrain,DynamicConsumerGenerator Placement=RandomPlacement State=Invalid]
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'IServiceProvider'.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ThrowHelper.ThrowObjectDisposedException()
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(ServiceIdentifier serviceIdentifier, ServiceProviderEngineScope serviceProviderEngineScope)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetService[T](IServiceProvider provider)
at Orleans.Runtime.ActivationData.GetComponent[TComponent]() in /_/src/Orleans.Runtime/Catalog/ActivationData.cs:line 257
at Orleans.Runtime.ActivationData.SetGrainInstance(Object grainInstance) in /_/src/Orleans.Runtime/Catalog/ActivationData.cs:line 305
at Orleans.Runtime.ActivationData.UnregisterMessageTarget() in /_/src/Orleans.Runtime/Catalog/ActivationData.cs:line 1829
at Orleans.Runtime.ActivationData.FinishDeactivating(CancellationToken cancellationToken) in /_/src/Orleans.Runtime/Catalog/ActivationData.cs:line 1731
fail: Orleans.Runtime.GrainTimer[101413]
Caught and ignored exception thrown from timer callback for timer GrainTimer.sys.svc.user.95B6CAE6/127.0.0.1:11111@68851927Timer TimerCallbackHandler:[SystemTarget: S127.0.0.1:11111:68851927/sys.svc.user.95B6CAE6/127.0.0.1:11111@68851927@0d73e76f00000000311eb42200000000]->System.Threading.Tasks.Task <Start>b__11_0(System.Object)
System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'IServiceProvider'.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ThrowHelper.ThrowObjectDisposedException()
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetServiceOrCreateInstance[T](IServiceProvider provider)
at Orleans.Serialization.GeneratedCodeHelpers.OrleansGeneratedCodeHelper.GetService[TService](Object caller, ICodecProvider codecProvider) in /_/src/Orleans.Serialization/GeneratedCodeHelpers/OrleansGeneratedCodeHelper.cs:line 72
at OrleansCodeGen.Orleans.Runtime.Proxy_IManagementGrain..ctor(GrainReferenceShared arg0, IdSpan arg1) in /_/src/Orleans.Core/Orleans.CodeGenerator/Orleans.CodeGenerator.OrleansSerializationSourceGenerator/Orleans.Core.orleans.g.cs:line 1115
at Proxy_IManagementGrain(Object, GrainReferenceShared, IdSpan)
at Orleans.GrainReferences.GrainReferenceActivatorProvider.GrainReferenceActivator.CreateReference(GrainId grainId) in /_/src/Orleans.Core/GrainReferences/GrainReferenceActivator.cs:line 380
at Orleans.GrainReferences.GrainReferenceActivator.CreateReference(GrainId grainId, GrainInterfaceType interfaceType) in /_/src/Orleans.Core/GrainReferences/GrainReferenceActivator.cs:line 57
at Orleans.GrainFactory.GetGrain(Type interfaceType, IdSpan grainKey, String grainClassNamePrefix) in /_/src/Orleans.Core/Core/GrainFactory.cs:line 217
at Orleans.GrainFactory.GetGrain[TGrainInterface](Int64 primaryKey, String grainClassNamePrefix) in /_/src/Orleans.Core/Core/GrainFactory.cs:line 51
at OrleansDashboard.SiloGrainService.CollectStatistics(Boolean canDeactivate)
at Orleans.Runtime.GrainTimer.ForwardToAsyncCallback(Object state) in /_/src/Orleans.Runtime/Timers/GrainTimer.cs:line 116
In your sample, the silo will stop after await executorGrain.Execute();
returns, no?
In your sample, the silo will stop after
await executorGrain.Execute();
returns, no?
@benjaminpetit for this implementation, yes. But normally, it will keep running, and I plan to consume events.