Skip to content

Commit 0d10dbf

Browse files
committed
Connect commands now accept timeout argument
1 parent 28eb847 commit 0d10dbf

File tree

6 files changed

+48
-18
lines changed

6 files changed

+48
-18
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Other changes:
2020
- Settings can now be specified in main `Preferences.sublime-settings` as well. Just prepend `clojure_sublimed_` to each setting’s name.
2121
- REPL can detect namespaces with meta on ns form
2222
- Detect `.shadow-cljs/nrepl.port` and `.shadow-cljs/socket-repl.port`
23+
- Connect commands now accept `timeout` argument for automation scenarios like “start clojure, start trying to connect to REPL until port is available”
2324

2425
### 3.8.0 - Aug 8, 2024
2526

cs_conn.py

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import os, re, sublime, sublime_plugin
1+
import os, re, sublime, sublime_plugin, threading, time
22
from . import cs_common, cs_eval, cs_eval_status, cs_parser, cs_warn
33

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

20+
def get_addr(self):
21+
return self.addr() if callable(self.addr) else self.addr
22+
2023
def connect_impl(self):
2124
pass
2225

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

40+
def try_connect_impl(self, timeout):
41+
state = cs_common.get_state(self.window)
42+
t0 = time.time()
43+
attempt = 1
44+
while time.time() - t0 <= timeout:
45+
time.sleep(0.25)
46+
try:
47+
cs_common.debug('Connection attempt #{} to {}', attempt, self.get_addr())
48+
self.connect_impl()
49+
state.conn = self
50+
return
51+
except Exception as e:
52+
attempt += 1
53+
cs_common.error('Giving up after {} sec connecting to {}', round(time.time() - t0, 2), self.get_addr())
54+
self.disconnect()
55+
if window := sublime.active_window():
56+
window.status_message(f'Connection failed')
57+
58+
def try_connect(self, timeout = 0):
59+
state = cs_common.get_state(self.window)
60+
if timeout:
61+
threading.Thread(target = self.try_connect_impl, args=(timeout,)).start()
62+
else:
63+
self.connect()
64+
3765
def ready(self):
3866
return bool(self.status and self.status[0] == phases[4])
3967

cs_conn_nrepl_jvm.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def handle_connect(self, msg):
8686
return True
8787

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

9292
def handle_new_session(self, msg):
@@ -136,12 +136,12 @@ def handle_msg(self, msg):
136136
or self.handle_lookup(msg)
137137

138138
class ClojureSublimedConnectNreplJvmCommand(sublime_plugin.WindowCommand):
139-
def run(self, address):
139+
def run(self, address, timeout = 0):
140140
state = cs_common.get_state(self.window)
141141
state.last_conn = ('clojure_sublimed_connect_nrepl_jvm', {'address': address})
142142
if address == 'auto':
143143
address = self.input({}).initial_text()
144-
ConnectionNreplJvm(address).connect()
144+
ConnectionNreplJvm(address).try_connect(timeout = timeout)
145145

146146
def input(self, args):
147147
if 'address' not in args:

cs_conn_nrepl_raw.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ def __init__(self, addr):
1616
self.output_view = None
1717

1818
def connect_impl(self):
19-
self.set_status(0, 'Connecting to {}...', self.addr)
20-
self.socket = cs_common.socket_connect(self.addr)
19+
self.set_status(0, 'Connecting to {}...', self.get_addr())
20+
self.socket = cs_common.socket_connect(self.get_addr())
2121
self.reader = threading.Thread(daemon=True, target=self.read_loop)
2222
self.reader.start()
2323

@@ -84,7 +84,7 @@ def interrupt_impl(self, batch_id, id):
8484
def handle_connect(self, msg):
8585
if 1 == msg.get('id') and 'new-session' in msg:
8686
self.session = msg['new-session']
87-
self.set_status(4, self.addr)
87+
self.set_status(4, self.get_addr())
8888
return True
8989

9090
def handle_disconnect(self, msg):
@@ -160,12 +160,13 @@ def handle_msg(self, msg):
160160
or self.handle_done(msg)
161161

162162
class ClojureSublimedConnectNreplRawCommand(sublime_plugin.WindowCommand):
163-
def run(self, address):
163+
def run(self, address, timeout = 0):
164164
state = cs_common.get_state(self.window)
165165
state.last_conn = ('clojure_sublimed_connect_nrepl_raw', {'address': address})
166166
if address == 'auto':
167167
address = self.input({}).initial_text()
168-
ConnectionNreplRaw(address).connect()
168+
while not state.conn:
169+
ConnectionNreplRaw(address).try_connect(timeout = timeout)
169170

170171
def input(self, args):
171172
if 'address' not in args:

cs_conn_shadow_cljs.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ def handle_connect(self, msg):
2727

2828
return True
2929
elif 2 == msg.get('id') and msg.get('status') == ['done']:
30-
self.set_status(4, self.addr)
30+
self.set_status(4, self.get_addr())
3131
return True
3232

3333
def handle_value(self, msg):
@@ -85,10 +85,10 @@ def preview(self, text):
8585
""")
8686

8787
class ClojureSublimedConnectShadowCljsCommand(sublime_plugin.WindowCommand):
88-
def run(self, address, build):
88+
def run(self, address, build, timeout = 0):
8989
state = cs_common.get_state(self.window)
9090
state.last_conn = ('clojure_sublimed_connect_shadow_cljs', {'address': address, 'build': build})
91-
ConnectionShadowCljs(address, build).connect()
91+
ConnectionShadowCljs(address, build).try_connect(timeout = timeout)
9292

9393
def input(self, args):
9494
if 'address' in args and 'build' in args:

cs_conn_socket_repl.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ def __init__(self, addr):
3030
self.closing = False
3131

3232
def connect_impl(self):
33-
self.set_status(0, 'Connecting to {}', self.addr)
34-
self.socket = cs_common.socket_connect(self.addr)
33+
self.set_status(0, 'Connecting to {}', self.get_addr())
34+
self.socket = cs_common.socket_connect(self.get_addr())
3535
self.reader = threading.Thread(daemon=True, target=self.read_loop)
3636
self.reader.start()
3737

@@ -57,7 +57,7 @@ def read_loop(self):
5757
self.handle_msg(msg)
5858
else:
5959
if '{"tag" "started"}' in line:
60-
self.set_status(4, self.addr)
60+
self.set_status(4, self.get_addr())
6161
started = True
6262
except OSError:
6363
pass
@@ -196,12 +196,12 @@ def handle_msg(self, msg):
196196
or self.handle_err(msg)
197197

198198
class ClojureSublimedConnectSocketReplCommand(sublime_plugin.WindowCommand):
199-
def run(self, address):
199+
def run(self, address, timeout = 0):
200200
state = cs_common.get_state(self.window)
201201
state.last_conn = ('clojure_sublimed_connect_socket_repl', {'address': address})
202202
if address == 'auto':
203-
address = self.input({}).initial_text()
204-
ConnectionSocketRepl(address).connect()
203+
address = lambda: self.input({}).initial_text()
204+
ConnectionSocketRepl(address).try_connect(timeout = timeout)
205205

206206
def input(self, args):
207207
if 'address' not in args:

0 commit comments

Comments
 (0)