Index: server/trunk/web/lib/Sophie/Base/Async.pm
===================================================================
--- server/trunk/web/lib/Sophie/Base/Async.pm	(revision 108)
+++ server/trunk/web/lib/Sophie/Base/Async.pm	(revision 108)
@@ -0,0 +1,77 @@
+package Sophie::Base::Async;
+
+use strict;
+use warnings;
+use DBD::Pg qw(:async);
+use Time::HiRes qw(sleep);
+
+sub new {
+    my ($class, $rs, %options) = @_;
+
+    my $query = $options{build}
+        ? $options{build}->($rs)->as_query
+        : $rs->as_query;
+    my ($sql, @bind) = @{ $$query };
+    my $sth = $rs->storage->dbh->prepare(
+        $sql,
+        { pg_async => PG_ASYNC } 
+    ) or return;
+
+    my $time = time;
+    $sth->execute(map { $_->[1] } @bind);
+
+    bless {
+        rs => $rs,
+        sth => $sth,
+        start => $time,
+        timeout => $options{timeout} || 10,
+    }, $class;
+}
+
+sub DESTROY {
+    my ($self) = @_;
+    $self->cancel;
+}
+
+sub cancel {
+    my ($self) = @_;
+    if ($self->{sth}) {
+        $self->{sth}->pg_cancel;
+        $self->{sth} = undef;
+        return 1;
+    } else {
+        return;
+    }
+}
+
+sub result {
+    my ($self) = @_;
+    if (!$self->{sth}) {
+        return;
+    }
+    if ($self->{rs}->storage->dbh->pg_ready) {
+        my $sth = $self->{sth};
+        $self->{sth} = undef;
+        $sth->pg_result;
+        return $sth;
+    } else {
+        return undef;
+    }
+}
+
+sub wait_result {
+    my ($self) = @_;
+
+    while (1) {
+        if (my $res = $self->result) {
+            return $res;
+        }
+        if (time > $self->{start} + $self->{timeout}) {
+            $self->cancel;
+            return;
+        }
+        sleep(0.25);
+    }
+}
+
+1;
Index: server/trunk/web/lib/Sophie/Controller/0Explorer.pm
===================================================================
--- server/trunk/web/lib/Sophie/Controller/0Explorer.pm	(revision 107)
+++ server/trunk/web/lib/Sophie/Controller/0Explorer.pm	(revision 108)
@@ -2,4 +2,6 @@
 use Moose;
 use namespace::autoclean;
+use DBD::Pg qw(:async);
+use Sophie::Base::Async;
 
 BEGIN {extends 'Catalyst::Controller'; }
@@ -31,25 +33,38 @@
             $c->session->{__explorer}, 1 ]);
     my %uniq;
-    foreach (
-        $c->model('Base')
-        ->resultset('Files')
-        ->search(
-            {
-                dirname => '/' . ($dir ? "$dir/" : ''),
-                ($rsdist 
-                    ? (pkgid => { IN => $rsdist->get_column('pkgid')->as_query, },)
-                    : ()),
-                ($c->req->param('filename')
-                    ? ( basename => { LIKE => $c->req->param('filename') . '%' } )
-                    : ()),
-            },
-            {
-                #order_by => [ 'basename' ],
-                #group_by => [ 'basename' ], 
-                select => [ 'basename' ],
-            }
-        )->get_column('basename')->all) {
-        $uniq{$_} = 1;
+
+    my $query = Sophie::Base::Async->new(
+        $c->model('Base'),
+        timeout => 10,
+        build => sub { $_[0]
+            ->resultset('Files')
+            ->search(
+                {
+                    dirname => '/' . ($dir ? "$dir/" : ''),
+                    ($rsdist 
+                        ? (pkgid => { IN => $rsdist->get_column('pkgid')->as_query, },)
+                        : ()),
+                    ($c->req->param('filename')
+                        ? ( basename => { LIKE => $c->req->param('filename') . '%' } )
+                        : ()),
+                },
+                {
+                    #order_by => [ 'basename' ],
+                    #group_by => [ 'basename' ], 
+                    select => [ 'basename' ],
+                }
+            )
+            ->get_column('basename')
+        },
+    );
+
+    if(my $sth = $query->wait_result) {
+        while (my $res = $sth->fetchrow_hashref()) {
+            $uniq{$res->{basename}} = 1;
+        }
+    } else {
+        $c->stash->{timeout} = 1;
     }
+
     $c->stash->{xmlrpc} = [ sort keys %uniq ]; 
 }
