diff --git a/pgweb/core/views.py b/pgweb/core/views.py index 90edbe6e..dcc11783 100644 --- a/pgweb/core/views.py +++ b/pgweb/core/views.py @@ -190,7 +190,7 @@ def admin_purge(request): # Fetch list of latest purges curs = connection.cursor() - curs.execute("SELECT ev_time, ev_data FROM pgq.event_1 WHERE ev_type='P' ORDER BY ev_time DESC LIMIT 20") + curs.execute("SELECT ev_time, ev_data FROM pgq.event_1 WHERE ev_type IN ('P', 'X') ORDER BY ev_time DESC LIMIT 20") latest = [{'t': r[0], 'u': r[1]} for r in curs.fetchall()] return render_to_response('core/admin_purge.html', { diff --git a/sql/varnish.sql b/sql/varnish.sql index 1b5f8d75..bfbdb743 100644 --- a/sql/varnish.sql +++ b/sql/varnish.sql @@ -13,4 +13,9 @@ AS $$ SELECT pgq.insert_event('varnish', 'P', $1); $$ LANGUAGE 'sql'; +CREATE OR REPLACE FUNCTION varnish_purge_expr(expr text) +RETURNS bigint +AS $$ + SELECT pgq.insert_event('varnish', 'X', $1); +$$ LANGUAGE 'sql'; COMMIT; \ No newline at end of file diff --git a/sql/varnish_local.sql b/sql/varnish_local.sql index cb3a9340..b827017b 100644 --- a/sql/varnish_local.sql +++ b/sql/varnish_local.sql @@ -12,4 +12,10 @@ AS $$ SELECT 1::bigint; $$ LANGUAGE 'sql'; +CREATE OR REPLACE FUNCTION varnish_purge_expr(url text) +RETURNS bigint +AS $$ + SELECT 1::bigint; +$$ LANGUAGE 'sql'; + COMMIT; \ No newline at end of file diff --git a/tools/pgq/varnish_consumer.py b/tools/pgq/varnish_consumer.py index 58648f25..dcab39a8 100755 --- a/tools/pgq/varnish_consumer.py +++ b/tools/pgq/varnish_consumer.py @@ -45,25 +45,31 @@ class VarnishPurger(pgq.Consumer): for ev in ev_list: if ev.type == 'P': - # 'P' events means purge. Currently it's the only event - # type we support. + # 'P' events means purge. print_t("Purging '%s' on %s" % (ev.data, self.frontend)) try: if self.do_purge(ev.data): ev.tag_done() except Exception, e: print_t("Failed to purge '%s' on '%s': %s" % (ev.data, self.frontend, e)) + elif ev.type == 'X': + # 'X' events means ban expression (rather than just urls) + print_t("Purging expression '%s' on %s" % (ev.data, self.frontend)) + try: + if self.do_purge_expr(ev.data): + ev.tag_done() + except Exception, e: + print_t("Failed to purge expression '%s' on '%s': %s" % (ev.data, self.frontend, e)) else: print_t("Unknown event type '%s'" % ev.type) - def do_purge(self, url): + def internal_purge(self, headers): """ Send the actual purge request, by contacting the frontend this purger is running for and sending a GET request to the special URL with our regexp in a special header. """ - headers = {'X-Purge-URL': url} conn = httplib.HTTPConnection('%s.postgresql.org' % self.frontend) conn.request("GET", "/varnish-purge-url", '', headers) resp = conn.getresponse() @@ -74,6 +80,11 @@ class VarnishPurger(pgq.Consumer): print_t("Varnish purge returned status %s (%s)" % (resp.status, resp.reason)) return False + def do_purge(self, url): + return self.internal_purge({'X-Purge-URL': url}) + + def do_purge_expr(self, expr): + return self.internal_purge({'X-Purge-Expr': expr}) class PurgerProcess(object): """