launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #04570
[Merge] lp:~stub/launchpad/staging into lp:launchpad/db-devel
Stuart Bishop has proposed merging lp:~stub/launchpad/staging into lp:launchpad/db-devel.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
Related bugs:
Bug #809123 in Launchpad itself: "we cannot deploy DB schema changes live"
https://bugs.launchpad.net/launchpad/+bug/809123
Bug #824462 in Launchpad itself: "preflight check should confirm terminated connections are dead before proceeding"
https://bugs.launchpad.net/launchpad/+bug/824462
For more details, see:
https://code.launchpad.net/~stub/launchpad/staging/+merge/71184
= Summary =
Wait for killed connections to terminate before proceeding to long transaction checks.
== Proposed fix ==
Loop until the connections are gone, repeatedly attempting to kill them. Report failure if they can't be killed after 10 seconds.
== Pre-implementation notes ==
== Implementation details ==
== Tests ==
== Demo and Q/A ==
= Launchpad lint =
Checking for conflicts and issues in changed files.
Linting changed files:
database/schema/preflight.py
database/schema/full-update.py
./database/schema/preflight.py
7: '_pythonpath' imported but unused
./database/schema/full-update.py
7: '_pythonpath' imported but unused
--
https://code.launchpad.net/~stub/launchpad/staging/+merge/71184
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stub/launchpad/staging into lp:launchpad/db-devel.
=== modified file 'database/schema/full-update.py'
--- database/schema/full-update.py 2011-08-03 14:30:44 +0000
+++ database/schema/full-update.py 2011-08-11 11:42:24 +0000
@@ -105,17 +105,17 @@
# work unattended.
#
+ # Confirm we can invoke PGBOUNCER_INITD
+ log.debug("Confirming sudo access to pgbouncer startup script")
+ pgbouncer_rc = run_pgbouncer(log, 'status')
+ if pgbouncer_rc != 0:
+ return pgbouncer_rc
+
# We initially ignore open connections, as they will shortly be
# killed.
if not NoConnectionCheckPreflight(log).check_all():
return 99
- # Confirm we can invoke PGBOUNCER_INITD
- log.debug("Confirming sudo access to pgbouncer startup script")
- pgbouncer_rc = run_pgbouncer(log, 'status')
- if pgbouncer_rc != 0:
- return pgbouncer_rc
-
#
# Start the actual upgrade. Failures beyond this point need to
# generate informative messages to help with recovery.
=== modified file 'database/schema/preflight.py'
--- database/schema/preflight.py 2011-08-05 13:29:24 +0000
+++ database/schema/preflight.py 2011-08-11 11:42:24 +0000
@@ -15,7 +15,7 @@
from datetime import timedelta
from optparse import OptionParser
-import sys
+import time
import psycopg2
@@ -282,21 +282,40 @@
System users are defined by SYSTEM_USERS.
"""
- for node in self.lpmain_nodes:
- cur = node.con.cursor()
- cur.execute("""
- SELECT
- procpid, datname, usename, pg_terminate_backend(procpid)
- FROM pg_stat_activity
- WHERE
- datname=current_database()
- AND procpid <> pg_backend_pid()
- AND usename NOT IN %s
- """ % sqlvalues(SYSTEM_USERS))
- for procpid, datname, usename, ignored in cur.fetchall():
- self.log.warning(
- "Killed %s [%s] on %s", usename, procpid, datname)
- return True
+ # We keep trying to terminate connections every 0.5 seconds for
+ # up to 10 seconds.
+ num_tries = 20
+ seconds_to_pause = 0.5
+ for loop_count in range(num_tries):
+ all_clear = True
+ for node in self.lpmain_nodes:
+ cur = node.con.cursor()
+ cur.execute("""
+ SELECT
+ procpid, datname, usename,
+ pg_terminate_backend(procpid)
+ FROM pg_stat_activity
+ WHERE
+ datname=current_database()
+ AND procpid <> pg_backend_pid()
+ AND usename NOT IN %s
+ """ % sqlvalues(SYSTEM_USERS))
+ for procpid, datname, usename, ignored in cur.fetchall():
+ all_clear = False
+ if loop_count == num_tries - 1:
+ self.log.fatal(
+ "Unable to kill %s [%s] on %s",
+ usename, procpid, datname)
+ else:
+ self.log.warning(
+ "Killed %s [%s] on %s", usename, procpid, datname)
+ if all_clear:
+ break
+
+ # Wait a little for any terminated connections to actually
+ # terminate.
+ time.sleep(seconds_to_pause)
+ return all_clear
def main():
@@ -337,4 +356,4 @@
if __name__ == '__main__':
- sys.exit(main())
+ raise SystemExit(main())