Skip to content

Commit

Permalink
Connect commands now accept timeout argument
Browse files Browse the repository at this point in the history
  • Loading branch information
tonsky committed Aug 23, 2024
1 parent 28eb847 commit 0d10dbf
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Other changes:
- Settings can now be specified in main `Preferences.sublime-settings` as well. Just prepend `clojure_sublimed_` to each setting’s name.
- REPL can detect namespaces with meta on ns form
- Detect `.shadow-cljs/nrepl.port` and `.shadow-cljs/socket-repl.port`
- Connect commands now accept `timeout` argument for automation scenarios like “start clojure, start trying to connect to REPL until port is available”

### 3.8.0 - Aug 8, 2024

Expand Down
30 changes: 29 additions & 1 deletion cs_conn.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import os, re, sublime, sublime_plugin
import os, re, sublime, sublime_plugin, threading, time
from . import cs_common, cs_eval, cs_eval_status, cs_parser, cs_warn

status_key = 'clojure-sublimed-conn'
Expand All @@ -17,6 +17,9 @@ def __init__(self):
self.disconnecting = False
self.window = sublime.active_window()

def get_addr(self):
return self.addr() if callable(self.addr) else self.addr

def connect_impl(self):
pass

Expand All @@ -34,6 +37,31 @@ def connect(self):
if window := sublime.active_window():
window.status_message(f'Connection failed')

def try_connect_impl(self, timeout):
state = cs_common.get_state(self.window)
t0 = time.time()
attempt = 1
while time.time() - t0 <= timeout:
time.sleep(0.25)
try:
cs_common.debug('Connection attempt #{} to {}', attempt, self.get_addr())
self.connect_impl()
state.conn = self
return
except Exception as e:
attempt += 1
cs_common.error('Giving up after {} sec connecting to {}', round(time.time() - t0, 2), self.get_addr())
self.disconnect()
if window := sublime.active_window():
window.status_message(f'Connection failed')

def try_connect(self, timeout = 0):
state = cs_common.get_state(self.window)
if timeout:
threading.Thread(target = self.try_connect_impl, args=(timeout,)).start()
else:
self.connect()

def ready(self):
return bool(self.status and self.status[0] == phases[4])

Expand Down
6 changes: 3 additions & 3 deletions cs_conn_nrepl_jvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def handle_connect(self, msg):
return True

elif 5 == msg.get('id') and 'done' in msg.get('status', []):
self.set_status(4, self.addr)
self.set_status(4, self.get_addr())
return True

def handle_new_session(self, msg):
Expand Down Expand Up @@ -136,12 +136,12 @@ def handle_msg(self, msg):
or self.handle_lookup(msg)

class ClojureSublimedConnectNreplJvmCommand(sublime_plugin.WindowCommand):
def run(self, address):
def run(self, address, timeout = 0):
state = cs_common.get_state(self.window)
state.last_conn = ('clojure_sublimed_connect_nrepl_jvm', {'address': address})
if address == 'auto':
address = self.input({}).initial_text()
ConnectionNreplJvm(address).connect()
ConnectionNreplJvm(address).try_connect(timeout = timeout)

def input(self, args):
if 'address' not in args:
Expand Down
11 changes: 6 additions & 5 deletions cs_conn_nrepl_raw.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ def __init__(self, addr):
self.output_view = None

def connect_impl(self):
self.set_status(0, 'Connecting to {}...', self.addr)
self.socket = cs_common.socket_connect(self.addr)
self.set_status(0, 'Connecting to {}...', self.get_addr())
self.socket = cs_common.socket_connect(self.get_addr())
self.reader = threading.Thread(daemon=True, target=self.read_loop)
self.reader.start()

Expand Down Expand Up @@ -84,7 +84,7 @@ def interrupt_impl(self, batch_id, id):
def handle_connect(self, msg):
if 1 == msg.get('id') and 'new-session' in msg:
self.session = msg['new-session']
self.set_status(4, self.addr)
self.set_status(4, self.get_addr())
return True

def handle_disconnect(self, msg):
Expand Down Expand Up @@ -160,12 +160,13 @@ def handle_msg(self, msg):
or self.handle_done(msg)

class ClojureSublimedConnectNreplRawCommand(sublime_plugin.WindowCommand):
def run(self, address):
def run(self, address, timeout = 0):
state = cs_common.get_state(self.window)
state.last_conn = ('clojure_sublimed_connect_nrepl_raw', {'address': address})
if address == 'auto':
address = self.input({}).initial_text()
ConnectionNreplRaw(address).connect()
while not state.conn:
ConnectionNreplRaw(address).try_connect(timeout = timeout)

def input(self, args):
if 'address' not in args:
Expand Down
6 changes: 3 additions & 3 deletions cs_conn_shadow_cljs.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def handle_connect(self, msg):

return True
elif 2 == msg.get('id') and msg.get('status') == ['done']:
self.set_status(4, self.addr)
self.set_status(4, self.get_addr())
return True

def handle_value(self, msg):
Expand Down Expand Up @@ -85,10 +85,10 @@ def preview(self, text):
""")

class ClojureSublimedConnectShadowCljsCommand(sublime_plugin.WindowCommand):
def run(self, address, build):
def run(self, address, build, timeout = 0):
state = cs_common.get_state(self.window)
state.last_conn = ('clojure_sublimed_connect_shadow_cljs', {'address': address, 'build': build})
ConnectionShadowCljs(address, build).connect()
ConnectionShadowCljs(address, build).try_connect(timeout = timeout)

def input(self, args):
if 'address' in args and 'build' in args:
Expand Down
12 changes: 6 additions & 6 deletions cs_conn_socket_repl.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ def __init__(self, addr):
self.closing = False

def connect_impl(self):
self.set_status(0, 'Connecting to {}', self.addr)
self.socket = cs_common.socket_connect(self.addr)
self.set_status(0, 'Connecting to {}', self.get_addr())
self.socket = cs_common.socket_connect(self.get_addr())
self.reader = threading.Thread(daemon=True, target=self.read_loop)
self.reader.start()

Expand All @@ -57,7 +57,7 @@ def read_loop(self):
self.handle_msg(msg)
else:
if '{"tag" "started"}' in line:
self.set_status(4, self.addr)
self.set_status(4, self.get_addr())
started = True
except OSError:
pass
Expand Down Expand Up @@ -196,12 +196,12 @@ def handle_msg(self, msg):
or self.handle_err(msg)

class ClojureSublimedConnectSocketReplCommand(sublime_plugin.WindowCommand):
def run(self, address):
def run(self, address, timeout = 0):
state = cs_common.get_state(self.window)
state.last_conn = ('clojure_sublimed_connect_socket_repl', {'address': address})
if address == 'auto':
address = self.input({}).initial_text()
ConnectionSocketRepl(address).connect()
address = lambda: self.input({}).initial_text()
ConnectionSocketRepl(address).try_connect(timeout = timeout)

def input(self, args):
if 'address' not in args:
Expand Down

0 comments on commit 0d10dbf

Please sign in to comment.