Do you post old data back when doing a long poll? - php

I think I understand the concept of polling fairly well. You basically just request data from the server, but only once the data has changed, does the server return it. Straight forward stuff. My problem comes with this example.
Let's say I have auctions with data that changes constantly. Among this data are things like
Closing time of the auction
Number of current bidders on the auction
When I start the long poll, I basically have something like this:
while($counter < $MESSAGE_TIMEOUT_SECONDS) {
$newData = getNewData();
$hasDataChanged = hasDataChanged($newData, $oldData);
if ( $hasDataChanged ) {
return $newData;
}
usleep($MESSAGE_POLL_MICROSECONDS);
}
Where do I get the old data from? I mean, when doing the request, I can either post the current state as it was last given to me, or I can store the data in Session. Am I allowed to store stuff in session when doing a long poll, or should I do a POST from the Javascript with the current state of that page?
Also, how would I stop someone opening 50 pages from killing the database? I mean, getNewData() effectively goes to the database. With a polling interval of about half a second, this could mean 50 requests every half a second, which could mean 50 x 2 x 30 = 3000 requests to the database in 30 seconds by just one user, if he decided to open 50 tabs?
Any ideas?

I would cache all ajax response data in memory along with last date that each auction had any change so you don't have to compare old and new data but just datetime. Invalidate cache on some change (closed, new bid, etc.) for auction.
Then from client side send time from last known data (last ajax call or when user opened page) and compare dates to see if something changed, if it didn't just return status:nochange (now client side knows there is nothing to update) and if it did return all necessary data from cache and update users page.
This model should protect database from overloading.

Related

Show real time data to users with same response time

I've doubt regarding speed and latency for show real time data.
Let's assume that I want to show read time data to users by fire ajax requests at every second that get data from MySql table by simple collection query.
For that currently these two options are bubbling in my mind
MySql / Amazon Aurora
File system
Among these options which would be better? Or any other solution?
As I checked practically, if we open one page in browser then ajax requests gives response in less than 500ms using PHP, MySql, Nginx stack.
But if we open more pages then same ajax requests gives response in more than 1 second that should be less than 500ms for every visitors.
So in this case if visitors increase then ajax requests gives very poor response.
I also checked with Node.js+MySql but same result.
Is it good to create json files for records and fetch data from file? Or any other solution?
Indeed, you have to use database to store actual data but you can easily add memory cache (it could be internal dictionary or separate component) to track actual updates.
Than your typical ajax request will look something like:
Memcache, do we have anything new for user 123?
Last update was 10 minutes ago
aha, so nothing new, let's return null;
When you write data:
Put data into database
Update lastupdated time for clients in memcache
Actual key might be different - e.g. chat room id. Idea is to read database only when updates actually happened.
Level 2:
You will burn you webserver and also client internet with high number of calls. You can do something:
DateTime start = DateTime.Now;
while(Now.Subtract(30 seconds) < start)
{
if (hasUpdates) return updates;
sleep(100);
}
Than client will call server 1 time per 30 seconds.
Client will get response immediately when server notices new data.

what would be better for conserving server system resources

I made a private chat system. So far the chat has 3 jquery ajax post scripts calling to the server in a loop for new data.
Message window between current user and target user (The ajax gets the timestamp of the last message on the db and compares it to the last message timestamp that was displayed. Get all messages > than last message timestamp and display it on message window. ajax loops every 5 seconds after last return.)
Whos online checker (Checks db for whos online. ajax loops every 30 seconds after last return)
Who messaged current user (Check and Get users who are not the current target user on the message window and has messaged the current user. ajax loops every 15 seconds after last return)
So far the above 3 are the only ajax loops I have and I am still double checking my code for areas where I can trim it down.
My question is. Would it be better in conserving server system resources if I group together the above 3 ajax post to create 1 ajax post and loop it every 5/8 seconds. Or should I leave it as?
I ask this because I got a warning from my hosting before that I was consuming too much of their server's system resources (due to a very stupid experiment). If I mess up again their gonna cut my hosting so I do hope you guys understand why I ask this kind of question.
Extra details: I use jquery ajax to talk to a php script that gets the data from a mysql db. The loop for the requests are done client side.
Websockets are tricky. So if you decide to go with ajax there are a couple of factors to consider:
The frequence. Efficient systems usually use a sort of tick system. In your case a tick would be 5 seconds as all your time lines can be tacted into a 5 second tact. And yes of course you group all transmission needs of a tick into 1 transmission.
The data quantity. Try to not send more than 1KB of Bytes per tick. Eg. use sparse formats like csv over eg. XML. Set hard entry limits. Compress. Things like that. Network traffic is packaged - so sending 1025 Bytes causes allocation of 2KB resources.
Act on user's inactivity somehow. Eg. do not use up each tick for the "Message window between current user and target user" if the user is inactive for more than a minute. Sort-of-session timeout of 20 minutes or so...
The computation. Make the server side tick response QUICK and small. Consider to use memory tables or mem chaches for the tick handling and then have a ten minutes or so agent that stores to persistence what is needed to go there. Try to avoid complex fat operations (like eg. >3 db round trips) in the tick response.
The hoster. That was also said in other comment. A quick additional hint: You could ask if you are allowed to implement that thing before you sign the contract, if you are able to change the contract. Sometimes there are things like video and instant messaging mentioned in the general terms of service.
There are probably more things.. But these come to my mind immediately...
In general maybe you should also check out https://developers.google.com/speed/docs/best-practices/rtt

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.

Countdown timer with random number generator

I am running a sweepstakes like thing and want my users to all be able to load the page and have the exact same countdown and number generator running. I tried this in AS3 but each user caches their own swf file and gets a different result from the random number generator, and the as3 countdown is a few seconds off from each user. How would I go about making a countdown that is the exact same for each user looking at it at the same time and then a random number generator where every user will see the same result it gives? Is it even possible?
Sorry I wasnt clear on this. I would like to have it where the viewers could see the number being generated when the timer runs out. Kind of like watching the lotto on TV. Again, not sure if this is possible.
I have looked around, I know as3, some php, and some javascript. I have given up on doing this in flash.
Assuming I understand correctly what you want, store a random value (RV) every time someone accesses the page associated with a UNIX timestamp in seconds. Make time column unique, then if another request is made the same second, the random number is going to be taken out of the database.
Store the timer result in a table, show users the stored random number. Then when needed simply create another random number, store again, show user. Repeat.
Every user that come to that page , first print the time from the server so every user that will come and if your server time is 12:00 am for example , you will show him 12:00 am.
And then with Ajax refresh this time every X seconds ajax will send a request to the server and the server will tell you the time to display.
Keep the random logic on your server and when your application logic will say to change to a different number the server will return a different number and your clients will get it on the next pull ( ajax ) .
I hope that answering your question.
I'm not too familiar with flash, but what I would do is make the countdown happen client side using javascript's getUTCSeconds(), getUTCMinutes(), getUTCHours() etc to figure out current time verses end time of the counter (end time in universal time code).
Then you could use php to generate the random numbers (and a corresponding remaining time associated with it? how often do you want these?) and store it in a location for later retrieval (database, or file or some such). You could use ajax to grab the random number at the specified times
for more about js date/time functions w3schools has a pretty good resource:
http://www.w3schools.com/jsref/jsref_obj_date.asp
This is possible.
All logic should be stored on the server side. Use Flash only to show results.
Countdown: create it with php, store on the server side in the storage (database, memory, files, whatever). All clients (written on Flash) request counter value and display the counter on the client side starting from the value taken from server.
Lotto results are also generated on the server and passed to the clients. On the first hand you may generate intermediate results on the server and read them one by one by the clients, but I'd generate all results at once and pass them to the client.
Intermediate results can then be synchronized with the counter.

PHP, how do I calculate total online time of a user?

What is the best way to calculate the total time spent by a registered user on the site? ...under these conditions
1) User logs out normally.
2) User can simply close browser.
3) User can auto-login next time he comes back.
I think the best way to do this would be to find the time spent by the user on each page and keep adding them to his total time instead of checking for the whole site. But I don't know how to implement that....please help
You can't find the exact time he leaves the system, unless he logs out. Even then, he might be browsing the site while logged out.
The approximate way to do this would be to set the start time in the session and keep incrementing the time everytime he visits a page.
So the first time the user comes to your site at time T, you will
Create a session and put the start time there
Add the total time as 0
For all subsequent requests you would
Check the start time and compare that with the time now and get the difference
Add that time to the total time
This method will not give you the time the user spent on the last page. But it will give you something to work with.
You can do this with JavaScript and a separate PHP script.
The javascript code reacts to events that mean that an user is active (such as mouse/keyboard/resize events) and invokes the php script.
The php script compares the time when it last received a request to the current time and checks if the difference is over a certain threshold (i suggest something like 10-30 minutes to prevent single-click sessions from adding up) nothing happens.
If the threshold is not reached then the difference between the two timestamps is added to the total sum in the database.
Afterwards (in both cases) the last request time is set to the current time and the script ends.
If you also want to know when the user closes your website pages you can subscribe to unload events and/or implement an heartbeat script that calls a PHP script every X seconds.
you have 2 approaches, either to create a log table in your DB to track each user (by ID) logins and logouts and then calculate the time difference between the two in each record for the specific user and then sum all of that. OR you go more complex and make 4 columns in your DB->usertable (logintime 'timestamp' - logouttime 'timestamp' - lastactive 'timestamp' - onlinetime 'int') and update each column as their names say by code according to user activities. then alter the Session.php script in the System/libraries directory at line 105 exactly after if ( ! $this->sess_read()) before the system creates a new session and write a code to check if the 'logouttime' is not the same as 'lastactive' time (to avoid session timeout expiry misunderstood in the next code) if both fields not the same, update your DB to make 'logouttime' equals 'lastactive' then at line 107 exactly after: $this->sess_update(); write a code to check if the 'logouttime' equals the 'lastactive' (and you will make that happen earlier in your logout.php script) write a code to calculate the online time by the difference between the 'logintime' and the now time 'time()' and add the result to the 'onlinetime' field. but if the 'logoutime' is not the same as 'lastactive' (that meanse the user is online and making activities in your site because you are tracking him and updating the 'lastactive' field frequently) then write a code to calculate the online time by the difference between the 'lastactive' and now time 'time()' and add the result to the 'onlinetime' field. that way you have the exactly online time logged forever in the 'onlinetime' field! I hope you got me right because the examples will be a lot long of scripts (although I don't mind to share upon request). good luck.
Use the Session ID to keep track of individual sessions.

Categories