RSS
 

Archive for the ‘Uncategorized’ Category

Simple PHP lockfile/pidfile implementation

30 Oct

We have a some PHP files that run as cron jobs. Some of them run frequently, but occasionally take longer to run than the interval we have them set to. To prevent pile-up, I created a simple lockfile mechanism. I take advantage of posix kill 0 to check if the script is still running, so I think this is only guaranteed to work on linux, definitely does not work on Windows last I checked.

All you need are two functions:

function lockfile_open()
{
    $pidfile = '/tmp/' . basename($_SERVER['PHP_SELF']) . '.pid';
    if (file_exists($pidfile)) {
        $pid = file_get_contents($pidfile);
        $running = posix_kill($pid, 0);
        if ($running) {
            return false;
        } else {
            unlink($pidfile);
        }
    }
    $handle = fopen($pidfile, 'x');
    if (!$handle) {
        return false;
    }
    $pid = getmypid();
    fwrite($handle, $pid);
    fclose($handle);
    register_shutdown_function('lockfile_close');
    return true;
}

function lockfile_close()
{
    $pidfile = '/tmp/' . basename($_SERVER['PHP_SELF']) . '.pid';
    if (file_exists($pidfile)) {
        unlink($pidfile);
    }
}

To use it, simply call lockfile_open(); at the beginning of cron execution and check the return, if it returns false then you have another copy of your script already running and you need to handle appropriately (in our case we log an error and die).

As with my previous post, I’ll break this down line by line to explain what is happening.

$pidfile = '/tmp/' . basename($_SERVER['PHP_SELF']) . '.pid';

this sets the path for the lockfile/pidfile. I am storing them in /tmp and basing the name entirely on the name of the script that is executing. Depending on your system you may need to store them somewhere else and come up with a different naming scheme.

if (file_exists($pidfile)) {
    $pid = file_get_contents($pidfile);


we check to see if our pidfile already exists. If no other copy of the script is running, it should not exist because the shutdown handler deletes the file. If it does exist then we need to read the contents of the file to get the pid, so we can check to see if it’s really still running, or if it’s stale.

$running = posix_kill($pid, 0);

doing a posix kill with signal 0 does not actually send a signal to the process, but still runs error checking, which includes testing to see if the pid is running.

    if ($running) {
        return false;
    } else {
        unlink($pidfile);
    }
}

if posix_kill returned something truthy then the process is in fact still running, so we return false to indicate that. If the pidfile is actually stale, we delete it and then continue as if the file never existed.

$handle = fopen($pidfile, 'x');

We create the pidfile with mode x, this will fail if the pidfile already exists, which means this handles the possible race condition of two scripts executing at the same time, where both check above for the pidfile and both see it as not existing. mode x guarantees that one of those scripts will succeed in creating the file and the other will fail.

if (!$handle) {
    return false;
}

If we failed to create the pidfile then we assume it’s due to the aforementioned race condition, so return false. NOTE: this assumes permissions are set up correctly for wherever you are saving your pidfile, if you set up a path that your crons can’t write to, this will fail to create the pidfile and assume it was due to the race condition even though there is probably not another instance of your script running.

$pid = getmypid();
fwrite($handle, $pid);
fclose($handle);

Here we get our current pid and write to to the pidfile, then close the file.

    register_shutdown_function('lockfile_close');
    return true;
}

If we made it this far then we are the first/only instance of the script currently running. We register our lockfile_close() function to clean up our pidfile when the script stops executing, and we return true to indicate that it’s safe to proceed.

function lockfile_close()
{
    $pidfile = '/tmp/' . basename($_SERVER['PHP_SELF']) . '.pid';
    if (file_exists($pidfile)) {
        unlink($pidfile);
    }
}

lockfile_close gets called automatically by the shutdown handler when the script stops executing. We check to make sure the pidfile still exists and then delete it, so we aren’t leaving stale pidfiles around.

 
 

South Carolina’s flag is bad for business

20 Jun

South Carolina’s confederate flag has come under intense scrutiny due to the recent actions of a certain racist asshole. Apparently last year, Governor Nikki Haley defended the confederate flag saying that CEOs do not have a problem with it.

I have two observations to make about this:

1. If a CEO is talking to the governor about moving their business to SC or has already moved their business to SC, they most likely had already decided the confederate flag was a non-issue for them, so why would they bring it up to the governor? The fact that CEOs aren’t talking to her about it doesn’t seem to say a whole lot about how CEOs in general feel about it.

2. Even if CEOs have no problems with the confederate flag, I know that SC is losing talent because of it. I know this because I know 4 extremely talented designers and software engineers from SC who left because of the blatant state sanctioned racism including the confederate flag. I also know that the confederate flag keeps talent away because although SC has the ideal climate for me and meets my requirements of being coastal, I refused to consider any jobs in that area because of the confederate flag. I will not tolerate living anywhere that is OK with prominently displaying a blatant symbol of racism. So even if CEOs are not complaining about the flag, it’s bad for business because it’s driving talent away, and businesses need talented people.

Now, I know some people claim that the confederate flag is not a symbol of racism and it’s about heritage, or it has some other meaning I’m not familiar with (I was not raised in the south, so I admit I may be ignorant on these things). Let’s assume that they are right and for some people the confederate flag has nothing at all to do with racism. I would argue that it does not matter what the flag means to some, if to the majority of people it represents racist ideology. Take the swastika: it had different meanings to different cultures, but you don’t see non-racists flying swastika flags and defending it as the ancient buddhist symbol of eternity, do you? No. Since the confederate flag is so closely associated with racism, it’s time for the non-racists who use it to mean something about heritage (or whatever they think it means) to pick a new symbol that does not have the hateful overtones of the confederate flag, unless they really don’t mind being associated with white supremacy…in which case I would argue that they are more racist than they think they are.

 
 

Android Wear: great now, awesome soon!

15 Jul

As everyone who pays attention to tech probably knows by now, Google gave away the LG G and Samsung Gear Live watches at I/O, as well as early access to the Android Wear companion app. I went with the LG G watch and have been using it since then.

The Watch

This post is mainly going to be about Android Wear, but I will share a little about the LG G watch first since I’m sure some people are curious. I actually think the Samsung is a much nicer looking watch with the curved edges vs the LG’s blocky square look. At first glance the LG actually made me nervous that it was going to stick out too far and I would end up catching and hitting it on things, but early reports of poor battery life on the Samsung convinced me to go with the LG. I also figured that if I changed my mind the higher retail price of the LG would make it easier to sell and replace with the Samsung later.

I’m happy to report that while it’s not the most stylish watch ever, it’s not so chunky that it gets snagged on things, so far it has never been in the way.

The battery life does seem to be significantly better compared to the what my friends with the Samsung are seeing, especially on the first night when they were new and we couldn’t stop playing with them, their watches died when mine still had over 60% battery life remaining, despite their having immediately charged theirs when they got them (I didn’t have time to top mine off). Under normal circumstances they have had no problem with the watch lasting a whole day, but my this is what the battery is like when it’s new; as it ages it may indeed have difficulty staying alive for a whole day, especially if I’m right and they end up getting a lot more use than we initially anticipated (more on that later). Obviously comparing battery life is difficult because everyone’s usage patterns are going to be different, but I should mention that we all had at least turned off the always-on feature, requiring a flick of the wrist to turn on the display, so it was as close to an apples-to-apples comparison as we could get under the circumstances. I’ve since switched my display to always-on, and still have plenty of battery left over at the end of the day.

Even though I am generally happy with my decision to go with the LG G, I do have some complaints, some of which may be eventually fixed by software:

Notifications – There is no way to change the length or intensity of the notification buzz. The default notification buzz is so short and gentle that I often do not feel it. The buzz for an incoming phone call or alarm is stronger and more persistent so I have no trouble feeling those, so I would love to be able to increase the strength of the buzz for a normal notification. I do not know if Samsung allows you to customize this, or what the default buzz is like.

Screen on gesture – Turning on the screen with a flick of the wrist is not as elegant as it sounds. It does not seem to be controlled by a gesture or motion at all, — This complaint has actually already been fixed by an update since I started writing this blog post! It is indeed now controlled by an actual gesture, but it’s still not perfect: about half the time when I flick my wrist the gesture isn’t recognized, especially if the strap is a little loose. There’s also still a magical angle that, if you hold the watch at exactly that angle the screen is on, no matter what. You can turn the screen off and it will just turn right back on even if you are perfectly still. It’s a minor annoyance though, the worst case if the gesture is not recognized is that you try again, or touch the screen to turn it on.

The band – The wrist band material is uncomfortable. I may be in the minority but I really strongly dislike the synthetic rubber material that both the LG and Samsung watch bands are made from. It traps sweat, is generally uncomfortable, and eventually gives me a rash. Not to mention that it looks cheap to me. Fortunately, the LG accepts a standard band so I replaced it with this one which I’m happy enough with (but any 22mm band will work). I’m told the Samsung can accept a standard band as well, but I think it would look really bizarre because of the way the band integrates with the watch.

Charger – The charger is completely nonstandard. Not a big deal in general for the LG G since the battery life is generally pretty good (with the screen set to auto-off, I’m usually around 80% battery life before I go to bed, with always on about 50%), but it will be annoying to have to take another proprietary charger with me when travelling. The charger at least accepts a standard micro USB connector, so it’s really just another random dongle to lose in my bag. At home the cradle is certainly more convenient than micro USB would be, but it would be nice to be able to charge with the cradle at home and fall back to standard micro USB on the road, especially since the cradle includes an adhesive to hold it in place on your nightstand. The Samsung also has a proprietary cradle charger thing, and I’ve seen reports of the clip-on tab breaking easily, which can’t happen with the LG since it’s only held on by magnets.

Charging at night – The screen is always on when it’s connected to the charger. I was strongly considering keeping the charger in another room because the amount of light from the screen is enough to be annoying, but I eventually realized that the watch charges so quickly that there’s really no need to charge it overnight. Now I actually turn the watch off when I go to sleep, and pop it on the charger in the morning, which automatically turns it back on. By the time I’m done with my morning routine, the watch is fully charged.

Android Wear

On to what this blog post is actually about: Android Wear. I have to admit that if I didn’t get an Android watch for free, I would have passed up the first generation and waited to see if there was something truly exciting that I could do with them. Despite being psyched about the wearable computing movement, I just didn’t find the smart watch a very compelling application, with such a small screen and limited forms of input, it just seemed pointless. But even after my few days with the LG G, I was sure that if something happened to it, I would buy a new one in a heartbeat.

Why it’s great right now

Some of my favorite features:
Timer/reminders – I can say “ok google set a time for 30 minutes” or “ok google remind me to write a blog post at 4:30pm” and I get a buzzing reminder on my watch at the appropriate time. It’s not only super convenient but it’s way less disturbing to other people than a noisy alarm on my phone, and unlike a buzzing reminder on my phone, it’s completely impossible to miss when this is going off. I would like if it was possible to manage these timers/reminders from my phone, because part of the appeal of not disturbing people sometimes is also not having to loudly talk to my watch.

Agenda – Every night a card pops up remind me of tomorrow’s agenda from my calendar. This is great because I’ve actually never been good about consistently checking the night before to make sure I am prepared for the next day. Now it’s automatic. This may not work for people who go to bed before midnight because right now it seems to just be based on the date; the card pops up at exactly midnight. Since I’m a night owl, that’s more than enough time for me. If you want to see your agenda any time when the card doesn’t automatically pop up you just have to say “show agenda” to see it.

Navigation – Currently the only useful use case for this is when you are walking around in a strange city, but when you are it’s so nice. I feel much less conspicuous glancing at my watch periodically than walking around with my phone out. I feel this app could use some visual tweaks as it’s very plain/ugly right now, and I’d love for them to find a way to fit a little more information on it (a way to see the next step, landmarks, alternative street names) but even as-is it’s highly useful for walking.

Weather – Weather was the one thing I consistently went to Google Now on my phone for. Now it’s on my watch, usually right under the time. A swipe to the right shows the weather for the next 4 days. I’d love to see them add support for another swipe to show me the hourly breakdown for the next 24 hours like I can in Google Now on my phone, that information is often more useful to me than what the weather is going to be like in a couple of days.

Messaging & hangouts – It’s nice being able to read most SMS messages at a glance, but what’s really cool is how much less annoying it is to be in a group hangout with a bunch of chatty people while you’re busy doing other things. No more constantly having to pull out your phone to keep up with the conversation. It’s also really handy to be able to send a text message when my hands are otherwise occupied/dirty, like when I was in the middle of cutting up raw chicken and needed my girlfriend’s help with something but she was outside tending the garden, or like when I was kayaking and wanted to let her know I was getting close to where we were meeting up. Did I mention that the watches are water resistant?

Grooveshark & other media players – Grooveshark works right out of the box on this, even though our most recent release predates the existence of Android Wear. Once music is playing, a card appears on the watch with the album art along with artist and song names, with a Play/Pause button. A swipe to the right shows a Next button, and another swipe to the right brings up a Previous button. All of these work, right now with no work necessary on Grooveshark’s side. The only annoyance I have with this is that the card doesn’t come up until music is actually playing. So I can’t say “ok google, start Grooveshark” and then immediately control playback. I still have to get it started playing on my phone. But after that, controlling via the watch works perfectly. There are two use cases this is awesome for: When I’m cooking in the kitchen, I have my phone plugged into a small speaker system playing music. I can now see what is playing, and control playback, without having to walk over to it and unlock my phone. The other use case any time when I am listening to music on my bluetooth headset and my phone is in my pocket – I no longer have to fish it out of my pocket to control playback…that makes the whole experience so much more convenient in general, but it was especially nice on the insanely long flight back to Gainesville from San Francisco; fishing anything out of my pockets when sitting in a cramped airplane seat is a chore.

Netflix & Chromecast – Much like how you can control Grooveshark with the watch, you can also control Netflix when casting to Chromecast. I can just run into the kitchen whenever I want, and if it turns out I’m missing something I can instantly pause it. Previously if I wanted to have that option I would have to make sure to bring my phone with me, then turn it on, unlock the screen and finally hit pause…by which point I’ve already missed whatever I was trying not to miss, and of course half the time I’d forget to bring my phone with me anyway. It’s one of those things that I never really thought of as annoying before but I find myself greatly appreciating the watch for solving anyway. I do wish they had the “skip back 30s” option like the app does on the phone, and there is a minor bug that I expect will be fixed soon where the card stays on the watch after the show has finished playing and it’s impossible to dismiss until you toggle play/pause on the watch, even though it’s not even playing (even if the TV is off!)

How it can be even better
Even though Android Wear is great today, I’m especially excited for the future because it has so much potential to be thoroughly awesome. Here’s hoping even a fraction of these come true.

Better Casting: The way Netflix & Chromecast works, anyone in the house can control playback no matter who started it. Right now though, if my girlfriend starts something on Netflix, I have to start up the app on my phone, switch to our shared profile, turn on casting, wait a few seconds for it to figure out what is going on, and then I can finally pause. If Android Wear could just figure out that hey, something is playing on the Chromecast, so you should have control options, that would be truly awesome. Obviously the same would be true on the Android phone, but my expectations for awesome context awareness as so much higher for Android Wear because it already delivers that experience for some things.

Payments – I want to stop carrying a wallet, or at least credit cards, and I don’t think NFC is ever going to get us there: retailers need to buy new equipment, more than just flagship phones need to support it, and a standard that everyone can use and be OK with needs to emerge. Imagine if whenever you walked into a store you got a card on your watch along the lines of: “It looks like you’re in Starbucks. Swipe right to pay.” swiping right shows a one-time-use QR code that the retailer can scan. That’s a system that I think would actually have a chance of succeeding because it utilizes equipment that retailers already have, and doesn’t require users to fiddle around with anything, the information is just there when they need it. If, instead of Google Wallet, that was supported directly by Visa, MasterCard, etc., the friction to adoption would just melt away. In fact Visa and MasterCard might have a strong incentive to go along with it since the one time use nature could reduce fraud by eliminating stolen credit card numbers. The same technology could and should exist on the phone as well, but it would be truly convenient on the watch.

Where’s my phone?! – Maybe it’s just me but when I’m at home I have a penchant for leaving my phone in odd places and then forgetting where that was. If the watch is in range (and the range is quite good for bluetooth), I’d love to be able to make my phone buzz or ring from the watch.

Better media player support – As far as I can tell there’s no way to send a Play event like you can from bluetooth media devices. For example in most bluetooth enabled cars there’s an option for it to just send play to your phone the moment you turn the car on. I don’t want that to be automatic with my watch, but I’d love to be able to say “ok google, play” and have it send a play event to whatever media player I had open most recently (usually Grooveshark of course!)

Soundhound/Shazam – I’d love to be able to say “ok google, what’s playing right now?” and get an answer on my watch.

Fitness / health / sleep tracking: Some of this will have to come on a different watch from either of the ones available today, because even the Samsung doesn’t have continuous heart rate monitoring. There’s no denying that fitness is a killer app for wearables, and one that’s more or less ignored in this version. It does include step counting, but that’s it. Continuous heart rate monitoring, sleep tracking, waking you up at just the right time, and food/calorie monitoring are all good places to start, and it’ll be interesting to see what Apple’s take on this will be since rumor has it their watch will be health focused.

Speaker This one is tricky because one of the things that nice about the watch most of the time is that it is silent. But there are times where it would be really nice if it could read something back to me, or even reading it back to me via the phone’s speaker would be an improvement.

Wireless charging – The charger for the LG isn’t bad or too annoying, but the magnet isn’t really strong enough to guarantee that it seats properly without fiddling. What would be really nice is being able to just take my watch off and plop it on a tray without paying any attention to where or how it lands.

For the love of god let me turn off the screen when charging! – My current solution of turning the watch off at night feels weirdly old fashioned, and it’s not exactly easy, you have to dig through the settings to find the option to turn it off. Really I just want to be able to put the watch on its cradle at night and turn the screen off, there’s no reason for it to be on lighting up the whole room when I’m trying to sleep.

Make everything dismissable – Certain notifications are impossible to dismiss (like that Netflix one I mentioned earlier). It really should be possible to tell every single notification to fuck off if I really want to. Go ahead and make it a 3 step process, as long as it’s possible.

Pin/resurrect cards – At the same time I also occasionally find myself accidentally dismissing cards when I actually wanted them to stick around and was just trying to get back to the “main” screen. A stronger hint that you’re about to dismiss a card would help, but really it would be nice if there was a way to quickly undo. It’s especially bad because dismissing a “Google Now” card seems to teach it that you don’t want that card anymore. I accidentally dismissed the weather card and I had to look up the weather a few times a day for a couple of days before it started coming in on its own again.

Better watch faces – I know it’s super early, but for now I’m stuck with a black watch face because I wanted one that shows the time and date, and none of the colorful ones do that. I’m sure it’s only a matter of time, there have already been a bunch of 3rd party watch faces made so I’m sure it’s only a matter of time before the perfect one for me exists.

Camera I’m officially in fantasy land on this one but some day in the distant future it would be cool to be able to take pictures straight from my watch. This was inspired from the most recent of many attempts to take a picture of an interesting creature in my back yard — by the time I got my phone out and fired up the camera app, it was gone. The biggest impediment to ever getting this is the creepy/spywatch factor, and the last thing Google needs is the same set of concerns people have about Glass.

Multiple device controls – This isn’t entirely Android Wear specific, but really in all of Android if you have multiple devices tied to the same account, dismissing a notification on one should dismiss it on all the others. My tablet constantly ends up with tons of useless notifications on it that I have already seen on my phone. Android wear has raised my awareness to the possibility of dismissing a notification on one device affecting the other, so now we just need to make it do that from my watch to all my devices, rather than just the phone it’s paired to.

Desktop integration – It would be really awesome if my watch could be more than just a remote extension of my phone. If there was a chrome extension, Android Wear would become even more useful: Controlling YouTube, Grooveshark, Netflix when they are running in the browser too? Yes please! I’d also love to see the same automatic lock/unlock functionality that’s coming to Android L, on my windows desktop. Even if it meant pulling up some card on my watch to lock the screen (or check whether it’s locked), that would be great.

3rd party integrations – Hangouts has me spoiled. Whenever I get a Facebook notification about a comment for example, I expect to be able to actually read the comment by tapping on the notification or swiping to the right, but right now all I can do is choose “Open on Phone” and then go find my phone. When app developers start including the full context in their notifications, they will be incredibly useful.

Wrapping it up
Android Wear is a great platform today, with a lot of potential to become truly amazing in the very near future. The watches available today are not perfect, but their drawbacks are minor, at least in the case of the LG G which I have experience with. If you have any interest in wearable computing or just making your life a bit more convenient, I think picking one up today is well worth it.

 
 

XSS cheat sheet

26 Apr

Discovered this amazing XSS cheat sheet while trying to prove to a co-worker that using a regex to prevent <script> tags embedded in HTML was not going to be effective. I knew about the UTF8 vulnerabilities and all of the obvious ones, but the US-ASCII Encoding one especially was new to me, impressive!

 
 

Grooveshark is Hiring (Part 3 – Devsigner Edition)

26 May

Grooveshark is looking for talented web developers. For part 3, I’m listing our front end developer/designer (affectionately known here as “devsigner”) position.

Grooveshark Web Developer / Designers

Must be willing to relocate to Gainesville, FL and legally work in the US. Relocation assistance is available.
Responsibilities include:
Maintaining existing HTML templates and JavaScript code
Writing clean well-formed HTML and CSS
Writing JavaScript to be able to achieve the desired user experience
Using Photoshop and Illustrator and be able to convert images to markup and JavaScript
Optimizing HTML and CSS for speed considerations

Desired Qualities:
Enjoy writing high quality, easy to read, well-documented code
High level of detail given to converting designs
Able to follow coding standards
Good written and verbal communication skills
Well versed in best practices & security concerns for web development
Ability to work independently and on teams, with little guidance
Capable of prototyping features (either visually or concretely)
Capable of having a flexible schedule

Experience:
Experience with JavaScript, HTML & CSS
Experience in Photoshop and designing websites
Familiar with jQuery, including JavaScriptMVC
Familiar with Actionscript
Experience with version control software

Not Desired:
Uses WYSIWYG editors
Only searches for jQuery plugin that fits the job

 
 

How to Jailbreak Chrome and Install Grooveshark

15 Apr

As you may already know, Grooveshark’s Android app was recently <a href=”http://news.cnet.com/8301-31001_3-20051156-261.htm”>pulled from the Android market</a> due to either label pressure, or concerns from its competing music service that is soon to be launched (or both). That event has been covered in great detail all over the net, so I won’t rehash it here; that’s not what this blog post is about.

 

Yesterday we discovered that Grooveshark has also been pulled from the Chrome Web Store. Fortunately, if you already installed Grooveshark, Google does not appear to be revoking the app from users Chrome home pages.

For users who had not yet installed Grooveshark, they are out of luck from the web store. However, we have discovered that it is possible to “jail break” your Chrome installation to get the full Grooveshark + Chrome experience.

Step 1: Visit http://grooveshark.com in your chrome browser.

Step 2: Close the Grooveshark tab.

Step 3: Open the New Tab tab by typing CTRL+T (CMD+T in OSX?), or by pressing on the small + icon next to the rightmost tab.

Step 4: If Grooveshark appears under “Most visited,” simply drag it to the top-left position, hover over the site preview for a second, and click on the pin icon that appears. Skip to step 7.

Step 5: If Grooveshark does not appear under Most visited, scroll down to Recently closed, and click on Grooveshark.

Step 6: Proceed to step 1.

Step 7: Collapse the Apps section, or remove it entirely.

It may take several thousand iterations of this loop to bring Grooveshark into your Most visited section depending on how obsessively you are checking the 8 websites that appear there for you, but we feel this added effort on your part is well worth it. When you are done Chrome should look something like this:

P.S.: Grooveshark was ranked #8, right behind YouTube, an interesting juxtaposition since these services are both powered by user contributed content, and are both legal, but one is owned by Google and the other is not.

P.P.S.: For those of you who are really bad at detecting sarcasm, I am being facetious. As with every blog post I make here, I also am not speaking for Grooveshark in any sort of official capacity.

 
 

How Grooveshark Uses Gearman

27 Mar

At Grooveshark, Gearman is an integral part of our backend technology stack.

30 Second Introduction to Gearman

  • Gearman is a simple, fast job queuing server.
  • Gearman is an anagram for manager. Gearman does not do any work itself, it just distributes jobs to workers.
  • Clients, workers and servers can all be on different boxes.
  • Jobs can be synchronous or asynchronous.
  • Jobs can have priorities.

To learn more about gearman, visit gearman.org, and peruse the presentations. I got started with this intro (or one much like it), but there may be better presentations available now, I haven’t checked.
The rest of this article will assume that you understand the basics Gearman including the terminology, and are looking for some use cases involving a real live high traffic website.

Architecture

With some exceptions, our architecture with respect to Gearman is a bit unconventional. In a typical deployment, you would have a large set of Apache + PHP servers (at Grooveshark we call these “front end nodes” or FENs for short) communicating with a smaller set of Gearman job servers, and a set of workers that are each connected to all of the job servers. In our setup, we have a gearman job server running on each FEN, and jobs are submitted over localhost. That’s because most of the jobs we submit are asynchronous, and we want the latency to be as low as possible so the FENs can fire off a job and get back to handling the user’s request. Then we have workers running on other boxes which connect to the gearman servers on the FENs and process the jobs. Where the workers run depends on their purpose, for example workers that insert data into a data store usually live on the same box as the data store, which again cuts down on network latency. This architecture means that in general, each FEN is isolated from the rest of the FENs, and Gearman servers are not another potential point of failure or even slowdowns. The only way a Gearman server is unavailable is if the FEN itself is out of commission. The only way a Gearman server is running slow is if the whole FEN is running slow.

Rate Limiting

One of the things that is really neat about this gearman architecture, especially when used asynchronously, is that jobs that need to happen eventually but not necessarily immediately can be easily rate limited by simply controlling the number of workers that are running. For example, we recently migrated Playlists from MySQL to MongoDB. Because many playlists have been abandoned over the years, we didn’t want to just blindly import all playlists into mongo. Instead we import them from MySQL as they are accessed. Once the data is in MongoDB, it is no longer needed in MySQL, so we would like to be able to delete that data to free up some memory. Deleting that data is by no means an urgent task, and we know that deletes of this nature cannot run in parallel; running more than one at a time just results in extra lock contention.

Our solution is to insert a job into the gearman queue to delete a given playlist from MySQL. We then have a single worker connecting to all of the FENs asking for playlist deletion jobs and then running the deletes one at a time from the MySQL server. Not surprisingly, when we flipped the switch deletion jobs came in much faster than they could be processed; at the peak we had a backlog of 800,000 deletion jobs waiting to be processed, and it took us about 2.5 weeks to get that number down to zero. During that time we had no DB hiccups, and server load was kept low.

Data Logging

We have certain high volume data that must be logged, such as song plays for accounting purposes, and searches performed so we can make our search algorithm better. We need to be able to log this high volume data in real time, without affecting the responsiveness of the site. Logging jobs are submitted asynchronously to Gearman over localhost. On our hadoop cluster, we have multiple workers per FEN collecting and processing jobs as quickly as possible. Each worker only connects to one FEN — in fact, each FEN has about 12 workers just for processing logging jobs. For a more in depth explanation for why we went with this setup, see lessons learned.

Backend API

We have some disjointed systems written in various languages that need to be able to interface with our core library, which is written in PHP. We considered making a simple API over HTTP much like the one that powers the website, but decided that it was silly to pay the cost of all the overhead of HTTP for an internal API. Instead, a set of PHP workers handle the incoming messages from these systems and respond accordingly. This also provides some level of rate limiting or control over how parallelized we want the processing to be. If a well meaning junior developer writes a some crazy piece of software with 2048 processes all trying to look up song information at once, we can rest assured that the database won’t actually be swamped with that much concurrency, because at most it will be limited to the number of workers that we have running.

Lessons Learned/Caveats

No technology is perfect, especially a technology when you are using it in a way other than how it was intended to be used.
We found that gearman workers (at least the pecl gearman extension’s implementation) connect to and process jobs on gearman servers in a round-robin fashion, draining all jobs from one server before moving to the next. That creates a few different headaches for us:

  • If one server has a large backlog of jobs and workers get to it first, they will process those jobs exclusively until they are all done, leaving the other servers to end up with a huge backlog
  • If one server is unreachable, workers will wait however long the timeout is configured for every time they run through the round-robin list. Even if the timeout is as low as 1 second, that is 1 second out of 20 that the worker cannot be processing any jobs. In a high volume logging situation, those jobs can add up quickly
  • Gearman doesn’t give memory that was used for long queues back to the OS when it’s done with it. It will reuse this memory, but if your normal gearman memory needs are 60MB and an epic backlog caused by these interactions leads it to use 2GB of memory, you won’t get that memory back until Gearman is restarted.

Our solution to these issues is, unless there is a strong need to rate limit the work, just configure a separate worker for each FEN so if one FEN is having weird issues, it won’t affect the others.
Our architecture combined with the fact that each request from a user will go to a different FEN means that we can’t take advantage of one really cool gearman feature: unique jobs. Unique jobs means that we could fire asynchronous jobs to prefetch data we know the client is going to ask for, and if the client asks for it before it is ready, we could have a synchronous request hook into the same job, waiting for the response.
Talking to a Gearman server over localhost is not the fastest thing in the world. We considered using Gearman to handle geolocation lookups by IP address so we can provide localized concert recommendations, since those jobs could be asynchronous, but we found that submitting an asynchronous job to Gearman was an order of magnitude slower than doing the lookup directly with the geoip PHP extension once we compiled it with mmap support. Gearman was still insanely fast, but this goes to show that not everything is better served being processed through Gearman.

Wish List

From reading the above you can probably guess what our wish list is:

  • Gearman should return memory to the OS when it is no longer needed. The argument here is that if you don’t want Gearman to use 2GB of memory, you can set a ulimit or take other measures to make sure you don’t ever get that far behind. That’s fine but in our case we would usually rather allow Gearman to use 2GB when it is needed, but we’d still like to have it back when it’s done!
  • Workers should be better at balancing. Even if one server is far behind it should not be able to monopolize a worker to the detriment of all other job servers.
  • Workers should be more aware of timeouts. Workers should have a way to remember when they failed to connect to a server and not try again for a configurable number of seconds. Or connections should be established to all job servers in a non-blocking manner, so that one timing out doesn’t affect the others.
  • Servers should be capable of replication/aggregation. This is more of a want than a need, but sometimes it would be nice if one job server could be configured to pull jobs off of other job servers and pool them. That way jobs could be submitted over localhost on each FEN, but aggregated elsewhere so that one worker could process them in serial if rate limiting is desired, without potentially being slowed down by a malfunctioning FEN.
  • Reduce latency for submitting asynchronous jobs locally. Submitting asynchronous jobs over localhost is fast, but it could probably be even faster. For example, I’d love to see how it could perform using unix sockets.

Even with these niggles and wants, Gearman has been a great, reliable and performant product that we are able to rely on to help keep the site fast and reliable for our users.

Supervisord

When talking about Gearman, I would be in remiss if I did not mention Supervisord, which we use to babysit all of our workers. Supervisord is a nice little python utility you can use to daemonize any process for you, and it will handle things like redirecting stdout to a log file, auto-restarting the process if it fails, starting as many instances of the process as you specify, and automatically backing off if your process fails to start a specified number of times in a row. It also has an RPC interface so you can manage it remotely, for instance if you notice a backlog of jobs piling up on one of your gearman servers, you can tell supervisord to fire up another 20 workers.

 
 

Grooveshark IE bug

29 Jan

I hate the idea that this blog might be turning into nothing but a journal of all the things at Grooveshark that have ever broken, but some of the most interesting challenges we face are when things go terribly awry, so I’m not going to avoid talking about it just because it involves something breaking at Grooveshark, again.

What happened was, out of the blue IE8 could no longer run the site. Users were getting a message about making sure they did not have flash block enabled, which means the swf was failing in some way. We determined that the swf was in fact loading, so why was it lying to us? There is one file that swfs need in order to talk to other domains: crossdomain.xml. If that file fails to load, the swf isn’t going to work. I suspected that was happening in this case, so I loaded up http://cowbell.grooveshark.com/crossdomain.xml and IE complained that it wasn’t valid XML. View source showed me that IE was right. It was in fact what looked like binary garbage. Loading the same file in Firefox and Chrome worked perfectly fine, but IE8 on 4 different computers all showed the invalid XML.

Some months ago, we switched from serving pages up directly from Apache, to running Nginx in front of Apache as a reverse proxy with caching. The difference that made on our front end servers in terms of memory usage and CPU load is phenomenal. Although Nginx serves 30% of requests from cache now, the drop in server load was much more than 30%. Nginx is truly a wonderful addition to our http stack…but as you’ve guessed by now, it played a key role in the latest breakage at Grooveshark.

Force clearing the cache in IE8 and in nginx would sometimes fix the file, but not always. I then turned to wget and found the same thing: whenever the file was broken for IE8, it was identical in wget. wget was showing the exact same file size that Firebug was showing, which was the biggest clue: Firefox received the file gzipped because it supports deflate, but wget also received the file gzipped even though it doesn’t support deflate. My theory, which proved correct, was that IE8 was for some reason asking for the non-gzipped version, but receiving the gzipped version and barfing.

Why would that happen? Well, remember that we are using nginx as a reverse proxy cache. It turns out that we just recently added some auto-gzipping for certain file types to apache. What was happening was, nginx would get a request for a file not in its cache, and forward along the request (with all headers intact) to Apache. If this request came from a client that supports deflate, Apache would respond with a gzipped file. Nginx would store that gzipped file in its cache, and the next request that came in asking for that file, with or without deflate support, would get the gzipped version served up.

The fix was relatively simple: add a variable in nginx conf tracking whether or not the current client supports deflate. Append the value of that variable to the proxy key, meaning that gzipped and non-gzipped versions of the files will be cached separately, and served appropriately depending on what the client supports.

What’s not clear to me at this time is why IE8 would refuse to accept gzipped content for that file, and whether that applies to all .xml files in IE8…but at least it helped us catch what would have otherwise been an extremely obscure issue!

 
 

Old sphinx bug

21 Nov

I’m posting this mostly as a note to myself.

When trying to build the pecl sphinx extension, ran into problems because I could not build libsphinxclient.

It looks like the bug causing that problem has been around for at least a year, but at least the fix is simple:
change line 280: void sock_close ( int sock ); to static void sock_close ( int sock );

Note: this applies to sphinx 0.9.9, the last “stable” release at the time of this writing.

 
 

Google AJAX Support: Awesome but Disappointing

18 Oct

Google has added support for crawling AJAX URLs. This is great news for us and any other site that makes heavy use of AJAX or is more of a web app than a collection of individual pages.

We have long worked around the issue of AJAX URLs not being crawl-able by having two versions of our URLs, with and without the hash. Users who are actually using the site will obviously get AJAX URLs like http://listen.grooveshark.com/#/user/jay/42, but if a crawler goes to http://listen.grooveshark.com/user/jay/42 they will get content for that page as well, while real users will be automatically redirected to the proper URL with the hash. Crawlers aren’t smart enough to go there on their own of course, but we provide a sitemap, and all links we present to crawlers are absent of the hash. Likewise, when users post links to Facebook via the app, we automatically give them the URL without the hash so they can put up a pretty preview of the link in the user’s news feed. The problem is, users also like to share by copying URLs from the URL bar. If users post those links anywhere, crawlers don’t know how to crawl them, so they either don’t or they just count it as a link to http://listen.grooveshark.com/ which isn’t great for us and is lousy for users too.

Google’s solution is for sites like ours to switch from using # to using #! and then opting in to having those URLs crawled. The crawler will take everything after the #! and convert the “pretty” URL into an ugly one. For example, /#!/user/jay/42 presumably becomes something like /?_escaped_fragment_=%2Fuser%2Fjay%2F42 when the crawler sends the request to us.

This is annoying and frustrating for several reasons:

  1. All our URLs have to change
    We have to change all URLs to have a #! instead of just a #. This not only requires developer effort but makes our URLs slightly uglier.
  2. All links that users have shared in the past will continue to be non-crawlable forever.
  3. We now have to support 3 URL formats instead of 2
  4. One of those URL formats no human will ever see; we are building a feature solely for the benefit of a robot.

Again, we greatly appreciate that Google is making an effort to crawl AJAX URLs, it’s a huge step forward. It’s just not as elegant as it could be. It seems like we could accomplish the same goals more simply by:

  1. Requiring opt-in just like the current system
  2. Using robots.txt to dictate which AJAX URLs should not be crawled
  3. Allowing webmasters to specify what the # should be replaced with
    In our case it would be replaced by nothing, just stripped out. For less sophisticated URL schemes that just use #x=y, webmasters could specify that the # should be replaced by a ?

That solution would have the same benefits of the current one, with the additional benefits of allowing all crawling permissions to be specified in the same place (robots.txt), automatically making links already in the wild crawl-able, without requiring the addition of support for yet another URL format.