Compare commits
2 Commits
20227dde4d
...
63ef3a8313
| Author | SHA1 | Date | |
|---|---|---|---|
| 63ef3a8313 | |||
| 05c08e3223 |
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "sessions-sublime"
|
||||
version = "0.7.29"
|
||||
version = "0.7.30"
|
||||
description = "Sublime-facing Python code for Sessions."
|
||||
requires-python = ">=3.8"
|
||||
license = {text = "MIT"}
|
||||
|
||||
12
rust/Cargo.lock
generated
12
rust/Cargo.lock
generated
@@ -221,7 +221,7 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
|
||||
|
||||
[[package]]
|
||||
name = "local_bridge"
|
||||
version = "0.7.29"
|
||||
version = "0.7.30"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"glob",
|
||||
@@ -432,7 +432,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "session_helper"
|
||||
version = "0.7.29"
|
||||
version = "0.7.30"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"notify",
|
||||
@@ -443,7 +443,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "session_protocol"
|
||||
version = "0.7.29"
|
||||
version = "0.7.30"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"serde",
|
||||
@@ -452,14 +452,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "sessions_askpass"
|
||||
version = "0.7.29"
|
||||
version = "0.7.30"
|
||||
dependencies = [
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sessions_native"
|
||||
version = "0.7.29"
|
||||
version = "0.7.30"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"serde_json",
|
||||
@@ -772,7 +772,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "workspace_identity"
|
||||
version = "0.7.29"
|
||||
version = "0.7.30"
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
|
||||
@@ -12,7 +12,7 @@ resolver = "2"
|
||||
[workspace.package]
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
version = "0.7.29"
|
||||
version = "0.7.30"
|
||||
authors = ["Myeongseon Choi <key262yek@gmail.com>"]
|
||||
repository = "https://git.teahaven.kr/sublime-rs/sessions"
|
||||
homepage = "https://git.teahaven.kr/sublime-rs/sessions"
|
||||
|
||||
@@ -1860,20 +1860,20 @@ def _schedule_sidebar_placeholder_hydrate(view: object) -> None:
|
||||
|
||||
_set_timeout(finish, 50)
|
||||
|
||||
# User-facing critical path: hydrate the file the user just opened.
|
||||
# Run on a dedicated daemon thread so neither ``eager_hydrate`` nor
|
||||
# ``sessions.refresh_git_state`` (which can block the shared worker
|
||||
# for up to 5 minutes on a slow ``git fetch``) can stall it. The
|
||||
# ``_HYDRATE_IN_FLIGHT`` set above already dedupes per-view, so
|
||||
# losing the queue's task_key dedup costs nothing.
|
||||
if bool(getattr(sublime, "_sessions_test_sync", False)):
|
||||
work()
|
||||
else:
|
||||
threading.Thread(
|
||||
target=work,
|
||||
daemon=True,
|
||||
name="sessions-hydrate-open-file-{}".format(view_id),
|
||||
).start()
|
||||
# Run on the shared background worker — sequential dispatch keeps the
|
||||
# number of concurrent broker.request callers bounded (one). v0.7.29
|
||||
# tried thread-per-view but rapid tab-switching spawned many threads
|
||||
# that contended on Sublime's non-thread-safe View API and bus-
|
||||
# errored on macOS. Long-running tasks that previously HOL-blocked
|
||||
# this lane (``eager_hydrate``, ``sessions.refresh_git_state``) now
|
||||
# have their own dedicated threads, so single-worker queueing is
|
||||
# safe again.
|
||||
_run_in_background(
|
||||
work,
|
||||
prioritize=True,
|
||||
task_key="hydrate:{}".format(path_str),
|
||||
task_label="hydrate_open_file",
|
||||
)
|
||||
|
||||
|
||||
class SessionsSidebarPlaceholderHydrateListener(sublime_plugin.EventListener):
|
||||
@@ -3592,6 +3592,19 @@ def _schedule_eager_hydrate_if_needed(
|
||||
if not basenames:
|
||||
return
|
||||
cache_key = context.cache_key
|
||||
# Fast-path skip: every workspace activation re-fires this scheduler
|
||||
# and an idle workspace with zero placeholders would otherwise spawn a
|
||||
# do-nothing thread on every tab switch (see the spam of
|
||||
# ``hydrated:0 skipped_existing:0 failed:0`` traces). Run a cheap
|
||||
# local-fs scan to bail out before threading.
|
||||
try:
|
||||
candidates = _rust_ffi.eager_hydrate_find_candidates(
|
||||
str(context.local_cache_root), list(basenames)
|
||||
)
|
||||
except Exception:
|
||||
candidates = ()
|
||||
if not candidates:
|
||||
return
|
||||
if bool(getattr(sublime, "_sessions_test_sync", False)):
|
||||
_eager_hydrate_workspace(window, context, basenames)
|
||||
return
|
||||
|
||||
@@ -644,16 +644,13 @@ def test_hydrate_precheck_error_skips_read_for_active_view(
|
||||
assert opened_calls == []
|
||||
|
||||
|
||||
def test_hydrate_schedule_runs_synchronously_in_test_mode(
|
||||
def test_hydrate_schedule_sets_path_scoped_task_key(
|
||||
tmp_path: Path, monkeypatch
|
||||
) -> None:
|
||||
"""v0.7.28+ hydrate-on-open runs on a dedicated daemon thread per
|
||||
view (not the shared background queue) so it cannot be head-of-
|
||||
line-blocked by long-running tasks (eager_hydrate,
|
||||
sessions.refresh_git_state). Under ``_sessions_test_sync`` the
|
||||
function falls back to running work() inline; we verify the
|
||||
expected ``open_remote_file_into_local_cache`` invocation reaches
|
||||
the right remote path with the right view-id dedup."""
|
||||
"""v0.7.30 reverts hydrate-on-open back to the shared background
|
||||
queue (single worker, sequential dispatch) — v0.7.29's per-view
|
||||
thread spawning crashed on rapid tab-switching due to concurrent
|
||||
Sublime View API calls. The queue's ``task_key`` dedup is back."""
|
||||
context = commands._WorkspaceContext(
|
||||
settings=SessionsSettings(),
|
||||
recent_entry=RecentWorkspace(
|
||||
@@ -679,38 +676,22 @@ def test_hydrate_schedule_runs_synchronously_in_test_mode(
|
||||
)
|
||||
view.id = lambda: 43
|
||||
|
||||
captured_remotes: List[str] = []
|
||||
|
||||
def fake_open(host, **kwargs):
|
||||
captured_remotes.append(kwargs["remote_absolute_path"])
|
||||
return commands.OpenFileResult(
|
||||
outcome=commands.OpenOutcome.OK,
|
||||
local_cache_path=kwargs["local_cache_path"],
|
||||
)
|
||||
|
||||
captured: List[Optional[str]] = []
|
||||
monkeypatch.setattr(commands, "_mirror_hydrate_placeholders_on_open", lambda: True)
|
||||
monkeypatch.setattr(commands, "_workspace_context", lambda *args, **kwargs: context)
|
||||
monkeypatch.setattr(
|
||||
commands, "_workspace_runtime_connected", lambda *args, **kwargs: True
|
||||
)
|
||||
monkeypatch.setattr(commands, "_active_view", lambda window: view)
|
||||
monkeypatch.setattr(
|
||||
commands,
|
||||
"_precheck_remote_file_openability",
|
||||
lambda **kwargs: commands._HydratePrecheckOutcome(
|
||||
proceed=True, stat_metadata=None
|
||||
),
|
||||
"_run_in_background",
|
||||
lambda target, *args, **kwargs: captured.append(kwargs.get("task_key")),
|
||||
)
|
||||
monkeypatch.setattr(commands, "open_remote_file_into_local_cache", fake_open)
|
||||
monkeypatch.setattr(commands, "_apply_hydrate_result", lambda **kwargs: None)
|
||||
monkeypatch.setattr(commands, "_set_timeout", lambda fn, ms: fn())
|
||||
monkeypatch.setattr(commands.sublime, "_sessions_test_sync", True, raising=False)
|
||||
commands._HYDRATE_IN_FLIGHT.clear()
|
||||
|
||||
commands._schedule_sidebar_placeholder_hydrate(view)
|
||||
|
||||
assert captured_remotes == ["/srv/ws/app.py"]
|
||||
assert 43 in commands._HYDRATE_IN_FLIGHT
|
||||
assert captured == ["hydrate:{}".format(str(local_file))]
|
||||
|
||||
|
||||
def test_hydrate_schedule_fetches_for_nonexistent_cache_file(
|
||||
@@ -752,38 +733,23 @@ def test_hydrate_schedule_fetches_for_nonexistent_cache_file(
|
||||
)
|
||||
view.id = lambda: 99
|
||||
|
||||
captured_remotes: List[str] = []
|
||||
|
||||
def fake_open(host, **kwargs):
|
||||
captured_remotes.append(kwargs["remote_absolute_path"])
|
||||
return commands.OpenFileResult(
|
||||
outcome=commands.OpenOutcome.OK,
|
||||
local_cache_path=kwargs["local_cache_path"],
|
||||
)
|
||||
|
||||
captured: List[Optional[str]] = []
|
||||
monkeypatch.setattr(commands, "_mirror_hydrate_placeholders_on_open", lambda: True)
|
||||
monkeypatch.setattr(commands, "_workspace_context", lambda *args, **kwargs: context)
|
||||
monkeypatch.setattr(
|
||||
commands, "_workspace_runtime_connected", lambda *args, **kwargs: True
|
||||
)
|
||||
monkeypatch.setattr(commands, "_active_view", lambda window: view)
|
||||
monkeypatch.setattr(
|
||||
commands,
|
||||
"_precheck_remote_file_openability",
|
||||
lambda **kwargs: commands._HydratePrecheckOutcome(
|
||||
proceed=True, stat_metadata=None
|
||||
),
|
||||
"_run_in_background",
|
||||
lambda target, *args, **kwargs: captured.append(kwargs.get("task_key")),
|
||||
)
|
||||
monkeypatch.setattr(commands, "open_remote_file_into_local_cache", fake_open)
|
||||
monkeypatch.setattr(commands, "_apply_hydrate_result", lambda **kwargs: None)
|
||||
monkeypatch.setattr(commands, "_set_timeout", lambda fn, ms: fn())
|
||||
monkeypatch.setattr(commands.sublime, "_sessions_test_sync", True, raising=False)
|
||||
commands._HYDRATE_IN_FLIGHT.clear()
|
||||
|
||||
commands._schedule_sidebar_placeholder_hydrate(view)
|
||||
|
||||
assert captured_remotes == ["/srv/ws/src/module.py"], (
|
||||
"goto-def on uncached file must still trigger a hydrate fetch"
|
||||
assert captured == ["hydrate:{}".format(str(local_file))], (
|
||||
"goto-def on uncached file must still enqueue a hydrate fetch"
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user