tags:

views:

89

answers:

3

I'm trying to build a Quicksilver style search system for the internal web app that we develop at work. There are plenty of examples of really cool front ends for this using JQuery or MooTools or whatever. None of these examples really talk about the back-end. As far as I can tell, these examples assuming the back-end is searching a single table or at least, performing a single query. What I want to do is design a system where you can, literally, type anything at all at it and find what you were looking for. Idealy, I want to be able to just write plugins for this system, drop them in, and start searching.

I have a solution where the back-end uses the observer pattern to send the query to different plugins for each type of search. However, this will return the results from all the plug-ins as one chunk. This could get noticeably slow if there are many kinds of searches. I'd like it to be quick and return the results in a more asynchronous fashion where results are displayed as they come in, a la OS X's Spotlight or Quicksilver.

Another solution is to write, on the fly, a javascript array with the names of the plug-ins to be used. I could then fire off separate calls to the server with the query, one for each plug-in. Something about this solution seems... off to me. I can't exactly put my finger on it though.

So, my question is: does anyone have any better solutions for building a plug-in based search system where the individual search types are not known before the page is loaded and the results are returned ASAP?

+1  A: 

You could do a Comet style solution that used long polling in Ajax to get results for the search. Make one place for the script to call that will give back the results of all the plugins as they come in. This method allows you to get the quick results displayed sooner.

Having an array of plugins is an option but some browsers are limited to 2 requests at a time so that would limit the amount of request just being kicked off and could cause a fast process to have to wait for the slow processes.

It sounds like you are getting close with with back end you have just make it provide up the data as it comes in. Also this will allow you to add and remove plugins on the fly without effecting the JS so no worries about cached array lists.

A few thoughts on the back end from comment. Build a work queue so search requests can be farmed out to many workers. It would be possible to implement the work queue in a DB or through a web service so you could use other languages or even computers to do the work for each search. The work call would need some id to pass back to direct the data at the correct client. Also you would want a way to remove jobs from the queue or at least mark all work for a client as void if that client goes away. (You should be able to detect this if you are using long polling.)

Connection limits

IE7 for HTTP1 4

IE7 for HTTP1.1 2

IE8 for HTTP1 6

IE8 for HTTP1.1 6

Jeff Beck
The problem I'm having is also on the back end. With the solution I have now, each search has to complete before the next will be run. This is a limitation of the way I've implemented the observer pattern. I've looked into forking a process or making async calls, but apparently it's a giant pain in PHP.
docgnome
What I would do is build a work queue. Each search plugin gets a queue and you can push the work from the call to each queue. The plugins can be configured to have pools of workers or just one worker and execute the searches as needed. The results are passed back to your comet style solution and pushed out to the client. This will allow you to have threads in PHP doing the work or even possibly other languages depending on your queue system.
Jeff Beck
I know that max requests is a per browser setting. Which browsers in particular are so limited by default? I'm not really that concerned about anything older than say... IE 7 and Firefox 3
docgnome
While the max requests could be a problem, making Apache handle the concurrency problems seems simpler than trying to handle them myself. I'm sort of coming to the conclusion that that is what I need to do rather than handle it myself. PHP is the preferred language as that is what the rest of the shop I work at is most familiar with. PHP's concurrency support inside of a request is pretty flippin' terrible.
docgnome
If you are worried about the number of requests, you very easily could trick the browser into thinking that it was for different domains. If you use separate sub domains for the requests sent. You will need a wild card cert if you are concerned about SSL though.
mediaslave
Here is an example of my last comment: http://www.ajaxperformance.com/2006/12/18/circumventing-browser-connection-limits-for-fun-and-profit/
mediaslave
+1  A: 

Another solution is to write, on the fly, a javascript array with the names of the plug-ins to be used. I could then fire off separate calls to the server with the query, one for each plug-in. Something about this solution seems... off to me. I can't exactly put my finger on it though.

This does not seem like that bad of an option. It gives you everything you need.

  1. You need search results to come back as soon as they can.
  2. It allows you to use your existing plugin architecture, I believe.
  3. It follows the KISS principle.

It is not a new solution, but I think that it is the easiest.

Regards.

mediaslave
I guess the real advantage of this solution is that it removes the burden of concurrent programing from me and hands it off to the web server, in this case Apache. Something about it still makes me uneasy, but more than one other person has suggested it. In this case, I guess I'll just ignore my gut feeling.
docgnome
I guess if you are worried about your gut feeling, then you could implement the solution, depending on deadlines and other factors. At some point when your gut tells what it is feeling and what the solution is you can then refactor the problem. Red - Green - Refactor.
mediaslave
On 2 it seems that he would need to change the plugins slightly as they are currently behind one call.
Jeff Beck
+1  A: 

From all the comments and talk it seems like you want to build this on the front end.

Don't build an array of plugins to call it forces you to worry about caching when changing out plugins you should do instead is build a bootstrap system. It would be a simple ajax call that got a list of plugins with there URL to call. This will allow you to turn on and off plugins from a central location and it will work better.

You will have to make each of your plugins into a web service instead of a plugin so each can be called independently. Make sure to use mediasalve's link about the number of connections because it will be limited by browsers if you don't get around it.

Jeff Beck
If you are worried about caching issues and you don't want to build a boot strap file, because you don't like the idea of an unnecessary ajax call there could be another solution. The dynamic array can hold an extra element that is a hash of the current time or something simmilar array(plugins=>array('foo', 'bar'), unique=>'hsodifwejrljfe983ojhsrfiauf0usd0fsd70f98sdf')This bit of javascript will not be cached now.
mediaslave
@jeff I do like your idea, just trying to keep the options open. ;)
mediaslave
Actually it would still be in the the JS file so that would be cached. You could add a hash like that onto the request for the JS file so it doesn't get cache and that would work. I have had a lot of head aches recently with a client who's IT departs cache servers don't follow directives correctly so I'm having JS files not refreshed for days. In most cases you could get by without the boot strap I'm just once bitten and being twice shy.
Jeff Beck