Orleans When Use RedisGrainStorage for "PubSubStore" throw GrainReferenceNotBoundException - c#

Orleans Blazor Server Sample,it work well.
https://github.com/dotnet/orleans/tree/main/samples/Blazor/BlazorServer
I just use Redis Persistence replace memory storage
<PackageReference Include="Orleans.Persistence.Redis" Version="3.1.1" />
await Host.CreateDefaultBuilder(args)
.UseOrleans(builder =>
{
builder.UseLocalhostClustering();
//builder.AddMemoryGrainStorageAsDefault();
builder.AddRedisGrainStorageAsDefault((options) =>
{
options.ConnectionString = redisConnection;
options.UseJson = true;
options.DatabaseNumber = 1;
});
builder.AddSimpleMessageStreamProvider("SMS");
//builder.AddMemoryGrainStorage("PubSubStore");
builder.AddRedisGrainStorage("PubSubStore", options =>
{
options.ConnectionString = redisConnection;
options.UseJson = true;
options.DatabaseNumber = 2;
});
})
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.RunConsoleAsync();
It work well when first build and run. Redis database created datas.
But when runing again it thrown exception when calling:
public Task<StreamSubscriptionHandle<TodoNotification>> SubscribeAsync(Guid ownerKey, Func<TodoNotification, Task> action) =>
client.GetStreamProvider("SMS")
.GetStream<TodoNotification>(ownerKey, nameof(ITodoGrain))
.SubscribeAsync(new TodoItemObserver(logger, action));
the exception is
GrainReferenceNotBoundException: Attempted to use a GrainReference which has not been bound to the runtime: GrainReference:*grn/BlazorServer.TodoGrain/4794564e-4c87-4674-8722-f87f20559abe-0x3CAFC40C. Use the IGrainFactory.BindGrainReference method to bind this reference to the runtime.
my question is how could I fix this exception? Thanks.

Related

"Please ensure OpenTelemetry is configured via Steeltoe extension methods" error?

I'm getting this error every time that the endpoint /actuator/prometheus is being call.
I don't have any idea what could be the problem?
This is the initialization code (I'm sure that openTelemetryEndpoint variable has a value):
builder.Services.AddAllActuators();
builder.Services.AddPrometheusActuator();
// OpenTelemetry configuration
var openTelemetryServiceName = Environment.GetEnvironmentVariable("OTEL_SERVICE_NAME");
var openTelemetryEndpoint = Environment.GetEnvironmentVariable("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT");
if (!string.IsNullOrWhiteSpace(openTelemetryEndpoint))
{
// Configure metrics
builder.Services.AddOpenTelemetryMetrics(b =>
{
b.AddHttpClientInstrumentation();
b.AddAspNetCoreInstrumentation();
b.AddMeter(openTelemetryServiceName + "-metrics");
b.AddOtlpExporter(options =>
{
options.Endpoint = new Uri(openTelemetryEndpoint);
options.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc;
});
});
// Configure tracing
builder.Services.AddOpenTelemetryTracing(b =>
{
b.SetResourceBuilder(ResourceBuilder.CreateDefault().AddService(openTelemetryServiceName));
b.AddHttpClientInstrumentation();
b.AddAspNetCoreInstrumentation();
b.AddSource(openTelemetryServiceName + "-activity-source");
b.AddOtlpExporter(options =>
{
options.Endpoint = new Uri(openTelemetryEndpoint);
options.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc;
});
});
// Configure logging
builder.Logging.AddOpenTelemetry(b =>
{
b.IncludeFormattedMessage = true;
b.IncludeScopes = true;
b.ParseStateValues = true;
b.AddOtlpExporter(options =>
{
options.Endpoint = new Uri(openTelemetryEndpoint);
options.Protocol = OpenTelemetry.Exporter.OtlpExportProtocol.Grpc;
});
b.AddConsoleExporter();
});
}
Marcelo,
The error message is saying that you need to use the Steeltoe extension for Metrics: `AddOpenTelemetryMetricsForSteeltoe to get the desired functionality. Steeltoe internally uses OpentelemetryMetrics for its own exports for example /Metrics, /Prometheus and also Wavefront Exporter. If you want to in addition to these add an OLTP exporter you would in addition have to use the extension methods to add the additional configuration.

Microsoft.Extensions.Logging - Add multiple windows event logs

I have a .NET Core application, writing to Windows event viewer.
I'd like to map some of the logs to one source and some to other (based on the caller class).
The setup in Program.cs looks like that:
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, logging) =>
{
logging.ClearProviders();
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddEventLog(new EventLogSettings()
{
LogName = "CustomerSearchScheduler",
SourceName = "CustomerSearchScheduler",
Filter = (source, level) => source.Contains("Schedulers")
});
logging.AddEventLog(new EventLogSettings()
{
LogName = "CustomerSearch",
SourceName = "CustomerSearch",
Filter = (source, level) => source.Contains("CustomerSearch") && !source.Contains("Schedulers")
});
logging.AddConsole();
})
//Web Host defaults.........
}
Problem is, AddEventLogs seem to override one another. With the code above, nothing is printed to CustomerSearch and only CustomerSearchScheduler shows new logs. When I remove the CustomerSearchScheduler part, the second type works as expected.
How can I make the two work simultaneously?
Thanks
You'll need to explicitly add the event log provider to the service collection:
logging.Services.AddSingleton<ILoggerProvider>(new EventLogLoggerProvider(settings));
The default will not add the service provider twice

UseSendExecute in ConfigurePublish in MassTransit 5.2.1

In MassTransit 5.2.0 I used the method UseSendExecute inside ConfigurePublish for adding headers to a particular message type:
var bus = BusConfigurator.ConfigureBus((h,cfg) =>
{
h.ConfigurePublish(x =>
x.UseSendExecute<TestMessage>(p =>
{
p.Headers.Set("x-deduplication-header", p.Message.Day.Ticks);
}));
});
After upgrading to MassTransit 5.2.1 the method UseSendExecute is not longer available inside ConfigurePublish.
Digging a little inside MassTransit changes I found that the problem happens because MassTransit.IPublishPipeConfigurator no longer implements MassTransit.ISendPipeConfigurator and UseSendExecute is an extension method for ISendPipeConfigurator inside MassTransit.DelegatePipeConfiguratorExtensions.
How can I set the same publish configuration using 5.2.1 version?
Well, you're configuring a publish behavior. The new syntax would be:
var bus = BusConfigurator.ConfigureBus((h,cfg) =>
{
h.ConfigurePublish(pc => pc.AddPipeSpecification(
new DelegatePipeSpecification<PublishContext<TestMessage>>(p =>
{
p.Headers.Set("x-deduplication-header", p.Message.Day.Ticks);
})));
});

Hangfire duplicates jobs on server restart

So we have an .NET Core API which uses hangfire as a task scheduler.
On startup, our API starts the following functions :
public void CreateTasks()
{
/* DATABASE TASKS */
SyncDatabaseTask();
/* SMS TASKS */
SendSmsTask();
}
public void SendSmsTask()
{
var taskId = BackgroundJob.Schedule(() => _smsService.SendSms(), TimeSpan.FromMinutes(30));
BackgroundJob.ContinueWith(taskId, () => SendSmsTask());
}
This creates the job SendSmsTask in Hangfire on startup and does not start a second job until the first one has been completed.
The issue that we just noticed however is that whenever our API reboots (server update for example) the existing jobs are still running and news jobs are being added.
So we would like to remove all scheduled or running jobs on startup.
I've looked through the documentation (http://docs.hangfire.io/en/latest/) but couldn't really find a solution for this issue.
This should solve your problem, just note that this is untested.
private void RemoveAllHangfireJobs()
{
var hangfireMonitor = JobStorage.Current.GetMonitoringApi();
//RecurringJobs
JobStorage.Current.GetConnection().GetRecurringJobs().ForEach(xx => BackgroundJob.Delete(xx.Id));
//ProcessingJobs
hangfireMonitor.ProcessingJobs(0, int.MaxValue).ForEach(xx => BackgroundJob.Delete(xx.Key));
//ScheduledJobs
hangfireMonitor.ScheduledJobs(0, int.MaxValue).ForEach(xx => BackgroundJob.Delete(xx.Key));
//EnqueuedJobs
hangfireMonitor.Queues().ToList().ForEach(xx => hangfireMonitor.EnqueuedJobs(xx.Name,0, int.MaxValue).ForEach(x => BackgroundJob.Delete(x.Key)));
}
If you still interest Pieter Alberts solution.
Some little changes on that.
If you use old code and you have old job in db, you will get Format Exception.
In //RecurringJobs section you have to change line like this:
JobStorage.Current.GetConnection().GetRecurringJobs().ForEach(xx => RecurringJob.RemoveIfExists(xx.Id));
TL;DR
Old Code:
private void RemoveAllHangfireJobs()
{
var hangfireMonitor = JobStorage.Current.GetMonitoringApi();
//RecurringJobs
JobStorage.Current.GetConnection().GetRecurringJobs().ForEach(xx => BackgroundJob.Delete(xx.Id));
//ProcessingJobs
hangfireMonitor.ProcessingJobs(0, int.MaxValue).ForEach(xx => BackgroundJob.Delete(xx.Key));
//ScheduledJobs
hangfireMonitor.ScheduledJobs(0, int.MaxValue).ForEach(xx => BackgroundJob.Delete(xx.Key));
//EnqueuedJobs
hangfireMonitor.Queues().ToList().ForEach(xx => hangfireMonitor.EnqueuedJobs(xx.Name,0, int.MaxValue).ForEach(x => BackgroundJob.Delete(x.Key)));
}
New Code:
private void RemoveAllHangfireJobs()
{
var hangfireMonitor = JobStorage.Current.GetMonitoringApi();
//RecurringJobs
JobStorage.Current.GetConnection().GetRecurringJobs().ForEach(xx => RecurringJob.RemoveIfExists(xx.Id)); // this line changed!
//ProcessingJobs
hangfireMonitor.ProcessingJobs(0, int.MaxValue).ForEach(xx => BackgroundJob.Delete(xx.Key));
//ScheduledJobs
hangfireMonitor.ScheduledJobs(0, int.MaxValue).ForEach(xx => BackgroundJob.Delete(xx.Key));
//EnqueuedJobs
hangfireMonitor.Queues().ToList().ForEach(xx => hangfireMonitor.EnqueuedJobs(xx.Name,0, int.MaxValue).ForEach(x => BackgroundJob.Delete(x.Key)));
}
PS Edit:
My Hangfire version is 1.7.9
and using Hangfire.PostgreSql
//Start Hangfire Server
var varJobOptions = new BackgroundJobServerOptions();
varJobOptions.ServerName = "job.fiscal.io";
varJobOptions.WorkerCount = Environment.ProcessorCount * 10;
app.UseHangfireServer(varJobOptions);
app.UseHangfireDashboard("/jobs", new DashboardOptions {
Authorization = new[] { new clsHangFireAuthFilter() }
});
//Remove Duplicte HangFire Server
var varMonitoringApi = JobStorage.Current.GetMonitoringApi();
var varServerList = varMonitoringApi.Servers().Where(r => r.Name.Contains("job.fiscal.io"));
foreach( var varServerItem in varServerList) {
JobStorage.Current.GetConnection().RemoveServer(varServerItem.Name);
}
HF 1.7.28
For me deleting Enqueued jobs like suggested did not work.
Instead, I had to use the following:
hangfireMonitor.Queues().ToList().ForEach(x => x.FirstJobs.Where(j => j.Value.InEnqueuedState).ToList().ForEach(x => BackgroundJob.Delete(x.Key)));

Topshelf WhenContinued not working

Topshelf is not working when I add whencontinued in the configuration. It is working fine with start and stop methods. I do not have any code in continue method that would block it from running ( simple console.writeline )
HostFactory.Run(x =>
{
x.SetDescription("Data Service - POC");
x.SetDisplayName("Data Service");
x.SetServiceName("DataService");
x.EnablePauseAndContinue();
x.Service<SampleService>(s =>
{
s.ConstructUsing(() => new SampleService());
s.WhenStarted(v => v.Start());
s.WhenStopped(v => v.Stop());
// s.WhenContinued(v => v.Continue());
});
x.RunAsLocalSystem();
});
what am I missing ?
It is compiling fine. It is not calling any of my methods . I see console flash and disappear. I cant even read what is on that console. If I comment out the line s.WhenContinued(v => v.Continue()); it is working fine
It requires pause to be configured as well. once I added pause method to configuration it started working.
HostFactory.Run(x =>
{
x.SetDescription("Data Service - POC");
x.SetDisplayName("Data Service");
x.SetServiceName("DataService");
x.EnablePauseAndContinue();
x.Service<SampleService>(s =>
{
s.ConstructUsing(() => new SampleService());
s.WhenStarted(v => v.Start());
s.WhenStopped(v => v.Stop());
s.WhenPaused(v => v.AnotherPause());
s.WhenContinued(v => v.Continue());
});
x.RunAsLocalSystem();
});

Categories