1

At the moment im doing a chat web app where multiple users can chat and it can control multiple rooms. Its working and getting the job done.

Right now its using ajax(jquery is used) and just use GET to the server.aspx with different query parameters and then return some content.(It is meant to be build into a larger project later on)

But I have one thing that I cannot figure out how to build for it and hopin' someone had a splendid idea :)

A "Keep Alive" (or TimeToLive) service on the users. The service should ensure when a user disconnects(machine crash - Browser/window close) the user times out from the chat room.

My idea was that on every request from the user TO the server it should update a TTL list(a list with a userid and a "timestamp") and this part is easy.

Now comes my challenge

Then there should be some service running on the server that continuesly checks this TTL list to see if any stamps has run out and if it has remove the user from the room

But how and where can I do this server service in .net ? Or do you have another approch ? :)

3 Answers3

2

I would just have a table called something like "LastPing" with user id and a date. Put a piece of javascript which calls a page on your site at regular intervals (window.setInterval(...)) - that page just updates the table with the current datetime or does an insert if no rows are updated.

Finally, create a sql server job/task that selects user id from Lastping where date is older than currentdate - 30 mins (or whatever). Those user ids get deleted from any chat rooms etc. and finally removed from the LastPing table.

I think that's about it :)

Nathan
  • 6,095
  • 2
  • 35
  • 61
  • ps - maybe include the session id in the table too: if a user moves from one machine to another and is logged in on both, you don't want the session that dies on the old machine to boot their new session out of the chat rooms! – Nathan May 05 '11 at 07:47
  • Thanks to you aswell @Nathan think ill go with a combo of yours and @Tr1stan – Rasmus Fjord May 05 '11 at 09:07
1

You could run a Console Application (or run it as a Windows Service) that could scan your TTL list using a Timer that ticks on a set interval to process them as you wish. Could all be done in .net, preventing you from having to store your business logic in an SSIS package within SQL server.

If you're going down this path I would recommend writing a windows service that can also be run as a console app. Query the Environment.UserInteractive property to work out which version is being run - this will help with your development because a console application can be a little more verbose than a windows service.

Here is a code sample:

public partial class Service1 : ServiceBase
{
    //Need to keep a reference to this object, else the Garbage Collector will clean it up and prevent further events from firing.
    private System.Threading.Timer _timer;

    static void Main(string[] args)
    {
        if (Environment.UserInteractive)
        {
            var service = new Service1();
            Log.Debug("Starting Console Application");

            service.OnStart(args);
            // The service can now be accessed.
            Console.WriteLine("Service ready.");
            Console.WriteLine("Press <ENTER> to terminate the application.");
            Console.ReadLine();
            service.OnStop();

            return;
        }
        var servicesToRun = new ServiceBase[] 
                                          { 
                                              new Service1() 
                                          };
        Run(servicesToRun);
    }

    public Service1()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        // For a single instance, this is a bit heavy handed, but if you're creating of a number of them
        // the NT service will need to return in a short period of time and thus I use QueueUserWorkItem
        ThreadPool.QueueUserWorkItem(SetupTimer, args);
    }

    protected override void OnStop()
    {
    }

    private void SetupTimer(object obj)
    {


        //Set the emailInterval to be 1 minute by default
        const int interval = 1;
        //Initialize the timer, wait 5 seconds before firing, and then fire every 15 minutes
        _timer = new Timer(TimerDelegate, 5000, 1, 1000 * 60 * interval);
    }
    private static void TimerDelegate(object stateInfo)
    {
            //Perform your DB TTL Check here
    }

}
Community
  • 1
  • 1
Tr1stan
  • 2,755
  • 1
  • 26
  • 45
  • I think this is a good idea. My thought was to keep the TTL list in the DB, but that would generate alot of traffic for that list, is there someway that i can share a list object between my webapp and a console app ? or what would you suggest ? – Rasmus Fjord May 05 '11 at 08:57
  • sweet :) alot of thanks @Tr1stan I really dig the example(havn't done a console app before for a 'real' project) so think ill go down this path combined with the idea from @Nathan on keeping a DB table as TTL and the console app will raise a flag(through a http) if there is any changes to webapp and telling the next user to update a shared List Object so ill save some DB roundtrips – Rasmus Fjord May 05 '11 at 09:06
  • @Rasmus Fjord: You're welcome. I find this is a good approach if you want to process things that are independent to the website app pools running. In your case this might be a little overkill (with what I know about it) because if the site is not up then the users can't use it anyway. Therefore you could use a similar approach, either querying the DB or keeping the TTL live in memory, but setup the timer calls in the Global.asax Application_OnStart event - then everything will be kept within the web application itself. – Tr1stan May 05 '11 at 09:13
0

For that type of solution, you would need to setup a separate Thread that is periodically checking for users to expire, or utilize a library for scheduled tasks and similarly setup a scheduled task.

DuckMaestro
  • 15,232
  • 11
  • 67
  • 85