Set time for scheduled task via ASP.NET - asp.net

I have to solve the following problem. We got an ASMX web service which is requested every two minutes. If this service is not requested for ten minutes an email should be sent. We want to realize this by using the scheduled tasks. We imagined it like this
1. Creating a scheduled task which will send an email every ten minutes
2. If the service is requested the execution time for the task will be set to ten minutes from now and so the execution time cannot be reached
- If the service is not requested the execution time will be reached and the email is sent
Is there a way to solve this in ASP.NET or are there maybe better solutions?
Thanks for any response.

You may want to take a look at the Revalee open source project.
You can use it to schedule web callbacks at specific times. In your case, you could schedule a web callback (10 minutes in the future) every time your web service is used. When your web service receives the callback, it can determine whether or not the service has been used recently. If the web service has been active, then the callback is ignored; if the web service has been inactive, then it can send out an email message.
For example using Revalee, you might:
Register a future (10 minutes from now) callback when your application launches.
private DateTimeOffet? lastActive = null;
private void ScheduleTenMinuteCallback()
{
// Schedule your callback 10 minutes from now
DateTimeOffset callbackTime = DateTimeOffset.Now.AddMinutes(10.0);
// Your web service's Uri
Uri callbackUrl = new Uri("http://yourwebservice.com/ScheduledCallback/YourActivityMonitor");
// Register the callback request with the Revalee service
RevaleeRegistrar.ScheduleCallback(callbackTime, callbackUrl);
}
Anytime your web service is used, you register another callback and store the date & time that your service was active as a global value.
lastActive = DateTimeOffset.Now;
ScheduleTenMinuteCallback();
Finally, when the web schedule task activates and calls your application back, then you test the value of the global
private void YourActivityMonitor()
{
if (!lastActive.HasValue || lastActive.Value <= DateTimeOffset.Now.AddMinutes(-10.0))
{
// Send your "10 minutes has elapsed" email message
}
}
I hope this helps.
Disclaimer: I was one of the developers involved with the Revalee project. To be clear, however, Revalee is free, open source software. The source code is available on GitHub.

Related

Net Core Async tasks

I have a web API over net core 3.0 and my API is using a mail DLL where I do some operations.
Web API controller:
_mailService.SendEmail();
Mail DLL:
public void SendEmail()
{
Console.Writeline("Registering at database");
RegisterAtDatabase(); //Do some stuff at database
SendMailToUser(); //Send mail to user. His operation takes about 1 minute
Console.Writeline("End mail proccess");
}
private void SendMailToUser()
{
Console.Writeline("Creating and sending mail");
//Here some stuff to send the mail. It takes about 1 minute
Console.Writeline("Mail sended");
}
I want to call _mailService.SendEmail() and not wait for the whole process. I want to write at the database and not wait for email sending process. So console output should be....
Registering at database
Creating and sending mail
End mail proccess
//After 1 minute
Mail sended
Is that possible using Task Async and await in some way?
I wanna return the control to the API while the email is sending.
Thanks
Is that possible using Task Async and await in some way?
No, that's not what async is for.
The proper solution is to write the work (e.g., "send this message to this email address") to a reliable queue (e.g., Azure Queue / Amazon SQS / etc), and then have a separate background process read and process that queue (e.g., ASP.NET Core background service / Azure Function / Amazon Lambda / etc).
You can use background Task queue for this kind of works and run them in the background.
full info at Microsoft Documents Background tasks with hosted services in ASP.NET Core

How to update service worker version of my subscribers?

i use minishlink/web-push for send pushes. And i make a service worker serviceworker.js for push messages, with push, notificationclick and notificationclose events listener.
To the site where the subscription takes place a have sw.js:
let timeStampInMs = new Date().getTime();
importScripts('https://super-push-site.com/serviceworker.js?ts=' + timeStampInMs);
It works fine.
But i make a new version of service worker and place it on old place (https://super-push-site.com/serviceworker.js).
How to update service worker version of my subscribers without their visit to the site where the subscription takes place?
Before answering your question, I would like to note that it's considered a bad practice to add a cache-buster parameter to your service worker URL, since the browser will already enqueue the new service worker for installation if it's byte-different to the existing service worker. You may read more about this on: The Service Worker Lifecycle
Now, to answer your actual question:
You can manually trigger the update by calling the update() method of your service worker registration, when a push message is received:
self.addEventListener('push', function (event) {
...
event.waitUntil(
Promise.all([
self.registration.showNotification(title, options);
self.registration.update()
])
);
});
You may also want to trigger self.registration.update() only if there actually is a newer version of the service worker available. To do that:
Store the version identifier of your SW in a variable.
Always send the latest SW version identifier within your push message payload.
Compare the two and trigger self.registration.update() if they don't match.
Hope this helps!

how to avoid any timeout during a long running method execution

I am working on an asp.net mvc 5 web application , deployed inside IIS-8, and i have a method inside my application to perform a long running task which mainly scans our network for servers & VMs and update our database with the scan results. method execution might last between 30-40 minutes to complete on production environment. and i am using a schedule tool named Hangfire which will call this method 2 times a day.
here is the job definition inside the startup.cs file, which will call the method at 8:01 am & 8:01 pm:-
public void Configuration(IAppBuilder app)
{
var options = new SqlServerStorageOptions
{
PrepareSchemaIfNecessary = false
};
GlobalConfiguration.Configuration.UseSqlServerStorage("scanservice",options);
RecurringJob.AddOrUpdate(() => ss.Scan(), "01 8,20 ***");
}
and here is the method which is being called twice a day by the schedule tool:-
public void Scan()
{
Service ss = new Service();
ss.NetworkScan().Wait();
}
Finally the method which do the real scan is (i only provide a high level description of what the method will do):-
public async Task<ScanResult> NetworkScan()
{
// retrieve the server info from the DB
// loop over all servers & then execute some power shell commands to scan the network & retrieve the info for each server one by one...
// after the shell command completed for each server, i will update the related server info inside the DB
currently i did some tests on our test environment and every thing worked well ,, where the scan took around 25 seconds to scan 2 test servers.but now we are planning to move the application to production and we have around 120++ servers to scan. so i estimate the method execution to take around 30 -40 minutes to complete on the production environment. so my question is how i can make sure that this execution will never expire , and the ScanNetwork() method will complete till the end?
Instead of worrying about your task timing out, perhaps you could start a new task for each server. In this way each task will be very short lived, and any exceptions caused by scanning a single server will not effect all the others. Additionally, if your application is restarted in IIS any scans which were not yet completed will be resumed. With all scans happening in one sequential task this is not possible. You will likely also see the total time to complete a scan of your entire network plummet, as the majority of time would likely be spent waiting on remote servers.
public void Scan()
{
Service ss = new Service();
foreach (var server in ss.GetServers())
{
BackgroundJob.Enqueue<Service>(s => s.ServerScan(server));
}
}
Now your scheduled task will simply enqueue one new task for each server.

Need advice in develop a queue job to interact between two application

Currently i have a web application and a wins form application in my server. Basically, the web application will receive request from user and this request will be send to the wins form application to proceed (wins form need about 1 minute to complete a request).
Let say 2 users send a request at the same time via web application, I need to develop a queue job to maintain the request in sequence.
1) User A make a request > request will be store into a queue job
2) User B make a request > request will be store into a queue job
3) The queue job will send the first request to the wins form. Once first request is complete, then will follow by the second request
So my question is, this queue job should be develop inside the web application? Or it should be develop in a stand alone wins form?
Any example code for create a queue job in ASP.NET?
Or anyone can suggest a better solution?
using System.Collections.Generic;
Queue<task> Q = new Queue<task>();
public void Proccess_Request(string info)
{
task t = new task();
t.INFO = info;
Q.Enqueue(task);
}
public void DoWork()
{
//
while (Q.Count > 0)
{
task t = Q.Dequeue();
//Process task t
}
}
public class task
{
public string INFO { get; set; }
// Whatever task properties you need
}
You will need to build the service that accepts form data and passes it to method Process_Request. You will also need to call method DoWork either once every x minutes, or have it listen for Process_Request to fire.
Or you can use MSMQ and do it that way. the ASP.NET site sends a message to the queue, the winforms app (or service) is bound to the queue so when messages come into the queue, it will pick it up, process it and let it be done until no more messages in the queue.
You can handle cross domain queue communication with MSMQ, for example.

Stoping web service in flex?

is it possible to stop a web service from executing?
I have a flex web application that searches clients with both full name and client id, when searching by name sometimes the usuer just types the last name and it takes a long time.
Since the app is used when clients are waiting in line, I would like to be able to stop the search and use their full name or id instead, and avoid waiting for the results and then having to search the user manually within the results.
thanks
edit: Sorry, I didn't explain myself correctly, when I meant "web service" I actually meant mx.rpc.soap.mxml.WebService, I want to stop it from waiting for the result event and the fault event. thanks.
There is actually a cancel(..) method explicitly for this purpose, though it is a little burried. Using the cancel method will cause the result and fault handlers not to be called and will also remove the busy cursor etc.
Depending on how you run your searches (ie. separate worker process etc), it is also possible to extend this by added in a cancelSearch() web service method to kill these worker processes and free up server resources etc.
private var _searchToken:AsyncToken;
public function doSearch(query:String):void
{
_searchToken = this.searchService.doSearch(query);
}
protected function doSearch_resultHandler(event:ResultEvent):void
{
trace("doSearch result");
trace("TODO: Do stuff with results");
_searchToken = null;
}
protected function doSearch_faultHandler(event:FaultEvent):void
{
trace("doSearch fault: " + event.fault);
_searchToken = null;
}
public function cancelSearch():void
{
var searchMessageId:String = _searchToken.message.messageId;
// Cancels the last service invocation or an invokation with the
// specified ID. Even though the network operation may still
// continue, no result or fault event is dispatched.
searchService.getOperation("doSearch").cancel(searchMessageId);
_searchToken = null;
trace("The search was cancelled, result/fault handlers not called");
// TODO: If your web service search method is using worker processes
// to do a search and is likely to continue processing for some time,
// you may want to implement a 'cancel()' method on the web service
// to stop any search threads that may be running.
}
Update
You could use disconnect() to remove any pending request responders, but it also disconnects the service's connection. Then call initialize().
/Update
You cannot stop the web service from executing, because that's beyond the Flex app's control, but you can limit the processing of the web service's response. For instance on the app, have a button like Cancel Search which sets a boolean bSearchCanceled to true.
The result handler for the web service call checks bSearchCanceled; if true just return.

Resources