HangFire Server Enable - Disable manually - c#

During development of HangFire application with C# ASP.NET, and I decided to implement functionally where Admin can manage state of Server, jobs.
List item
Server Enable Disable state. Using Enable Button click event Admin
can start JOB server so all the Fire and Forget and Recurrent job can
performed. And Disable button stop all the activities of JOB.
Retrieve the current state of Server
I want to retrieve current state of JOB server, So I can show is
server is on or Off.
Retrieve state and enable / disable state of Jobs (Only recurrent).

If you want to manage Server/Job created by Hangfire, you can use MonitoringApi or JobStorage to get there statuses.
Sample Codes :
var _jobStorage = JobStorage.Current;
// How to get recurringjobs
using (var connection = _jobStorage.GetConnection())
{
var storageConnection = connection as JobStorageConnection;
if (storageConnection != null)
{
var recurringJob = storageConnection.GetRecurringJobs();
foreach(var job in recurringJob)
{
// do you stuff
}
}
}
// How to get Servers
var monitoringApi = _jobStorage.GetMonitoringApi();
var serverList = monitoringApi.Servers();
foreach( var server in serverList)
{
// do you stuff with the server
// you can use var connection = _jobStorage.GetConnection()
// to remove server
}
From here you can play around with Hangfire.

Related

Single session enforcement using signalR/Long polling

I want to implement single session enforcement in my application. Meaning if another login activity found for the same user in different browser/different machine then then first session should get auto logoff. If I use the Ajax polling then unnecessary network traffic will happen. So am planning to use signalR.
For that i tried simple click event. Its working without refreshing the page from browser 1 to browser 2.
I created hubclass and my cshtml as follows
var myHub = $.connection.myHub;
$.connection.hub.logging = true;
$.connection.hub.start();
myHub.client.Postmessage = function (message) {
$('#message1').append('<li><strong>'+ htmlEncode(messaage) + '</li>')
$("btnClick").click(function () (
var message = $('message').val();
myHub.server.helloServer(message);
$('#message1').val('').focus();
External service class to find the session details
private static ISSEnforcementSvc ssEnforcement;
public static SSEnforcementSVC GetSSEnforcementService()
{
if (ssEnforcement == null)
{
var localService GetLocalizationsvc;
var configurationSvc = GetConfigurationSvc();
var cacheSvc = GetCacheSvc();
ssessionEnforcement Service = new
SinglesessionEnforcementService(localService,
configurationSvc,cacheSvc)
}
return ssEnforcement;
}
Please suggest how to implement same way to push the 1st browser to logoff.

How to subscribe to Redis events with C#

I have a remote computer which is uses Redis. I want to receive notifications about it Redis events (updates, new keys etc.). I've searched online for solution and landed on StackExchange.Redis, then i've started to create windows service that will listen to Redis events. I have found code example:
var endp = "x.x.x.x:xxxx"
using (ConnectionMultiplexer connection = ConnectionMultiplexer.Connect(endp))
{
IDatabase db = connection.GetDatabase();
ISubscriber subscriber = connection.GetSubscriber();
int f = 0;
subscriber.Subscribe("__keyspace#0__:*", (channel, value) =>
{
if ((string) channel != null)
{
f++;
// Do stuff if some item is added to a hypothethical "users" set in Redis
}
}
);
}
for now i wan't to get all of it events and just increase counter. Is this enough or i've missed something?

How to force hangfire server to remove old server data for that particular server on restart?

I am showing list of hangfire servers currently running on my page.
I am running hangfire server in console application but the problem is when I don't have my console application running still hangfire api returns hangfire servers.
Moreover when I run my console application multiple times I get 3-4 hangfire servers though I have only 1 hangfire server running in console application.
Mvc application :
IMonitoringApi monitoringApi = JobStorage.Current.GetMonitoringApi();
var servers = monitoringApi.Servers().OrderByDescending(s => s.StartedAt);
Console Application:Hangfire server
public static void Main(string[] args)
{
var sqlServerPolling = new SqlServerStorageOptions
{
QueuePollInterval = TimeSpan.FromSeconds(20) // Default value
};
GlobalConfiguration.Configuration.UseSqlServerStorage("ConnectionString", sqlServerPolling);
// Set automatic retry attempt
GlobalJobFilters.Filters.Add(new AutomaticRetryAttribute { Attempts = 0 });
// Set worker count
var options = new BackgroundJobServerOptions
{
WorkerCount = 1,
};
using (var server = new BackgroundJobServer(options))
{
Console.WriteLine("Hangfire Server1 started. Press any key to exit...");
Console.ReadKey();
}
}
Hangfire server doenst automatically remove old server data whenever I run my console application again for that particular server?
I will appreciate any help :)
I dug through the source code to find:
IMonitoringApi monitoringApi = JobStorage.Current.GetMonitoringApi();
var serverToRemove = monitoringApi.Servers().First(); //<-- adjust query as needed
JobStorage.Current.GetConnection().RemoveServer(serverToRemove.Name)
If you want to see the code yourself, here are the related source code files:
Mapping of db server.Id
Background server announcement
Delete server from db with id
Code to generate server id
Via the last link, it's also clear that you can customize your server name to make it easier to find and remove:
var options = new BackgroundJobServerOptions
{
WorkerCount = 1,
ServerName = "removeMe",
};
// ....
IMonitoringApi monitoringApi = JobStorage.Current.GetMonitoringApi();
var serverToRemove = monitoringApi.Servers().First(svr => srv.Name.Contains("removeMe"));
JobStorage.Current.GetConnection().RemoveServer(serverToRemove.Name);
Follow the code to remove duplicate in the same server.
//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);
}

SignalR - Pushing notification to servers

When I try to broadcast a message to all clients, I can trigger client's javascript code from server and get the job done.
But this time my aim is to trigger a method in all servers. For example, when roles of a user changed in one server, I want to warn other servers about this operation and I want to make other servers retrieve updated user role list for particular user.
Is it possible to do this with SignalR? Can a server behave like a client (browser)?
Yes you can do that.
Let's say you have the following hub:
public class TheHub : Hub
{
public void RoleChanged(int userId)
{
Clients.All.roleChanged(userId);
}
}
On all the listening servers, you'd have to do:
var _connection = new HubConnection("http://localhost:1234/signalr");
var _theHub = _connection.CreateHubProxy("TheHub");
_myHub.On<int>("RoleChanged", userId =>
{
System.Diagnostics.Debug.WriteLine("Changed user's Id: " + userId);
});
_connection.Start().Wait();
To invoke the RoleChanged event, do:
_myHub.Invoke("RoleChanged").Wait();

Listening to Events in the calendar from more than one person using EWS API

Simply I would like to receive a notification every time someone added a new appointment or made any changes on what he/she has.
The only way I know how to do it , is by using
service.SubscribeToStreamingNotifications
but the problem here that it only listens to the account that the service is bound to like in this way
var service = new ExchangeService(ExchangeVersion.Exchange2010_SP2)
{
Credentials = new WebCredentials(userName, password)
};
service.SubscribeToStreamingNotifications(new FolderId[]
{
WellKnownFolderName.Calendar
}, EventType.FreeBusyChanged, EventType.Deleted);
I have solved this problem by creating a list of services each service is bounded to different user and the application should listen to each of them.
The problem with this way is that I need to have the password of each account I wont to listen to its events, which is not possible in real world.
so is there any way to deal with that ?
I have solved this problem, by creating a list of services, all the services are a clone of the main ExchangeService, with the same credentials for the admin account, but they are impersonated to the other accounts.
NOTE: You need to setup the server so it allows impersonation.
private void ImpersonateUsers(ICollection<string> userSmtps)
{
if (userSmtps != null)
if (userSmtps.Count > 0)
{
foreach (var userSmtp in userSmtps)
{
if (_services.ContainsKey(userSmtp)) continue;
var newService = new ExchangeService(ExchangeVersion.Exchange2010_SP2);
try
{
var serviceCred = ((System.Net.NetworkCredential)(((WebCredentials)(_services.First().Value.Credentials)).Credentials));
newService.Credentials = new WebCredentials(serviceCred.UserName, serviceCred.Password, serviceCred.Domain);
newService.AutodiscoverUrl(serviceCred.UserName + "#" + serviceCred.Domain, RedirectionUrlValidationCallback);
newService.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, userSmtp);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
_services.Add(userSmtp, newService);
}
}
}
Where userSmtps is a list of the email addresses I want to impersonate and _services is the dictionary of services where the first member is the main service.
you will have to create a service instance per user. There is no way to subscribe to other users folder.
But instead of StreamingNotifications you can use Pull and Push-Subscriptions too.
Something like this:
List<FolderId> folders = new List<FolderId>();
folders.Add(new FolderId(WellKnownFolderName.Calendar));
PullSubscription subscription = = service.SubscribeToPullNotifications(folders, 1440, watermark, EventType.Created, EventType.Deleted, EventType.Modified, EventType.Moved, EventType.NewMail);
Some time later....
GetEventsResults currentevents = m_subscription .GetEvents();

Categories