On many of our projects we use Gearman to do background processing. One of problems with doing things in the background is that the web debug toolbar isn’t available to help with debugging problems, including queries. Normally when you want to see your queries you can look at the debug toolbar and get a runnable version of the query quickly. However, when its running in the background, you have to look at the application logs to see what the query is. The logs don’t contain a runnable format of the query, for example they may look like this:
Problem is you can’t quickly take that to your database and run it to see the results. Plugging in the parameters is easy enough, but it takes time. I decided to quickly whip up a script that will take what is in the gist above and convert it to a runnable format. I’ve posted this over at http://code.setfive.com/doctrine-query-log-converter/ . This hopefully will save you some time when you are trying to debug your background processes.
It should work with both Doctrine 1.x/symfony 1.x and Doctrine2.x/Symfony2.x. If you find any issues with it let me know.
Good luck debugging!
As we continue to expand in 2015 we’re looking to add another developer to our team. Currently we’re seeking a junior level engineer to join us! A few attributes of a person that we’re looking for:
- 1-2 years of experience with MVC based frameworks (we use Symfony2)
- 1-2 years of real world experience
- Comfortable talking directly with clients, no account managers here!
- Works well in a team environment, but also self-managed.
A few of the perks:
- Flexible hours
- 100% paid health care (PPO)
- 401(k) with matching
- Company outings
For some more detailed information on the job please visit the posting. If you are, or know, a developer who is looking for a new opportunity lets connect!
Posted In: General
Recently we’ve been working with one of our clients to build application for use with AppNexus. We were faced with a challenge which required a bunch of different technologies to all come together and work together. Below I’ll try to list out how we approached it and what additional challenges we faced.
First came the obvious challenge: How to handle at least 25,000 requests per second. Our usual language of choice is PHP and knew it was not a good candidate for the project. Instead we wanted to do some benchmarks on a number of other other languages and frameworks. We looked at Rusty/Nginx/Lua, Go, Scala, and Java. After some testing it appeared that Java was the best bet for us. We initially loaded up Jetty. We knew that this had a bit more baked in than we needed, but it was also the quickest way to get up and running and could be migrated away from fairly easily. The idea overall was to keep the parsing of the request logic separate from the business logic. In our initial tests we were able to get around 20,000 requests a second using Jetty, which was good, but we wanted better.
Jetty was great at breaking down the incoming HTTP requests to easily work with, it even provided an out of the box general statistics package. However, we didn’t need much heavy lifting on the HTTP side, what we were building required very little complexity on with regards to HTTP protocol. Jetty in the end was spending too many CPU cycles for what we needed. We looked to Netty next.
Netty out of the box is not as friendly as Jetty as it is much lower level. That said, it wasn’t too much work to get Netty up and running responding to HTTP request. We ported over most of the business logic from our Jetty code and were off to the races. We did have to add our own statistics layer as Netty didn’t have an embedded one for what we were looking for. After some fine tuning with Netty we were able to start to handle over 40,000 requests per second. This part of the puzzle was solved.
On our DB side we had heard great things about Aerospike in terms of performance and some of its features. We ended up using this on the backend. When we query Aerospike we have the timeout set at 3ms. We’ll get around one or two request timeouts per second, or about 0.0025% of the time we’ll timeout, not too shabby. One of the nice features of Aerospike is the XDR function of the enterprise version. With this we can have multiple Aerospike clusters which all stay in sync from a master cluster. This lets us load our data onto one machine, which isn’t handling all the requests, and then it is replicated to the machines which are handling all the requests.
All in all we’ve had a great experience with the Netty and Aerospike integration. We’re able to consistently handle around 40,000 requests a second with the average response time (including network time) of 4ms.
It’s that time of the year that Setfive has retreated to warmer environments to focus on internal team building, communication, and management. I write this post as we fly past Florida on JetBlue to the Caymans and wanted to reflect on the struggle it has been to get to this point.
As we all know, weather in the Northeast the past month or so has not been very forgiving to anyone, especially airlines. Noone controls the weather so only best efforts can be made to work around it. Before I dive into some thoughts on how airlines may be able to improve the experience for their passengers, I want to give a up-to-date accounting of everything that has occurred thus far to show what I am drawing some of these suggestions from, I’ll try to keep this somewhat short and concise.
Thursday I realize that the majority of our team has a 45 minute layover in Newark which is already tight and with the recent weather unlikely to be enough time. I call up United Airlines and ask if we can move the group up to a flight that leaves on Sunday (the same day as originally planned) but about an hour earlier. I’m told it would be 200 a person if we wanted to make the change, but there is plenty of room. I suggest that we’re trying to just make sure we make our flight and United only has one flight out of Newark to the Caymans on Sunday so if we missed it, we’d be stuck. I’m assured we’ll be there in plenty of time.
Saturday I decide to tweet “@united we have developers flying down tmrw morn. w/45 min layover, there is an earlier flight to have 1.5hr layover, can move them up” to see if I have better luck. United is very responsive and quickly look through options via direct messages. The earlier flight is full and all other routes don’t look promising. I understand they can’t make seats appear and understand we’re hoping for the best. Saturday night at 9:55PM we get a notification from United our flight is delayed 20 minutes due to “Crew availability”.
We arrive Sunday morning and talk with an United service rep to see what we can do about our situation. We’re told that we still may make the connection with only 10 minutes now at the layover with our delay, but they have already double booked us on a backup flight to fly to Miami, stay the night, and fly out Monday morning to the Caymans. After another delay sets us back now an hour, we go back to the same rep and see if there are other routes we can take, like directly to Miami and catch a flight that night to the Caymans. Unfortunately all the seats straight there are full, but the rep says we have our Miami flight on “backup” and that we may be able to catch the last flight to the Caymans and to just board our delayed Newark flight.
We arrive in Newark and talk to a service rep to get our backup boarding passes. We find out that there is no booking for us at all, in fact the system couldn’t find any good alternatives so the automatic rebooking didn’t even work. At this point the rep in Newark says the rep in Boston never booked us on anything. Newark rep proceeds to try to get us on a later Miami flight, can’t get us confirmed, and then says we’ll rebook you tomorrow morning on a flight with an hour layover which you have to re-checkin for another airline and then will get to the Caymans. I brought up the last time the hour layover didn’t work so hot, but the rep said she wasn’t concerned we could always get another flight to the caymans later that day or the next day.
At this point we decide that the Jetblue direct flight from JFK is worth the extra money to have less of not arriving for another day at the Caymans. I call up United and try to get any sort of refund but am told our Boston-Newark flight was the majority of the cost so no refund would be given. We try to get our luggage from United which they say wait for at least an hour and it should come out on that belt. 2 hours later we find out that 2 of the 3 bags we’re waiting for are now Miami bound and they’ll try to figure it out in Miami what to do with them.
Looking back on this we all thought the biggest problem was the lack of communication and accountability. The group of us all felt that if there had been clear communication (or in some cases any communication) that much of the stress and problems would have been mitigated. The other problem is each time we did anything, we started having to double check that it was actually done.
Here are a some suggestions for possible improvements that I think may help all airlines (and possibly other industries) work better with their customers. Some of these may already exist at some airlines or not be feasible to do in some situations; I just wanted to get some thoughts out and see what people think.
- Have a clear, non-technical way which all communication can be documented and viewed. On several of my calls with United I asked them to make sure they made notes on my record to document what was discussed. Out of all those requests, I have not had one rep say they saw any log of any previous calls I made to them.
- Increase mediums for communication. United did a great job of responding quickly via Twitter, which also satisfies my first suggestion, however it would be great if there was a live chat for customers without Twitter. The live chat also provides easy documentation of everything that was discussed and who it was with.
- Increased accountability. One of the more frustrating parts of any situation is when you are told one thing, but find out from another representative that it is not the case. This seems to happen a lot at larger companies. Even when you can prove you were told one thing, the other representative’s answer is usually “they shouldn’t have said that”. I can’t imagine what our clients would think if you talked to one of our developers and were told one thing, but then told something completely differently from another developer. Aside from better training to prevent these situations, I would think the company would try to “make it up” in one fashion or another to the customer. Anytime I feel that we may have crossed communication here or misled someone, I make sure to do everything and anything within my power to make sure that the client is satisfied. I’m not saying the airline should dwell out free flights, but things that have a very small cost could make difference in the customers eyes, for example free access to the lounge.
- Callbacks. Some companies I’ve noticed have started to do this. You can call up, leave a number and it will ring you back when you are about to be connected with a representative. I imagine this should be more efficient for all parties. As a customer I no longer have to wait listening hold music for an hour or even worse have a dropped call after 35 minutes of holding. Often I’ll put the phone down and forget about it, and come back later to someone saying “This is the last time I will ask can you hear me?” On the airline side, representatives will have very few, if any, calls where the person has left for the moment and isn’t ready when they are taken off hold. If a user doesn’t answer, it could even try back 5 minutes later before removing them from the queue.
I understand our troubles with the airline getting down are no more important or different than the thousands of other’s that had problems. I’m more interested in seeing what ways we can try to improve the experience overall for both customers and airlines alike. I know running a business is never as simple as it seems and some of these suggestions may be implemented behind the scenes. However, there is always room for improvement.
What do you think? How can airlines improve the customer relations experience?
Posted In: General
Recently I was working on a project where part of it was doing data exports. Exports on the surface are quick and easy – query the database, put it into the export format, send it over to the user. However, as a data set grows, exports become more complicated. Now processing it in real time no longer works as it takes too long or too much memory to export. This is why I’ll almost always use a background process (notified via Gearman) to process the data and notify the user when the export is ready for download. On separate background threads you can have different memory limits and not worry about a request timeout. I suggest trying to not use Doctrine’s objects for the export, but get the query back in array format (via getArrayResult). Doctrine objects are great to work with, but expensive in terms of time to populate and memory usage; if you don’t need the object graph results in array format are much quicker and smaller memory wise.
On this specific export I was exporting an entity which had a foreign key to another table that needed to be in the export. I didn’t want to create a join over the entire data set as it was unnecessary. For example, a project which has a created by user as a relation. If I simply did the following:
I’d end up with an array which had all the project columns except any that are defined as a foreign key. This means in my export I couldn’t output the “Created by user id” as it wasn’t included in the array. It turns out that Doctrine already has this exact situation accounted for. To include the FK columns you need to set a hint on the query to include meta columns to true. The updated query code would look similar to:
Now you can include the foreign key columns without doing an joins on a query that returns an array result set.