The chat system has two underlying functions.
- Request – The user requests the latest messages
- Post – The user is sending a message to the chat system
A Request is an automated callback, which requests any messages after the last one the user has currently displayed. The Post is triggered by the clicking of either the enter key or the Send button in order to trigger a message to be sent to the server. Both functions make AJAX requests and send them to the server, which are parsed and executed as permissions allow. The appropriate connections are made, actions executed and then the system returns the appropriate updated block of messages to the user. This fifty thousand foot view is strictly for demonstration purposes and is highly simplified, although it details out the process quite well, as you can see in Figure 1.
|Figure 1: An overview of the AJAX Interaction for the Request|
The design is rather straight forward, adhering to the idea of what AJAX was created for, asynchronous requests. The requests are sent across to the server in escaped URL strings so the load is not too heavy there. It is, however, a system that poses a few unique challenges. To begin with when there are more than 50 users making these requests every 3 seconds and sending messages to the server it makes the server think its losing its mind, apparently. Note that this is compounded by the fact that the users are able to open up multiple windows or pages that each have their own requests for the chat system. It can push the server to close to 50% load and that is strictly absurd.
Database Connections and Query Optimization
Our first assignment/task was to open up the code and straighten out this 50% garbage. From the get go I was a bit confused with the code. Over and over the blocks would have a statement similar to the following which was used to include and execute the db_connect methods and ultimately create the appropriate database connections. The initial development was made with about 30% knowledge of how PHP works, and coasting the rest of the way. It may be true that if you are using mysql_query you don’t NEED to send in the database handle, provided you have connected to it earlier in the execution, but that is by no means something you should take advantage of.
@include($_SERVER['DOCUMENT_ROOT'] . "/connect_to_forum_db.php"); # Execute a number of queries and some other processing @include($_SERVER['DOCUMENT_ROOT'] . "/connect_to_an_db.php");
Passing the Database handle is actually a very useful thing, especially when you get into situations like this where we are using a single sign in to the forum and the atheist nation site itself. Instead of cramming a bunch of new tables into the old ones Robert made a new database, which has its benefits (mainly smaller individual/segregated backups). The problem is that each one of these includes has two shocking issues.
First, we are creating a new database connection with each include. This is probably the most costly part of database interaction (aside from SELECT efficiency) and needs to be watched. Even if you are taking advantage of persistent connections, it is still more efficient to cache the handle and reuse it throughout a single execution than to re-query for it.
As if the first issue weren’t bad enough! There is a sly command sitting in two of the above lines that needs to be addressed. Relying on @ in order to avoid outputting errors is a very difficult thing to justify. @ is one of those commands that people find and think are a god send, but it is another kludge in my eyes. It is comparable to the register_globals directive in that it makes for difficult to manage code. The command dev/null’s any bitches pitched in that include, ergo if your db connection fails it will just return and that means you are going to have a failed database query and since this is all that’s going on in this file you are selling yourself short. The queries you attempt to execute next will undoubtedly fail if the connection previously fails.
What this means to you is that error checking is not a simple thing. It is an all encompassing science that requires diligent work in order to ensure that the code is not going to just fail without reason. As with the register_globals directive, there are reasons to use @ that I will not be going into here. If time permits I will try to explain where it is useful to use @.
I will Resume this series with a discussion about the new PHP DBQuery Class.