Skip to content

Instantly share code, notes, and snippets.

@egil
Created August 26, 2025 07:20
Show Gist options
  • Select an option

  • Save egil/6493f37770bc4d6fad67d67f47098941 to your computer and use it in GitHub Desktop.

Select an option

Save egil/6493f37770bc4d6fad67d67f47098941 to your computer and use it in GitHub Desktop.
Activate grain on silo startup
public interface IExampleGrain : IStartupGrain, IGrainWithIntegerKey { }
public class ExampleGrain : Grain, IExampleGrain
{
public override Task OnActivateAsync(CancellationToken cancellationToken)
{
// do things
}
}
// in Program.cs
builder.Services.AddStartupGrain<IExampleGrain>(0);
public interface IStartupGrain : IAddressable
{
Task StartAsync() => Task.CompletedTask;
}
internal sealed partial class StartupGrainInvokerBackgroundService<TStartupGrain>(
Func<TStartupGrain> startupGrainFactory,
ILogger<StartupGrainInvokerBackgroundService<TStartupGrain>> logger) : IHostedLifecycleService
where TStartupGrain : IStartupGrain
{
private Task StartedAsync(CancellationToken stoppingToken)
{
LogStartingGrain(typeof(TStartupGrain).FullName ?? typeof(TStartupGrain).Name);
var grain = startupGrainFactory();
return grain.StartAsync();
}
[LoggerMessage(Level = LogLevel.Information, Message = "Starting grain {GrainType}.")]
private partial void LogStartingGrain(string grainType);
Task IHostedService.StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
Task IHostedLifecycleService.StartedAsync(CancellationToken cancellationToken) => StartedAsync(cancellationToken);
Task IHostedLifecycleService.StartingAsync(CancellationToken cancellationToken) => Task.CompletedTask;
Task IHostedService.StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
Task IHostedLifecycleService.StoppedAsync(CancellationToken cancellationToken) => Task.CompletedTask;
Task IHostedLifecycleService.StoppingAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}
public static class StartupGrainInvokerBackgroundServiceExtensions
{
public static IServiceCollection AddStartupGrain<TStartupGrain>(this IServiceCollection services, string grainId)
where TStartupGrain : IStartupGrain, IGrainWithStringKey
{
services.AddHostedService(s => new StartupGrainInvokerBackgroundService<TStartupGrain>(
() => s.GetRequiredService<IGrainFactory>().GetGrain<TStartupGrain>(grainId),
s.GetRequiredService<ILogger<StartupGrainInvokerBackgroundService<TStartupGrain>>>()));
return services;
}
public static IServiceCollection AddStartupGrain<TStartupGrain>(this IServiceCollection services, Guid grainId)
where TStartupGrain : IStartupGrain, IGrainWithGuidKey
{
services.AddHostedService(s => new StartupGrainInvokerBackgroundService<TStartupGrain>(
() => s.GetRequiredService<IGrainFactory>().GetGrain<TStartupGrain>(grainId),
s.GetRequiredService<ILogger<StartupGrainInvokerBackgroundService<TStartupGrain>>>()));
return services;
}
public static IServiceCollection AddStartupGrain<TStartupGrain>(this IServiceCollection services, int grainId)
where TStartupGrain : IStartupGrain, IGrainWithIntegerKey
{
services.AddHostedService(s => new StartupGrainInvokerBackgroundService<TStartupGrain>(
() => s.GetRequiredService<IGrainFactory>().GetGrain<TStartupGrain>(grainId),
s.GetRequiredService<ILogger<StartupGrainInvokerBackgroundService<TStartupGrain>>>()));
return services;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment