From 6a9f748d03531b2fd90deb7219e5e2d4b7b3d452 Mon Sep 17 00:00:00 2001 From: koljonen Date: Wed, 29 Jun 2016 14:13:12 +0200 Subject: [PATCH 1/5] Make connections per view instead of per buffer (i.e. file) --- pgcli_sublime.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pgcli_sublime.py b/pgcli_sublime.py index fdfc667..7f9aef7 100644 --- a/pgcli_sublime.py +++ b/pgcli_sublime.py @@ -20,7 +20,7 @@ completers = {} # Dict mapping urls to pgcompleter objects completer_lock = Lock() -executors = {} # Dict mapping buffer ids to pgexecutor objects +executors = {} # Dict mapping view ids to pgexecutor objects executor_lock = Lock() recent_urls = [] @@ -372,8 +372,8 @@ def check_pgcli(view): return with executor_lock: - buffer_id = view.buffer_id() - if buffer_id not in executors: + view_id = view.id() + if view_id not in executors: url = get(view, 'pgcli_url') if not url: @@ -394,7 +394,7 @@ def check_pgcli(view): status = 'ERROR CONNECTING TO {}'.format(url) view.set_status('pgcli', status) - executors[buffer_id] = executor + executors[view_id] = executor # Make sure we have a completer for the corresponding url with completer_lock: @@ -461,7 +461,7 @@ def run_sqls_async(view, sqls): def run_sql_async(view, sql, panel): - executor = executors[view.buffer_id()] + executor = executors[view.id()] logger.debug('Command: PgcliExecute: %r', sql) save_mode = get(view, 'pgcli_save_on_run_query_mode') From 090ba76160a46808a8aba4c321ab80568a9ea536 Mon Sep 17 00:00:00 2001 From: koljonen Date: Wed, 29 Jun 2016 14:23:47 +0200 Subject: [PATCH 2/5] Close the corresponding db connection when a view is closed --- pgcli_sublime.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pgcli_sublime.py b/pgcli_sublime.py index 7f9aef7..b25cca0 100644 --- a/pgcli_sublime.py +++ b/pgcli_sublime.py @@ -89,6 +89,11 @@ def plugin_unloaded(): class PgcliPlugin(sublime_plugin.EventListener): + def on_close(self, view): + executor = executors.pop(view.id()) + if executor: + executor.conn.close() + def on_post_save_async(self, view): check_pgcli(view) From 0a22d2dbaadfaf4ccc4856224299a15941c9ec92 Mon Sep 17 00:00:00 2001 From: Joakim Koljonen Date: Tue, 5 Jul 2016 22:45:09 +0200 Subject: [PATCH 3/5] Automatically reconnect when a connection is broken --- pgcli_sublime.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pgcli_sublime.py b/pgcli_sublime.py index b25cca0..fc434fe 100644 --- a/pgcli_sublime.py +++ b/pgcli_sublime.py @@ -470,6 +470,13 @@ def run_sql_async(view, sql, panel): logger.debug('Command: PgcliExecute: %r', sql) save_mode = get(view, 'pgcli_save_on_run_query_mode') + try: # Check if the connection has died + executor.conn.cursor().execute('select 1') + except psycopg2.DatabaseError: + pass # psycopg2 has now marked the connection as closed + if executor.conn.closed: + logger.debug('DB connection closed; reconnecting') + executor.connect() # Make sure the output panel is visiblle sublime.active_window().run_command('pgcli_show_output_panel') # Put a leading datetime From 41b22e3a7c4830a10cc923ec5eec7c570eb77ae3 Mon Sep 17 00:00:00 2001 From: Joakim Koljonen Date: Sat, 30 Jul 2016 18:35:46 +0200 Subject: [PATCH 4/5] Avoid KeyError when trying to close connection --- pgcli_sublime.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pgcli_sublime.py b/pgcli_sublime.py index fc434fe..ed2a194 100644 --- a/pgcli_sublime.py +++ b/pgcli_sublime.py @@ -90,7 +90,7 @@ def plugin_unloaded(): class PgcliPlugin(sublime_plugin.EventListener): def on_close(self, view): - executor = executors.pop(view.id()) + executor = executors.pop(view.id(), None) if executor: executor.conn.close() From 47bfd16f747ca37a0e440f17a1b666e7b67c4a17 Mon Sep 17 00:00:00 2001 From: Joakim Koljonen Date: Thu, 4 Aug 2016 20:34:56 +0200 Subject: [PATCH 5/5] Move reconnect logic into main exception handler --- pgcli_sublime.py | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/pgcli_sublime.py b/pgcli_sublime.py index ed2a194..79fecd8 100644 --- a/pgcli_sublime.py +++ b/pgcli_sublime.py @@ -469,32 +469,32 @@ def run_sql_async(view, sql, panel): executor = executors[view.id()] logger.debug('Command: PgcliExecute: %r', sql) save_mode = get(view, 'pgcli_save_on_run_query_mode') - - try: # Check if the connection has died - executor.conn.cursor().execute('select 1') - except psycopg2.DatabaseError: - pass # psycopg2 has now marked the connection as closed - if executor.conn.closed: - logger.debug('DB connection closed; reconnecting') - executor.connect() # Make sure the output panel is visiblle sublime.active_window().run_command('pgcli_show_output_panel') # Put a leading datetime datestr = str(datetime.datetime.now()) + '\n\n' panel.run_command('append', {'characters': datestr, 'pos': 0}) - results = executor.run(sql, pgspecial=special) - try: - for (title, cur, headers, status, _, _) in results: - fmt = format_output(title, cur, headers, status, 'psql') - out = ('\n'.join(fmt) - + '\n\n' + str(datetime.datetime.now()) + '\n\n') + for attempts in range(2): + results = executor.run(sql, pgspecial=special) + try: + for (title, cur, headers, status, _, _) in results: + fmt = format_output(title, cur, headers, status, 'psql') + out = ('\n'.join(fmt) + + '\n\n' + str(datetime.datetime.now()) + '\n\n') + panel.run_command('append', {'characters': out}) + except psycopg2.DatabaseError as e: + success = False + out = str(e) + '\n\n' + str(datetime.datetime.now()) + '\n\n' panel.run_command('append', {'characters': out}) - except psycopg2.DatabaseError as e: - success = False - out = str(e) + '\n\n' + str(datetime.datetime.now()) + '\n\n' - panel.run_command('append', {'characters': out}) - else: - success = True + if executor.conn.closed and attempts == 0: + panel.run_command('append', { + 'characters': 'Reconnecting ...\n\n'}) + executor.connect() + else: + break + else: + success = True + break if (view.file_name() and ((save_mode == 'always')