Progress!

Good news: the screw-up is officially fixed and, in terms of project functionality, we are now back to where we were before we knew the screw-up occurred. A little bit of new terminology I’ve coined: the term “project response” is now used when referring to the entire package of answers a user provides for a given project; that is to say, a “project response” includes (or rather, will include) both the numerical inputs and the answers to the marketing/tech questions. This name was chosen to distinguish from the “project survey” term which is just the latter. Of course, coining new terms doesn’t come without problems. You’ve got to make sure nobody else is using it, copyright or trademark it, keep an eye out for assholes who try to steal it, and, if you’re using Flex Builder 3, make sure that you don’t have a SOAP operation called yaddaResponse.

Wait, what?

Yep, it’s the attack of the bugs again. For some reason, having a SOAP operation called XResponse breaks the web service code auto-generation feature in Flex Builder 3. Instead of XResponseResultEvent containing an XResponseResponseType, it contains a XResponseRequestType. I do not know, nor do I suspect I want to know, what could possibly cause this to happen. All I know is that this bug has ruined my life, or at least my scheme to corner the market on terminology coinage. So instead of having a GetProjectResponse SOAP operation, we call it GetProjectAnswer instead. Yes, yes, “answer” is a synonym for “response”, but it’s not the same thing, damn it!

*Shakes fist* ADOOOOOOOOOOBEEEEEEEEEEEEEEEEEEEEEE!

*Ahem* In other news, I realized that some of our SOAP operations could potentially fall victim to race conditions. Specifically, any operation that first used a SELECT query to check a unique constraint (e.g. a new user tries to register, so we check if the username is available) and then used an INSERT if the check succeeded could be vulnerable. As an example, take two users trying to create an account with the same username. User A submits his request, followed by user B. The server begins processing user A’s request, but the OS timeslices the process after the SELECT check but before the INSERT statement. The server then processes user B’s request in its entirety; user B has now claimed the disputed username. The server then re-schedules user A’s request, which fails with a generic error message because, as far as the script can tell, there’s no reason the INSERT shouldn’t have worked.

There are a few ways of dealing with this. The first is to ignore the problem; the odds of something like this happening are fairly slim, but I’d prefer not to leave it up to chance. The second is to use locking so that nobody can mess with the table between the time we execute the SELECT and the time we execute the INSERT; MySQL’s documentation recommends against locking InnoDB tables, and locking would probably cause a fairly significant performance hit. Option three, which I opted for, is to simply perform a blind INSERT, without doing the check first, and then seeing if there’s an error message about a duplicate key value. It’s kind of a hack, but it’s simple and gets the job done.

One thing I did notice is that even if the INSERT fails, InnoDB still performs the auto-increment (this applies to our Projects table, which has an ID as its primary key). I suppose theoretically you could use this to DDoS the service, by racking up the auto-increment until it passes the limits of the INT data type the column is declared as. According to my calculations though, even if the server could handle 100 requests per second (which, given that we’re in a shared hosting environment and the database is located on a different system from the web server, seems unlikely), it would take a year or so to max out the column. If this did still become a problem, we could always fix it by just altering the table to use a BIGINT instead of an INT or possibly resetting the auto-increment counter somehow. Alternatively, we could adjust the schema and the PHP scripts to eliminate the use of an ID column; an ID column is being used mainly to save space (one INT column versus two VARCHAR columns).

I’m considering going the “dual VARCHARs” route anyway, because every time I want to retrieve a project response, I have to go to the Projects table to find out what the ID is using either a subquery or a JOIN. This is your classic memory usage vs. processing speed dilemma: the ID column saves space (or it should, at least, though I haven’t really checked any authoritative sources) but slows processing, whereas the VARCHARs would use more space but speed processing (since they eliminate the need for subqueries/JOINs). This is something I’m going to look into at some point, maybe later this week.

Speaking of this week, I abandoned my plan to have the Business final finished by tomorrow. Instead, I’ll spread it out over tomorrow and Wednesday. I’m not sure how this will impact what I get done for the project for the rest of the week. I’ll be happy if I can get the surveys implemented; figuring out the app<=>site bridge would be nice, and not having logoff is really starting to get annoying. Those items are on top of the list; analysis UI will definitely be delayed until B-term, as predicted.

This entry was posted in IQP, rants. Bookmark the permalink.

One Response to Progress!

  1. Pingback: Flex Sucks: Greatest Hits! « CaptainRichard's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s