PHP: how to update user logged in timer without using AJAX calls - php

I am creating a web application named Online Exam using PHP+MySQL and AngularJS. Now I am getting some trouble on project like changing the user looged in status. Let us take this condition as a example:
Suppose a authorized user/student successfully logged in online exam section(After successfully logged current time will be inserted in the db in exam_start_time column as unix timestamp format and exam_status will be set as 'ACTIVE`.
1hr(60 min) countdown timer is initialize for him/her as per the inserted exam_start_time in db.
Now suppose after 15 min the system shuts down automatically, then if user logged in again(In same system or other) then the countdown timer should be set for 45 minutes only.
Previously I was updating the last_activity_time in our table in every 10 sec(using ajax calls). but now I want to change this way, Is there any way like(socket or network programming using PHP) to update the column.
Here is my table structure which is managing user logged in status
Please give me some suggestions on it.

A Php socket server programming tutorial : http://www.christophh.net/2012/07/24/php-socket-programming/

Sockets, as Pascal Le Merrer mentioned, is IMO your best option. But beware of Apache! Every WebSocket holds one Apache thread, and Apache wasn't designed to do that. when too many (and by too many I mean few dozen) clients connect to your site, it will crash. (I've been there while trying to implement long polling/comet, ended up using NodeJS. If you're using nginx, it is more likely that it will become low on resources and effective, but there are also other ways. Take a look here:
Using WebSocket on Apache server
If you find this uncomfortable/hard to learn, try also another idea:
try to add hidden iFrame to your exam page, pointing to prepared site that updates database row. Use javascript to refresh this page every 10-15 seconds. Every refresh causes update of specific row in DB, using current date and time. It should work (not tested, but give it a try).

Related

Running a function/script per user on the server side

I'm working on a basic lamp(willing to change) website , and I currently need a way to run some function on the server that runs for several hours per user, and every X hours it needs to query the mysql database to see if the value for that user has been updated, if it hasn't it need it to insert a new record in the database...I also should mention that the 'every X hours' can change per user too, and the total runtime of the function per user can also vary.
So basically I need a function that runs continuously on the server for few hours per user. What is the best way to do this? I want the site to be able to support many users (like 10000 +).
I'm willing to try new technologies for every aspect of the site, I'm still in the design phase and I was looking for some input.
I've looked at cron but not really sure how well it would work when dealing with so many users...
edit: Here is a typical scenario of events;
User presses button on the website and closes the browser.
Server starts a timer from when they pressed the button, now
the server will check if that user has pressed a different button within a given time frame (time frame can change per user), say within 30 minutes. If they didn't press the other button then the server needs to automatically insert a new record in the database.
The script will need to continue running, checking every 30 mins for say the next 5 hours.
Thank you!
Cron would work as well as you can code the page it will run. It's not a cron limitation.
The question is ambiguous btw. Maybe explaining your full scenario would help.
Meanwhile, my suggestion would be to set up a scrip that allows you to manually check what you need to check.
You definitely need the DB to be InnoDB optimized with proper indexes to be able to support 1000 plus users.
To alleviate the number of calls to the database, a common practice is to run scripts only on what you are interested (so in the case of users you would only select those who have logged on in say the past 3 hours)
That's achievable in 2 ways, a simple select statement, or by adding entries to a specific table on the login page, and remove them after the automated script has finished running.
All of this is pure theory without understanding exactly what you need to do though.
You are telling what/how you want to do, but not why you want to do it. Maybe letting us know why could lead to a different how ;)
However, what you can do is still use cron (or anything similar). The trick is to have
a last_interaction timestamp column
a maximum_interval column
a daily_runtime column
in your users database. Not optimized but you are in the design phase so you shouldn't pay too much attention to the performance aspect (except is explicitly required).

is it possible to update mysql with timed intervals without a client request

I have working on game where users can send each other challenges. These challenges have timed intervals, say hours, days etc.
When a user logs in the times set can be retrieved through mysql then displayed as a countdown clock using java script to show and countdown remaining time. If the time runs out the database can be updated to display this. This works fine if users are logged in but what if the time set ends when nobody is logged in.
So is there a way of running something constantly on the server to check these countdowns and change the database if the time has ran out or would it work better check the timer when a user views the challenge then act accordingly.
to clarify:
Option 1. Automated script that runs on a server checking the times of each challenge. Either by having a computer constantlylogged in running an ajajar request with an interval timer. (Preferably without a computer and ajax)
Option 2: when a user views the challenge the time is worked out. If the time has ended update this in the database so the challenge now shows up as ended.
If option 1 is possible is it better and how would this Work?
Yes, you can. Use dates. Go with date_created and date_expired. If the current time exceeds the date expired time, etc etc.
are you looking to delete the expired challenges? or set a flag, so the user knows they existed but expired?
depending on your SQL version, look into 'Events'. it's similar to a CRON job, but is run on the SQL server. i would say this is a good option if available to you.

Updating db tables based on user activity

I have log table for all users of website
I'm recording various data about user righ after successfull login.
If signout_dt field not filled and status is 1 for some user_id, website prevents login automatically.
For that who have cookies - there is no problem.
The problem is,lets say user signed in without cookies: only sessions variables. I have no idea, how can I update db table and signout user let's say after 30 minute inactivity. Note that I can't create cron job or something serverside, because using shared hosting.
Heard that, it's possible to create some script like heartbeat that continously sends some data about user activity. But I think this will heavily load the server especially if there are more than 1000 users.. Any suggestion, tutorial, article, something else?
Update
Deceze tried to explain but I really need better explanation (better idea), with code.
To "timeout" a user, simply note the time he was last seen. Then, when necessary, check if the last time you've seen the user was over x minutes/hours/days, and consider the last session timed out. You don't need to run a cron job or anything that cleans up after users in realtime, you only need to be able to determine if some information should be considered stale when you need that information.
You may want to occasionally run a cron job or something to clean out old, unnecessary data, but that doesn't need to happen in realtime. You could even run this as part of a regular page request:
if (mt_rand(1, 1000) == 1) {
mysql_query('DELETE FROM `table` WHERE `last_seen` < some point in time');
}
To note the last seen time, just run this query on each page load:
UPDATE `table` SET `last_seen` = NOW() WHERE `user_id` = ...
To avoid thrashing the database with these queries, you can also just do it every so often. Keep a "last_seen_last_updated" timestamp in the user's session, then on each page load check if you might want to update the database:
if ($_SESSION['last_seen_last_updated'] < strtotime('-5 minutes')) {
mysql_query(...);
$_SESSION['last_seen_last_updated'] = time();
}
That gives you 5 minutes of jitter, but that's usually perfectly acceptable.
Your management of sessions is broken and does not conform to accepted stateless behaviour - in as much as you apparently require the user to sign out, which rarely is the case in web applications -- most people just closes the browser, and the cookies will just float around and appear next time the user accesses the website. If the system wants the user to sign in again, then the web server will have to validate the session -- for example using a timestamp and/or cookie signing etc, and invalidate the cookie to force the user to re-login if needed.
Hence you should treat cookies and sessions variables the same -- that is; have your server side generate a unique signed value. Keep an expiration time (for example now()+20min) either in the cookie/session variable or keep the expiration time in the database.
At each access check that the cookie/session-variable is correctly signed, and check that it is not beyond the expiration time, and update the expiration time to allow another 20min.
If the access is past the expiration time -- i.e. the user has been idle for too long, then clear the cookie/session-variable and force the user to login again.
If you keep the expiration time in the database, you simply write a small program which once and day or once an hour run though all records and remove those which you deem too old.
As per my understanding of your question, you want to address following things:
a. If for a given period of time, a user is inactive then he should be logged out and your database table gets updated. Here being inactive means, user has not used keyboard/mouse for a given period of time.
b. If a user closes the browser without logging out, then he should be forcefully logged out and database table gets updated.
Both these things can be accomplished using Javascript Functions and Ajax. Following is the flow which we have in our application for addressing above issues:
Create a Javascript function, say logoutUser(), which will send an Ajax request for updating the database tables and destroying the session.
Use Javascript function - setTimeOut - to call logoutUser() function after time period you have set for inactivity.
Use Javascript events to catch mouse movement and keyboard activity and in every such event call use successively clearTimeOut (in order to remove the old time for execution of logoutUser()) and setTimeOut (for setting the new time of execution of logoutUser()). This way you would be able to catch the inactivity and logout the user after a period of time.
For taking care of the issue related to closing of browser window use 'onbeforeunload' event of javascript and in this event send the Ajax request for updating the database tables.
As our application uses ExtJS, thus, we have used ExtJs library functions to detect events. You can also prefer using some Javascript library for catching the events and implemeting the above solution.
Hope this helps.

daemon software to update mysql database in background

I'm writing a realtime wep application, something similar to auction site. The problem is that I need a daemon script, preferrably php, that runs in background and constantly launches queries to mysql db and basing on some of criterias (time and conditions from resultsets) updates other tables. Performance of the daemon is crucial. Sample use case: we have a deal that is going to expire in 2:37 minutes. Even if nobody is watching/bidding it we need to expire it exactly in 2:37 since the time it started.
Can anybody advise a programming technology/software that performs this kind of task the best?
Thanks in advance
UPDATED: need to perform a query when a deal expires, no matter if it has ever been accessed by a user or not.
Why do you need to fire queries at time intervals? Can't you just change how your frontend works?
For example, in the "Deals" page, just show only deals that haven't expired - simplified example:
SELECT * FROM Deal WHERE NOW() <= DateTimeToExpire
Accordingly for the "Orders" page, a deal can become a placed order only if time hasn't expired yet.
Does your daemon need to trigger actions instantaneously? If you need a table containing the expired state as a column you could just compute the expire value on the fly or define a view? You could then use a daemon/cron job querying the view every 10 minutes or so if you have to send out emails or do some cleanup work etc.

Few issues with creating a web based chat system

I've decided to create a web based chat system for the experience. I'm using a mixture of AJAX(jQuery), PHP, and JSON to transfer the data. Now that I've started thinking about certain things, I've come to a mind block.
Right now, I use javascript to post the last loaded message id to a php file that queries the data and echoes new posts in json and then displays those posts in order on the page. However, the dates don't reflect the current time for the user. Since I use php to get the current time, I have no idea how to display the correct time to the user which takes into account of their time zone. Second, how would I incorporate a who's online list with this method? I could create a separate table and update it when a user creates a session and delete their name when they end the session; but what if they don't close it properly? Should I just add their last sent message into the the table and if it's been about 5 minutes since their last message consider the user disconnected? Lastly, is the method I'm using to collect new posts efficient? This there a better way to go about this? I appreciate any input.
This seems related: Determine a User's Timezone
I'm going to make you go there for the code snip so you give proper credit with your upvotes.
I get the impression that Javascript is the best/easiest way to get that data.
What I would probably do is use GMT or some other fixed time zone for all your server stuff and then just adjust that with js once it hits the browser depending on their time zone. Either that or just collect it once at the start of the conversation and adjust your output accordingly. There might be advantages to either way.
Edit:
Oh yeah, about the "who's online" I think you're headed in the right direction. I might suggest 2 lists. "Who's active" and "Who was active recently"
That way you can put people inactive after 5 mins and consider them disconnected after 10 or something. I guess it's about the same but it seems more accurate to me somehow.
The other option would be to set an ajax request to automatically fire of a request every minute or so. When they stop then you know the user is gone.

Categories