app-server: retain thread listener across disconnects (#12373)
- keep the per-thread app-server listener alive when the last client unsubscribes or disconnects - preserve listener-side active turn history so running `thread/resume` can merge an in-progress turn snapshot after reconnect - add `ThreadStateManager` regressions for disconnect/unsubscribe retention and explicit thread teardown cleanup Added unit tests, and I manually tested to confirm the fix --------- Co-authored-by: Codex <noreply@openai.com>
This commit is contained in:
parent
c4f1af7a86
commit
37610240ec
3 changed files with 109 additions and 14 deletions
9
MODULE.bazel.lock
generated
9
MODULE.bazel.lock
generated
|
|
@ -646,6 +646,7 @@
|
|||
"basic-toml_0.1.10": "{\"dependencies\":[{\"features\":[\"serde\"],\"kind\":\"dev\",\"name\":\"semver\",\"req\":\"^1.0.17\"},{\"name\":\"serde\",\"req\":\"^1.0.194\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0.194\"},{\"kind\":\"dev\",\"name\":\"serde_derive\",\"req\":\"^1.0.194\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0.99\"}],\"features\":{}}",
|
||||
"bech32_0.9.1": "{\"dependencies\":[],\"features\":{\"default\":[\"std\"],\"std\":[],\"strict\":[]}}",
|
||||
"beef_0.5.2": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"alloc\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.105\"},{\"kind\":\"dev\",\"name\":\"serde_derive\",\"req\":\"^1.0.105\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"}],\"features\":{\"const_fn\":[],\"default\":[],\"impl_serde\":[\"serde\"]}}",
|
||||
"bincode_1.3.3": "{\"dependencies\":[{\"name\":\"serde\",\"req\":\"^1.0.63\"},{\"kind\":\"dev\",\"name\":\"serde_bytes\",\"req\":\"^0.11\"},{\"kind\":\"dev\",\"name\":\"serde_derive\",\"req\":\"^1.0.27\"}],\"features\":{\"i128\":[]}}",
|
||||
"bit-set_0.5.3": "{\"dependencies\":[{\"default_features\":false,\"name\":\"bit-vec\",\"req\":\"^0.6.1\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.3\"}],\"features\":{\"default\":[\"std\"],\"std\":[\"bit-vec/std\"]}}",
|
||||
"bit-vec_0.6.3": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.7\"},{\"kind\":\"dev\",\"name\":\"rand_xorshift\",\"req\":\"^0.2\"},{\"default_features\":false,\"features\":[\"derive\"],\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"}],\"features\":{\"default\":[\"std\"],\"serde_no_std\":[\"serde/alloc\"],\"serde_std\":[\"std\",\"serde/std\"],\"std\":[]}}",
|
||||
"bitflags_1.3.2": "{\"dependencies\":[{\"name\":\"compiler_builtins\",\"optional\":true,\"req\":\"^0.1.2\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_derive\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"trybuild\",\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"walkdir\",\"req\":\"^2.3\"}],\"features\":{\"default\":[],\"example_generated\":[],\"rustc-dep-of-std\":[\"core\",\"compiler_builtins\"]}}",
|
||||
|
|
@ -954,6 +955,7 @@
|
|||
"libredox_0.1.12": "{\"dependencies\":[{\"name\":\"bitflags\",\"req\":\"^2\"},{\"name\":\"ioslice\",\"optional\":true,\"req\":\"^0.6\"},{\"name\":\"libc\",\"req\":\"^0.2\"},{\"name\":\"redox_syscall\",\"optional\":true,\"req\":\"^0.7\"}],\"features\":{\"call\":[],\"default\":[\"call\",\"std\",\"redox_syscall\"],\"mkns\":[\"ioslice\"],\"std\":[]}}",
|
||||
"libsqlite3-sys_0.30.1": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"runtime\"],\"kind\":\"build\",\"name\":\"bindgen\",\"optional\":true,\"req\":\"^0.69\"},{\"kind\":\"build\",\"name\":\"cc\",\"optional\":true,\"req\":\"^1.1.6\"},{\"name\":\"openssl-sys\",\"optional\":true,\"req\":\"^0.9.103\"},{\"kind\":\"build\",\"name\":\"pkg-config\",\"optional\":true,\"req\":\"^0.3.19\"},{\"kind\":\"build\",\"name\":\"prettyplease\",\"optional\":true,\"req\":\"^0.2.20\"},{\"default_features\":false,\"kind\":\"build\",\"name\":\"quote\",\"optional\":true,\"req\":\"^1.0.36\"},{\"features\":[\"full\",\"extra-traits\",\"visit-mut\"],\"kind\":\"build\",\"name\":\"syn\",\"optional\":true,\"req\":\"^2.0.72\"},{\"kind\":\"build\",\"name\":\"vcpkg\",\"optional\":true,\"req\":\"^0.2.15\"}],\"features\":{\"buildtime_bindgen\":[\"bindgen\",\"pkg-config\",\"vcpkg\"],\"bundled\":[\"cc\",\"bundled_bindings\"],\"bundled-sqlcipher\":[\"bundled\"],\"bundled-sqlcipher-vendored-openssl\":[\"bundled-sqlcipher\",\"openssl-sys/vendored\"],\"bundled-windows\":[\"cc\",\"bundled_bindings\"],\"bundled_bindings\":[],\"default\":[\"min_sqlite_version_3_14_0\"],\"in_gecko\":[],\"loadable_extension\":[\"prettyplease\",\"quote\",\"syn\"],\"min_sqlite_version_3_14_0\":[\"pkg-config\",\"vcpkg\"],\"preupdate_hook\":[\"buildtime_bindgen\"],\"session\":[\"preupdate_hook\",\"buildtime_bindgen\"],\"sqlcipher\":[],\"unlock_notify\":[],\"wasm32-wasi-vfs\":[],\"with-asan\":[]}}",
|
||||
"libz-sys_1.1.23": "{\"dependencies\":[{\"kind\":\"build\",\"name\":\"cc\",\"req\":\"^1.0.98\"},{\"kind\":\"build\",\"name\":\"cmake\",\"optional\":true,\"req\":\"^0.1.50\"},{\"name\":\"libc\",\"optional\":true,\"req\":\"^0.2.43\"},{\"kind\":\"build\",\"name\":\"pkg-config\",\"req\":\"^0.3.9\"},{\"kind\":\"build\",\"name\":\"vcpkg\",\"req\":\"^0.2.11\"}],\"features\":{\"asm\":[],\"default\":[\"libc\",\"stock-zlib\"],\"static\":[],\"stock-zlib\":[],\"zlib-ng\":[\"libc\",\"cmake\"],\"zlib-ng-no-cmake-experimental-community-maintained\":[\"libc\"]}}",
|
||||
"linked-hash-map_0.5.6": "{\"dependencies\":[{\"name\":\"heapsize\",\"optional\":true,\"req\":\"^0.4\"},{\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_test\",\"req\":\"^1.0\"}],\"features\":{\"heapsize_impl\":[\"heapsize\"],\"nightly\":[],\"serde_impl\":[\"serde\"]}}",
|
||||
"linux-keyutils_0.2.4": "{\"dependencies\":[{\"default_features\":false,\"name\":\"bitflags\",\"req\":\"^2.4\"},{\"default_features\":false,\"features\":[\"std\",\"derive\"],\"kind\":\"dev\",\"name\":\"clap\",\"req\":\"^4.4.11\"},{\"default_features\":false,\"name\":\"libc\",\"req\":\"^0.2.132\"},{\"kind\":\"dev\",\"name\":\"zeroize\",\"req\":\"^1.5.7\"}],\"features\":{\"default\":[],\"std\":[\"bitflags/std\"]}}",
|
||||
"linux-raw-sys_0.11.0": "{\"dependencies\":[{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"libc\",\"req\":\"^0.2.100\"},{\"kind\":\"dev\",\"name\":\"static_assertions\",\"req\":\"^1.1.0\"}],\"features\":{\"auxvec\":[],\"bootparam\":[],\"btrfs\":[],\"default\":[\"std\",\"general\",\"errno\"],\"elf\":[],\"elf_uapi\":[],\"errno\":[],\"general\":[],\"if_arp\":[],\"if_ether\":[],\"if_packet\":[],\"image\":[],\"io_uring\":[],\"ioctl\":[],\"landlock\":[],\"loop_device\":[],\"mempolicy\":[],\"net\":[],\"netlink\":[],\"no_std\":[],\"prctl\":[],\"ptrace\":[],\"rustc-dep-of-std\":[\"core\",\"no_std\"],\"std\":[],\"system\":[],\"xdp\":[]}}",
|
||||
"linux-raw-sys_0.4.15": "{\"dependencies\":[{\"name\":\"compiler_builtins\",\"optional\":true,\"req\":\"^0.1.49\"},{\"name\":\"core\",\"optional\":true,\"package\":\"rustc-std-workspace-core\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"libc\",\"req\":\"^0.2.100\"},{\"kind\":\"dev\",\"name\":\"static_assertions\",\"req\":\"^1.1.0\"}],\"features\":{\"bootparam\":[],\"btrfs\":[],\"default\":[\"std\",\"general\",\"errno\"],\"elf\":[],\"elf_uapi\":[],\"errno\":[],\"general\":[],\"if_arp\":[],\"if_ether\":[],\"if_packet\":[],\"io_uring\":[],\"ioctl\":[],\"landlock\":[],\"loop_device\":[],\"mempolicy\":[],\"net\":[],\"netlink\":[],\"no_std\":[],\"prctl\":[],\"ptrace\":[],\"rustc-dep-of-std\":[\"core\",\"compiler_builtins\",\"no_std\"],\"std\":[],\"system\":[],\"xdp\":[]}}",
|
||||
|
|
@ -1031,6 +1033,8 @@
|
|||
"oid-registry_0.8.1": "{\"dependencies\":[{\"name\":\"asn1-rs\",\"req\":\"^0.7\"}],\"features\":{\"crypto\":[\"kdf\",\"pkcs1\",\"pkcs7\",\"pkcs9\",\"pkcs12\",\"nist_algs\",\"x962\"],\"default\":[\"registry\"],\"kdf\":[],\"ms_spc\":[],\"nist_algs\":[],\"pkcs1\":[],\"pkcs12\":[],\"pkcs7\":[],\"pkcs9\":[],\"registry\":[],\"x500\":[],\"x509\":[],\"x962\":[]}}",
|
||||
"once_cell_1.21.3": "{\"dependencies\":[{\"name\":\"critical-section\",\"optional\":true,\"req\":\"^1.1.3\"},{\"features\":[\"std\"],\"kind\":\"dev\",\"name\":\"critical-section\",\"req\":\"^1.1.3\"},{\"default_features\":false,\"name\":\"parking_lot_core\",\"optional\":true,\"req\":\"^0.9.10\"},{\"default_features\":false,\"name\":\"portable-atomic\",\"optional\":true,\"req\":\"^1.8\"},{\"kind\":\"dev\",\"name\":\"regex\",\"req\":\"^1.10.6\"}],\"features\":{\"alloc\":[\"race\"],\"atomic-polyfill\":[\"critical-section\"],\"critical-section\":[\"dep:critical-section\",\"portable-atomic\"],\"default\":[\"std\"],\"parking_lot\":[\"dep:parking_lot_core\"],\"portable-atomic\":[\"dep:portable-atomic\"],\"race\":[],\"std\":[\"alloc\"],\"unstable\":[]}}",
|
||||
"once_cell_polyfill_1.70.2": "{\"dependencies\":[],\"features\":{\"default\":[]}}",
|
||||
"onig_6.5.1": "{\"dependencies\":[{\"name\":\"bitflags\",\"req\":\"^2.4.0\"},{\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(windows)\"},{\"name\":\"once_cell\",\"req\":\"^1.12\"},{\"default_features\":false,\"name\":\"onig_sys\",\"req\":\"^69.9.1\"}],\"features\":{\"default\":[\"generate\"],\"generate\":[\"onig_sys/generate\"],\"posix-api\":[\"onig_sys/posix-api\"],\"print-debug\":[\"onig_sys/print-debug\"],\"std-pattern\":[]}}",
|
||||
"onig_sys_69.9.1": "{\"dependencies\":[{\"features\":[\"runtime\"],\"kind\":\"build\",\"name\":\"bindgen\",\"optional\":true,\"req\":\"^0.71\"},{\"kind\":\"build\",\"name\":\"cc\",\"req\":\"^1.0\"},{\"kind\":\"build\",\"name\":\"pkg-config\",\"req\":\"^0.3.16\"}],\"features\":{\"default\":[\"generate\"],\"generate\":[\"bindgen\"],\"posix-api\":[],\"print-debug\":[]}}",
|
||||
"opaque-debug_0.3.1": "{\"dependencies\":[],\"features\":{}}",
|
||||
"openssl-macros_0.1.1": "{\"dependencies\":[{\"name\":\"proc-macro2\",\"req\":\"^1\"},{\"name\":\"quote\",\"req\":\"^1\"},{\"features\":[\"full\"],\"name\":\"syn\",\"req\":\"^2\"}],\"features\":{}}",
|
||||
"openssl-probe_0.1.6": "{\"dependencies\":[],\"features\":{}}",
|
||||
|
|
@ -1073,6 +1077,7 @@
|
|||
"pkcs1_0.7.5": "{\"dependencies\":[{\"features\":[\"db\"],\"kind\":\"dev\",\"name\":\"const-oid\",\"req\":\"^0.9\"},{\"features\":[\"oid\"],\"name\":\"der\",\"req\":\"^0.7\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.4\"},{\"default_features\":false,\"name\":\"pkcs8\",\"optional\":true,\"req\":\"^0.10\"},{\"name\":\"spki\",\"req\":\"^0.7\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3\"}],\"features\":{\"alloc\":[\"der/alloc\",\"zeroize\",\"pkcs8?/alloc\"],\"pem\":[\"alloc\",\"der/pem\",\"pkcs8?/pem\"],\"std\":[\"der/std\",\"alloc\"],\"zeroize\":[\"der/zeroize\"]}}",
|
||||
"pkcs8_0.10.2": "{\"dependencies\":[{\"features\":[\"oid\"],\"name\":\"der\",\"req\":\"^0.7\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.3\"},{\"name\":\"pkcs5\",\"optional\":true,\"req\":\"^0.7\"},{\"default_features\":false,\"name\":\"rand_core\",\"optional\":true,\"req\":\"^0.6\"},{\"name\":\"spki\",\"req\":\"^0.7.1\"},{\"default_features\":false,\"name\":\"subtle\",\"optional\":true,\"req\":\"^2\"},{\"kind\":\"dev\",\"name\":\"tempfile\",\"req\":\"^3\"}],\"features\":{\"3des\":[\"encryption\",\"pkcs5/3des\"],\"alloc\":[\"der/alloc\",\"der/zeroize\",\"spki/alloc\"],\"des-insecure\":[\"encryption\",\"pkcs5/des-insecure\"],\"encryption\":[\"alloc\",\"pkcs5/alloc\",\"pkcs5/pbes2\",\"rand_core\"],\"getrandom\":[\"rand_core/getrandom\"],\"pem\":[\"alloc\",\"der/pem\",\"spki/pem\"],\"sha1-insecure\":[\"encryption\",\"pkcs5/sha1-insecure\"],\"std\":[\"alloc\",\"der/std\",\"spki/std\"]}}",
|
||||
"pkg-config_0.3.32": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"lazy_static\",\"req\":\"^1\"}],\"features\":{}}",
|
||||
"plist_1.8.0": "{\"dependencies\":[{\"name\":\"base64\",\"req\":\"^0.22.0\"},{\"name\":\"indexmap\",\"req\":\"^2.1.0\"},{\"name\":\"quick_xml\",\"package\":\"quick-xml\",\"req\":\"^0.38.0\"},{\"name\":\"serde\",\"optional\":true,\"req\":\"^1.0.2\"},{\"kind\":\"dev\",\"name\":\"serde_derive\",\"req\":\"^1.0.2\"},{\"kind\":\"dev\",\"name\":\"serde_yaml\",\"req\":\"^0.8.21\"},{\"features\":[\"parsing\",\"formatting\"],\"name\":\"time\",\"req\":\"^0.3.30\"}],\"features\":{\"default\":[\"serde\"],\"enable_unstable_features_that_may_break_with_minor_version_bumps\":[]}}",
|
||||
"png_0.18.0": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"approx\",\"req\":\"^0.5.1\"},{\"name\":\"bitflags\",\"req\":\"^2.0\"},{\"kind\":\"dev\",\"name\":\"byteorder\",\"req\":\"^1.5.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"clap\",\"req\":\"^4.0\"},{\"name\":\"crc32fast\",\"req\":\"^1.2.0\"},{\"default_features\":false,\"features\":[\"cargo_bench_support\"],\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.7.0\"},{\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.7.0\",\"target\":\"cfg(not(target_arch = \\\"wasm32\\\"))\"},{\"name\":\"fdeflate\",\"req\":\"^0.3.3\"},{\"name\":\"flate2\",\"req\":\"^1.0.35\"},{\"kind\":\"dev\",\"name\":\"glob\",\"req\":\"^0.3\"},{\"features\":[\"simd\"],\"name\":\"miniz_oxide\",\"req\":\"^0.8\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.9.2\"}],\"features\":{\"benchmarks\":[],\"unstable\":[\"crc32fast/nightly\"],\"zlib-rs\":[\"flate2/zlib-rs\"]}}",
|
||||
"polling_3.11.0": "{\"dependencies\":[{\"name\":\"cfg-if\",\"req\":\"^1\"},{\"name\":\"concurrent-queue\",\"req\":\"^2.2.0\",\"target\":\"cfg(windows)\"},{\"kind\":\"dev\",\"name\":\"easy-parallel\",\"req\":\"^3.1.0\"},{\"kind\":\"dev\",\"name\":\"fastrand\",\"req\":\"^2.0.0\"},{\"name\":\"hermit-abi\",\"req\":\"^0.5.0\",\"target\":\"cfg(target_os = \\\"hermit\\\")\"},{\"kind\":\"dev\",\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(unix)\"},{\"name\":\"pin-project-lite\",\"req\":\"^0.2.9\",\"target\":\"cfg(windows)\"},{\"default_features\":false,\"features\":[\"event\",\"fs\",\"pipe\",\"process\",\"std\",\"time\"],\"name\":\"rustix\",\"req\":\"^1.0.5\",\"target\":\"cfg(any(unix, target_os = \\\"fuchsia\\\", target_os = \\\"vxworks\\\"))\"},{\"kind\":\"dev\",\"name\":\"signal-hook\",\"req\":\"^0.3.17\",\"target\":\"cfg(all(unix, not(target_os=\\\"vita\\\")))\"},{\"kind\":\"dev\",\"name\":\"socket2\",\"req\":\"^0.6.0\"},{\"default_features\":false,\"name\":\"tracing\",\"optional\":true,\"req\":\"^0.1.37\"},{\"features\":[\"Wdk_Foundation\",\"Wdk_Storage_FileSystem\",\"Win32_Foundation\",\"Win32_Networking_WinSock\",\"Win32_Security\",\"Win32_Storage_FileSystem\",\"Win32_System_IO\",\"Win32_System_LibraryLoader\",\"Win32_System_Threading\",\"Win32_System_WindowsProgramming\"],\"name\":\"windows-sys\",\"req\":\"^0.61\",\"target\":\"cfg(windows)\"}],\"features\":{}}",
|
||||
"poly1305_0.8.0": "{\"dependencies\":[{\"name\":\"cpufeatures\",\"req\":\"^0.2\",\"target\":\"cfg(any(target_arch = \\\"x86_64\\\", target_arch = \\\"x86\\\"))\"},{\"kind\":\"dev\",\"name\":\"hex-literal\",\"req\":\"^0.3\"},{\"name\":\"opaque-debug\",\"req\":\"^0.3\"},{\"default_features\":false,\"name\":\"universal-hash\",\"req\":\"^0.5\"},{\"default_features\":false,\"name\":\"zeroize\",\"optional\":true,\"req\":\"^1\"}],\"features\":{\"std\":[\"universal-hash/std\"]}}",
|
||||
|
|
@ -1275,6 +1280,7 @@
|
|||
"syn_2.0.114": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"anyhow\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"automod\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"flate2\",\"req\":\"^1\",\"target\":\"cfg(not(miri))\"},{\"kind\":\"dev\",\"name\":\"insta\",\"req\":\"^1\"},{\"default_features\":false,\"name\":\"proc-macro2\",\"req\":\"^1.0.91\"},{\"default_features\":false,\"name\":\"quote\",\"optional\":true,\"req\":\"^1.0.35\"},{\"kind\":\"dev\",\"name\":\"rayon\",\"req\":\"^1\",\"target\":\"cfg(not(miri))\"},{\"kind\":\"dev\",\"name\":\"ref-cast\",\"req\":\"^1\"},{\"features\":[\"blocking\"],\"kind\":\"dev\",\"name\":\"reqwest\",\"req\":\"^0.13\",\"target\":\"cfg(not(miri))\"},{\"kind\":\"dev\",\"name\":\"rustversion\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"syn-test-suite\",\"req\":\"^0\"},{\"kind\":\"dev\",\"name\":\"tar\",\"req\":\"^0.4.16\",\"target\":\"cfg(not(miri))\"},{\"kind\":\"dev\",\"name\":\"termcolor\",\"req\":\"^1\"},{\"name\":\"unicode-ident\",\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"walkdir\",\"req\":\"^2.3.2\",\"target\":\"cfg(not(miri))\"}],\"features\":{\"clone-impls\":[],\"default\":[\"derive\",\"parsing\",\"printing\",\"clone-impls\",\"proc-macro\"],\"derive\":[],\"extra-traits\":[],\"fold\":[],\"full\":[],\"parsing\":[],\"printing\":[\"dep:quote\"],\"proc-macro\":[\"proc-macro2/proc-macro\",\"quote?/proc-macro\"],\"test\":[\"syn-test-suite/all-features\"],\"visit\":[],\"visit-mut\":[]}}",
|
||||
"sync_wrapper_1.0.2": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"futures\",\"req\":\"^0.3\"},{\"default_features\":false,\"name\":\"futures-core\",\"optional\":true,\"req\":\"^0.3\"},{\"kind\":\"dev\",\"name\":\"pin-project-lite\",\"req\":\"^0.2.7\"}],\"features\":{\"futures\":[\"futures-core\"]}}",
|
||||
"synstructure_0.13.2": "{\"dependencies\":[{\"default_features\":false,\"name\":\"proc-macro2\",\"req\":\"^1.0.60\"},{\"default_features\":false,\"name\":\"quote\",\"req\":\"^1\"},{\"default_features\":false,\"features\":[\"derive\",\"parsing\",\"printing\",\"clone-impls\",\"visit\",\"extra-traits\"],\"name\":\"syn\",\"req\":\"^2\"},{\"kind\":\"dev\",\"name\":\"synstructure_test_traits\",\"req\":\"^0.1\"}],\"features\":{\"default\":[\"proc-macro\"],\"proc-macro\":[\"proc-macro2/proc-macro\",\"syn/proc-macro\",\"quote/proc-macro\"]}}",
|
||||
"syntect_5.3.0": "{\"dependencies\":[{\"name\":\"bincode\",\"optional\":true,\"req\":\"^1.0\"},{\"features\":[\"html_reports\"],\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.3\"},{\"name\":\"fancy-regex\",\"optional\":true,\"req\":\"^0.16.2\"},{\"name\":\"flate2\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"fnv\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"getopts\",\"req\":\"^0.2\"},{\"name\":\"once_cell\",\"req\":\"^1.8\"},{\"default_features\":false,\"name\":\"onig\",\"optional\":true,\"req\":\"^6.5.1\"},{\"name\":\"plist\",\"optional\":true,\"req\":\"^1.3\"},{\"kind\":\"dev\",\"name\":\"pretty_assertions\",\"req\":\"^0.6\"},{\"kind\":\"dev\",\"name\":\"public-api\",\"req\":\"^0.50.1\"},{\"kind\":\"dev\",\"name\":\"rayon\",\"req\":\"^1.0.0\"},{\"kind\":\"dev\",\"name\":\"regex\",\"req\":\"^1.0\"},{\"name\":\"regex-syntax\",\"optional\":true,\"req\":\"^0.8\"},{\"kind\":\"dev\",\"name\":\"rustdoc-json\",\"req\":\"^0.9.7\"},{\"kind\":\"dev\",\"name\":\"rustup-toolchain\",\"req\":\"^0.1.5\"},{\"name\":\"serde\",\"req\":\"^1.0\"},{\"name\":\"serde_derive\",\"req\":\"^1.0\"},{\"name\":\"serde_json\",\"optional\":true,\"req\":\"^1.0\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1.0\"},{\"name\":\"thiserror\",\"req\":\"^2.0.12\"},{\"name\":\"walkdir\",\"req\":\"^2.0\"},{\"name\":\"yaml-rust\",\"optional\":true,\"req\":\"^0.4.5\"}],\"features\":{\"default\":[\"default-onig\"],\"default-fancy\":[\"parsing\",\"default-syntaxes\",\"default-themes\",\"html\",\"plist-load\",\"yaml-load\",\"dump-load\",\"dump-create\",\"regex-fancy\"],\"default-onig\":[\"parsing\",\"default-syntaxes\",\"default-themes\",\"html\",\"plist-load\",\"yaml-load\",\"dump-load\",\"dump-create\",\"regex-onig\"],\"default-syntaxes\":[\"parsing\",\"dump-load\"],\"default-themes\":[\"dump-load\"],\"dump-create\":[\"flate2\",\"bincode\"],\"dump-load\":[\"flate2\",\"bincode\"],\"html\":[\"parsing\"],\"metadata\":[\"parsing\",\"plist-load\",\"dep:serde_json\"],\"parsing\":[\"regex-syntax\",\"fnv\",\"dump-create\",\"dump-load\"],\"plist-load\":[\"plist\",\"dep:serde_json\"],\"regex-fancy\":[\"fancy-regex\"],\"regex-onig\":[\"onig\"],\"yaml-load\":[\"yaml-rust\",\"parsing\"]}}",
|
||||
"sys-locale_0.3.2": "{\"dependencies\":[{\"name\":\"js-sys\",\"optional\":true,\"req\":\"^0.3\",\"target\":\"cfg(all(target_family = \\\"wasm\\\", not(unix)))\"},{\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(target_os = \\\"android\\\")\"},{\"name\":\"wasm-bindgen\",\"optional\":true,\"req\":\"^0.2\",\"target\":\"cfg(all(target_family = \\\"wasm\\\", not(unix)))\"},{\"kind\":\"dev\",\"name\":\"wasm-bindgen-test\",\"req\":\"^0.3\",\"target\":\"cfg(all(target_family = \\\"wasm\\\", not(unix)))\"},{\"features\":[\"Window\",\"WorkerGlobalScope\",\"Navigator\",\"WorkerNavigator\"],\"name\":\"web-sys\",\"optional\":true,\"req\":\"^0.3\",\"target\":\"cfg(all(target_family = \\\"wasm\\\", not(unix)))\"}],\"features\":{\"js\":[\"js-sys\",\"wasm-bindgen\",\"web-sys\"]}}",
|
||||
"system-configuration-sys_0.6.0": "{\"dependencies\":[{\"name\":\"core-foundation-sys\",\"req\":\"^0.8\"},{\"name\":\"libc\",\"req\":\"^0.2.149\"}],\"features\":{}}",
|
||||
"system-configuration_0.6.1": "{\"dependencies\":[{\"name\":\"bitflags\",\"req\":\"^2\"},{\"name\":\"core-foundation\",\"req\":\"^0.9\"},{\"name\":\"system-configuration-sys\",\"req\":\"^0.6\"}],\"features\":{}}",
|
||||
|
|
@ -1338,13 +1344,13 @@
|
|||
"tracing-test_0.2.5": "{\"dependencies\":[{\"features\":[\"rt-multi-thread\",\"macros\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1\"},{\"default_features\":false,\"features\":[\"std\"],\"kind\":\"dev\",\"name\":\"tracing\",\"req\":\"^0.1\"},{\"name\":\"tracing-core\",\"req\":\"^0.1\"},{\"features\":[\"env-filter\"],\"name\":\"tracing-subscriber\",\"req\":\"^0.3\"},{\"name\":\"tracing-test-macro\",\"req\":\"^0.2.5\"}],\"features\":{\"no-env-filter\":[\"tracing-test-macro/no-env-filter\"]}}",
|
||||
"tracing_0.1.44": "{\"dependencies\":[{\"default_features\":false,\"kind\":\"dev\",\"name\":\"criterion\",\"req\":\"^0.3.6\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"futures\",\"req\":\"^0.3.21\"},{\"name\":\"log\",\"optional\":true,\"req\":\"^0.4.17\"},{\"kind\":\"dev\",\"name\":\"log\",\"req\":\"^0.4.17\"},{\"name\":\"pin-project-lite\",\"req\":\"^0.2.9\"},{\"name\":\"tracing-attributes\",\"optional\":true,\"req\":\"^0.1.31\"},{\"default_features\":false,\"name\":\"tracing-core\",\"req\":\"^0.1.36\"},{\"kind\":\"dev\",\"name\":\"wasm-bindgen-test\",\"req\":\"^0.3.38\",\"target\":\"cfg(target_arch = \\\"wasm32\\\")\"}],\"features\":{\"async-await\":[],\"attributes\":[\"tracing-attributes\"],\"default\":[\"std\",\"attributes\"],\"log-always\":[\"log\"],\"max_level_debug\":[],\"max_level_error\":[],\"max_level_info\":[],\"max_level_off\":[],\"max_level_trace\":[],\"max_level_warn\":[],\"release_max_level_debug\":[],\"release_max_level_error\":[],\"release_max_level_info\":[],\"release_max_level_off\":[],\"release_max_level_trace\":[],\"release_max_level_warn\":[],\"std\":[\"tracing-core/std\"],\"valuable\":[\"tracing-core/valuable\"]}}",
|
||||
"tree-sitter-bash_0.25.1": "{\"dependencies\":[{\"kind\":\"build\",\"name\":\"cc\",\"req\":\"^1.1\"},{\"kind\":\"dev\",\"name\":\"tree-sitter\",\"req\":\"^0.25\"},{\"name\":\"tree-sitter-language\",\"req\":\"^0.1\"}],\"features\":{}}",
|
||||
"tree-sitter-highlight_0.25.10": "{\"dependencies\":[{\"name\":\"regex\",\"req\":\"^1.11.1\"},{\"name\":\"streaming-iterator\",\"req\":\"^0.1.9\"},{\"name\":\"thiserror\",\"req\":\"^2.0.11\"},{\"name\":\"tree-sitter\",\"req\":\"^0.25.10\"}],\"features\":{}}",
|
||||
"tree-sitter-language_0.1.7": "{\"dependencies\":[],\"features\":{}}",
|
||||
"tree-sitter_0.25.10": "{\"dependencies\":[{\"kind\":\"build\",\"name\":\"bindgen\",\"optional\":true,\"req\":\"^0.71.1\"},{\"kind\":\"build\",\"name\":\"cc\",\"req\":\"^1.2.10\"},{\"default_features\":false,\"features\":[\"unicode\"],\"name\":\"regex\",\"req\":\"^1.11.1\"},{\"default_features\":false,\"name\":\"regex-syntax\",\"req\":\"^0.8.5\"},{\"features\":[\"preserve_order\"],\"kind\":\"build\",\"name\":\"serde_json\",\"req\":\"^1.0.137\"},{\"name\":\"streaming-iterator\",\"req\":\"^0.1.9\"},{\"name\":\"tree-sitter-language\",\"req\":\"^0.1\"},{\"default_features\":false,\"features\":[\"cranelift\",\"gc-drc\"],\"name\":\"wasmtime-c-api\",\"optional\":true,\"package\":\"wasmtime-c-api-impl\",\"req\":\"^29.0.1\"}],\"features\":{\"default\":[\"std\"],\"std\":[\"regex/std\",\"regex/perf\",\"regex-syntax/unicode\"],\"wasm\":[\"std\",\"wasmtime-c-api\"]}}",
|
||||
"tree_magic_mini_3.2.2": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"bencher\",\"req\":\"^0.1.0\"},{\"name\":\"memchr\",\"req\":\"^2.0\"},{\"name\":\"nom\",\"req\":\"^8.0\"},{\"default_features\":false,\"name\":\"petgraph\",\"req\":\"^0.8.0\"},{\"name\":\"tree_magic_db\",\"optional\":true,\"req\":\"^3.0\"}],\"features\":{\"with-gpl-data\":[\"dep:tree_magic_db\"]}}",
|
||||
"try-lock_0.2.5": "{\"dependencies\":[],\"features\":{}}",
|
||||
"ts-rs-macros_11.1.0": "{\"dependencies\":[{\"name\":\"proc-macro2\",\"req\":\"^1\"},{\"name\":\"quote\",\"req\":\"^1\"},{\"features\":[\"full\",\"extra-traits\"],\"name\":\"syn\",\"req\":\"^2.0.28\"},{\"name\":\"termcolor\",\"optional\":true,\"req\":\"^1\"}],\"features\":{\"no-serde-warnings\":[],\"serde-compat\":[\"termcolor\"]}}",
|
||||
"ts-rs_11.1.0": "{\"dependencies\":[{\"features\":[\"serde\"],\"name\":\"bigdecimal\",\"optional\":true,\"req\":\">=0.0.13, <0.5\"},{\"name\":\"bson\",\"optional\":true,\"req\":\"^2\"},{\"name\":\"bytes\",\"optional\":true,\"req\":\"^1\"},{\"name\":\"chrono\",\"optional\":true,\"req\":\"^0.4\"},{\"features\":[\"serde\"],\"kind\":\"dev\",\"name\":\"chrono\",\"req\":\"^0.4\"},{\"name\":\"dprint-plugin-typescript\",\"optional\":true,\"req\":\"=0.95\"},{\"name\":\"heapless\",\"optional\":true,\"req\":\">=0.7, <0.9\"},{\"name\":\"indexmap\",\"optional\":true,\"req\":\"^2\"},{\"name\":\"ordered-float\",\"optional\":true,\"req\":\">=3, <6\"},{\"name\":\"semver\",\"optional\":true,\"req\":\"^1\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"serde\",\"req\":\"^1.0\"},{\"name\":\"serde_json\",\"optional\":true,\"req\":\"^1\"},{\"kind\":\"dev\",\"name\":\"serde_json\",\"req\":\"^1\"},{\"name\":\"smol_str\",\"optional\":true,\"req\":\"^0.3\"},{\"name\":\"thiserror\",\"req\":\"^2\"},{\"features\":[\"sync\"],\"name\":\"tokio\",\"optional\":true,\"req\":\"^1\"},{\"features\":[\"sync\",\"rt\"],\"kind\":\"dev\",\"name\":\"tokio\",\"req\":\"^1.40\"},{\"name\":\"ts-rs-macros\",\"req\":\"=11.1.0\"},{\"name\":\"url\",\"optional\":true,\"req\":\"^2\"},{\"name\":\"uuid\",\"optional\":true,\"req\":\"^1\"}],\"features\":{\"bigdecimal-impl\":[\"bigdecimal\"],\"bson-uuid-impl\":[\"bson\"],\"bytes-impl\":[\"bytes\"],\"chrono-impl\":[\"chrono\"],\"default\":[\"serde-compat\"],\"format\":[\"dprint-plugin-typescript\"],\"heapless-impl\":[\"heapless\"],\"import-esm\":[],\"indexmap-impl\":[\"indexmap\"],\"no-serde-warnings\":[\"ts-rs-macros/no-serde-warnings\"],\"ordered-float-impl\":[\"ordered-float\"],\"semver-impl\":[\"semver\"],\"serde-compat\":[\"ts-rs-macros/serde-compat\"],\"serde-json-impl\":[\"serde_json\"],\"smol_str-impl\":[\"smol_str\"],\"tokio-impl\":[\"tokio\"],\"url-impl\":[\"url\"],\"uuid-impl\":[\"uuid\"]}}",
|
||||
"two-face_0.5.1": "{\"dependencies\":[{\"kind\":\"dev\",\"name\":\"cargo-lock\",\"req\":\"^10.1.0\"},{\"kind\":\"dev\",\"name\":\"insta\",\"req\":\"^1.44.3\"},{\"default_features\":false,\"features\":[\"read\"],\"kind\":\"dev\",\"name\":\"object\",\"req\":\"^0.36.7\"},{\"name\":\"serde\",\"req\":\"^1.0.228\"},{\"name\":\"serde_derive\",\"req\":\"^1.0.228\"},{\"kind\":\"dev\",\"name\":\"similar\",\"req\":\"^2.7.0\"},{\"features\":[\"derive\"],\"kind\":\"dev\",\"name\":\"strum\",\"req\":\"^0.26.3\"},{\"default_features\":false,\"features\":[\"dump-load\",\"parsing\"],\"name\":\"syntect\",\"req\":\"^5.3.0\"},{\"default_features\":false,\"features\":[\"html\"],\"kind\":\"dev\",\"name\":\"syntect\",\"req\":\"^5.3.0\"},{\"kind\":\"dev\",\"name\":\"toml\",\"req\":\"^0.8.23\"},{\"default_features\":false,\"features\":[\"std\",\"xxhash64\"],\"kind\":\"dev\",\"name\":\"twox-hash\",\"req\":\"^2.1.2\"}],\"features\":{\"default\":[\"syntect-onig\"],\"syntect-default-fancy\":[\"syntect-fancy\",\"syntect/default-fancy\"],\"syntect-default-onig\":[\"syntect-onig\",\"syntect/default-onig\"],\"syntect-fancy\":[\"syntect/regex-fancy\"],\"syntect-onig\":[\"syntect/regex-onig\"]}}",
|
||||
"type-map_0.5.1": "{\"dependencies\":[{\"name\":\"rustc-hash\",\"req\":\"^2\"}],\"features\":{}}",
|
||||
"typenum_1.19.0": "{\"dependencies\":[{\"default_features\":false,\"name\":\"scale-info\",\"optional\":true,\"req\":\"^1.0\"}],\"features\":{\"const-generics\":[],\"force_unix_path_separator\":[],\"i128\":[],\"no_std\":[],\"scale_info\":[\"scale-info/derive\"],\"strict\":[]}}",
|
||||
"uds_windows_1.1.0": "{\"dependencies\":[{\"name\":\"memoffset\",\"req\":\"^0.9.0\"},{\"name\":\"tempfile\",\"req\":\"^3\",\"target\":\"cfg(windows)\"},{\"features\":[\"winsock2\",\"ws2def\",\"minwinbase\",\"ntdef\",\"processthreadsapi\",\"handleapi\",\"ws2tcpip\",\"winbase\"],\"name\":\"winapi\",\"req\":\"^0.3.9\",\"target\":\"cfg(windows)\"}],\"features\":{}}",
|
||||
|
|
@ -1488,6 +1494,7 @@
|
|||
"x509-parser_0.18.1": "{\"dependencies\":[{\"features\":[\"datetime\"],\"name\":\"asn1-rs\",\"req\":\"^0.7.0\"},{\"name\":\"aws-lc-rs\",\"optional\":true,\"req\":\"^1.0\"},{\"name\":\"data-encoding\",\"req\":\"^2.2.1\"},{\"features\":[\"bigint\"],\"name\":\"der-parser\",\"req\":\"^10.0\"},{\"name\":\"lazy_static\",\"req\":\"^1.4\"},{\"name\":\"nom\",\"req\":\"^7.0\"},{\"features\":[\"crypto\",\"x509\",\"x962\"],\"name\":\"oid-registry\",\"req\":\"^0.8.1\"},{\"name\":\"ring\",\"optional\":true,\"req\":\"^0.17.12\"},{\"name\":\"rusticata-macros\",\"req\":\"^4.0\"},{\"name\":\"thiserror\",\"req\":\"^2.0\"},{\"features\":[\"formatting\"],\"name\":\"time\",\"req\":\"^0.3.35\"}],\"features\":{\"default\":[],\"validate\":[],\"verify\":[\"ring\"],\"verify-aws\":[\"aws-lc-rs\"]}}",
|
||||
"xdg-home_1.3.0": "{\"dependencies\":[{\"name\":\"libc\",\"req\":\"^0.2\",\"target\":\"cfg(unix)\"},{\"features\":[\"Win32_Foundation\",\"Win32_UI_Shell\",\"Win32_System_Com\"],\"name\":\"windows-sys\",\"req\":\"^0.59\",\"target\":\"cfg(windows)\"}],\"features\":{}}",
|
||||
"xz2_0.1.7": "{\"dependencies\":[{\"name\":\"futures\",\"optional\":true,\"req\":\"^0.1.26\"},{\"name\":\"lzma-sys\",\"req\":\"^0.1.18\"},{\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^1.0.1\"},{\"kind\":\"dev\",\"name\":\"rand\",\"req\":\"^0.8.0\"},{\"kind\":\"dev\",\"name\":\"tokio-core\",\"req\":\"^0.1.17\"},{\"name\":\"tokio-io\",\"optional\":true,\"req\":\"^0.1.12\"}],\"features\":{\"static\":[\"lzma-sys/static\"],\"tokio\":[\"tokio-io\",\"futures\"]}}",
|
||||
"yaml-rust_0.4.5": "{\"dependencies\":[{\"name\":\"linked-hash-map\",\"req\":\"^0.5.3\"},{\"kind\":\"dev\",\"name\":\"quickcheck\",\"req\":\"^0.9\"}],\"features\":{}}",
|
||||
"yansi_1.0.1": "{\"dependencies\":[{\"name\":\"is-terminal\",\"optional\":true,\"req\":\"^0.4.11\"}],\"features\":{\"_nightly\":[],\"alloc\":[],\"default\":[\"std\"],\"detect-env\":[\"std\"],\"detect-tty\":[\"is-terminal\",\"std\"],\"hyperlink\":[\"std\"],\"std\":[\"alloc\"]}}",
|
||||
"yasna_0.5.2": "{\"dependencies\":[{\"default_features\":false,\"features\":[\"std\"],\"name\":\"bit-vec\",\"optional\":true,\"req\":\"^0.6.1\"},{\"name\":\"num-bigint\",\"optional\":true,\"req\":\"^0.4\"},{\"default_features\":false,\"kind\":\"dev\",\"name\":\"num-traits\",\"req\":\"^0.2\"},{\"default_features\":false,\"features\":[\"std\"],\"name\":\"time\",\"optional\":true,\"req\":\"^0.3.1\"}],\"features\":{\"default\":[],\"std\":[]}}",
|
||||
"yoke-derive_0.8.1": "{\"dependencies\":[{\"name\":\"proc-macro2\",\"req\":\"^1.0.61\"},{\"name\":\"quote\",\"req\":\"^1.0.28\"},{\"features\":[\"fold\"],\"name\":\"syn\",\"req\":\"^2.0.21\"},{\"name\":\"synstructure\",\"req\":\"^0.13.0\"}],\"features\":{}}",
|
||||
|
|
|
|||
|
|
@ -5876,7 +5876,7 @@ impl CodexMessageProcessor {
|
|||
loop {
|
||||
tokio::select! {
|
||||
_ = &mut cancel_rx => {
|
||||
// User has unsubscribed, so exit this task.
|
||||
// Listener was superseded or the thread is being torn down.
|
||||
break;
|
||||
}
|
||||
event = conversation.next_event() => {
|
||||
|
|
@ -6296,6 +6296,14 @@ async fn handle_pending_thread_resume_request(
|
|||
let state = thread_state.lock().await;
|
||||
state.active_turn_snapshot()
|
||||
};
|
||||
tracing::debug!(
|
||||
thread_id = %conversation_id,
|
||||
request_id = ?pending.request_id,
|
||||
active_turn_present = active_turn.is_some(),
|
||||
active_turn_id = ?active_turn.as_ref().map(|turn| turn.id.as_str()),
|
||||
active_turn_status = ?active_turn.as_ref().map(|turn| &turn.status),
|
||||
"composing running thread resume response"
|
||||
);
|
||||
let mut has_in_progress_turn = active_turn
|
||||
.as_ref()
|
||||
.is_some_and(|turn| matches!(turn.status, TurnStatus::InProgress));
|
||||
|
|
@ -7344,8 +7352,8 @@ mod tests {
|
|||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn removing_one_listener_does_not_cancel_other_subscriptions_for_same_thread()
|
||||
-> Result<()> {
|
||||
async fn removing_listeners_retains_thread_listener_when_last_subscriber_leaves() -> Result<()>
|
||||
{
|
||||
let mut manager = ThreadStateManager::new();
|
||||
let thread_id = ThreadId::from_string("ad7f0408-99b8-4f6e-a46f-bd0eec433370")?;
|
||||
let listener_a = Uuid::new_v4();
|
||||
|
|
@ -7372,7 +7380,13 @@ mod tests {
|
|||
.is_err()
|
||||
);
|
||||
assert_eq!(manager.remove_listener(listener_b).await, Some(thread_id));
|
||||
assert_eq!(cancel_rx.await, Ok(()));
|
||||
assert!(
|
||||
tokio::time::timeout(Duration::from_millis(20), &mut cancel_rx)
|
||||
.await
|
||||
.is_err()
|
||||
);
|
||||
let state = manager.thread_state(thread_id);
|
||||
assert!(state.lock().await.subscribed_connection_ids().is_empty());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
@ -7424,28 +7438,79 @@ mod tests {
|
|||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn removing_connection_clears_subscription_and_listener_when_last_subscriber()
|
||||
async fn removing_connection_retains_listener_and_active_turn_when_last_subscriber_disconnects()
|
||||
-> Result<()> {
|
||||
let mut manager = ThreadStateManager::new();
|
||||
let thread_id = ThreadId::from_string("ad7f0408-99b8-4f6e-a46f-bd0eec433370")?;
|
||||
let listener = Uuid::new_v4();
|
||||
let connection = ConnectionId(1);
|
||||
let (cancel_tx, cancel_rx) = oneshot::channel();
|
||||
let (cancel_tx, mut cancel_rx) = oneshot::channel();
|
||||
|
||||
manager
|
||||
.set_listener(listener, thread_id, connection, false)
|
||||
.await;
|
||||
{
|
||||
let state = manager.thread_state(thread_id);
|
||||
state.lock().await.cancel_tx = Some(cancel_tx);
|
||||
let mut state = state.lock().await;
|
||||
state.cancel_tx = Some(cancel_tx);
|
||||
state.track_current_turn_event(&EventMsg::TurnStarted(
|
||||
codex_protocol::protocol::TurnStartedEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
model_context_window: None,
|
||||
collaboration_mode_kind: Default::default(),
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
manager.remove_connection(connection).await;
|
||||
assert_eq!(cancel_rx.await, Ok(()));
|
||||
assert!(
|
||||
tokio::time::timeout(Duration::from_millis(20), &mut cancel_rx)
|
||||
.await
|
||||
.is_err()
|
||||
);
|
||||
assert_eq!(manager.remove_listener(listener).await, None);
|
||||
|
||||
let state = manager.thread_state(thread_id);
|
||||
assert!(state.lock().await.subscribed_connection_ids().is_empty());
|
||||
let state = state.lock().await;
|
||||
assert!(state.subscribed_connection_ids().is_empty());
|
||||
assert!(state.cancel_tx.is_some());
|
||||
let active_turn = state.active_turn_snapshot().expect("active turn snapshot");
|
||||
assert_eq!(active_turn.id, "turn-1");
|
||||
assert_eq!(active_turn.status, TurnStatus::InProgress);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn removing_thread_state_clears_listener_and_active_turn_history() -> Result<()> {
|
||||
let mut manager = ThreadStateManager::new();
|
||||
let thread_id = ThreadId::from_string("ad7f0408-99b8-4f6e-a46f-bd0eec433370")?;
|
||||
let connection = ConnectionId(1);
|
||||
let (cancel_tx, cancel_rx) = oneshot::channel();
|
||||
|
||||
manager
|
||||
.ensure_connection_subscribed(thread_id, connection, false)
|
||||
.await;
|
||||
{
|
||||
let state = manager.thread_state(thread_id);
|
||||
let mut state = state.lock().await;
|
||||
state.cancel_tx = Some(cancel_tx);
|
||||
state.track_current_turn_event(&EventMsg::TurnStarted(
|
||||
codex_protocol::protocol::TurnStartedEvent {
|
||||
turn_id: "turn-1".to_string(),
|
||||
model_context_window: None,
|
||||
collaboration_mode_kind: Default::default(),
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
manager.remove_thread_state(thread_id).await;
|
||||
assert_eq!(cancel_rx.await, Ok(()));
|
||||
|
||||
let state = manager.thread_state(thread_id);
|
||||
let state = state.lock().await;
|
||||
assert!(state.subscribed_connection_ids().is_empty());
|
||||
assert!(state.cancel_tx.is_none());
|
||||
assert!(state.active_turn_snapshot().is_none());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -175,7 +175,13 @@ impl ThreadStateManager {
|
|||
thread_state.remove_connection(subscription_state.connection_id);
|
||||
}
|
||||
if thread_state.subscribed_connection_ids().is_empty() {
|
||||
thread_state.clear_listener();
|
||||
tracing::debug!(
|
||||
thread_id = %thread_id,
|
||||
subscription_id = %subscription_id,
|
||||
connection_id = ?subscription_state.connection_id,
|
||||
listener_generation = thread_state.listener_generation,
|
||||
"retaining thread listener after last subscription removed"
|
||||
);
|
||||
}
|
||||
}
|
||||
Some(thread_id)
|
||||
|
|
@ -183,7 +189,15 @@ impl ThreadStateManager {
|
|||
|
||||
pub(crate) async fn remove_thread_state(&mut self, thread_id: ThreadId) {
|
||||
if let Some(thread_state) = self.thread_states.remove(&thread_id) {
|
||||
thread_state.lock().await.clear_listener();
|
||||
let mut thread_state = thread_state.lock().await;
|
||||
tracing::debug!(
|
||||
thread_id = %thread_id,
|
||||
listener_generation = thread_state.listener_generation,
|
||||
had_listener = thread_state.cancel_tx.is_some(),
|
||||
had_active_turn = thread_state.active_turn_snapshot().is_some(),
|
||||
"clearing thread listener during thread-state teardown"
|
||||
);
|
||||
thread_state.clear_listener();
|
||||
}
|
||||
self.subscription_state_by_id
|
||||
.retain(|_, state| state.thread_id != thread_id);
|
||||
|
|
@ -254,7 +268,11 @@ impl ThreadStateManager {
|
|||
let mut thread_state = thread_state.lock().await;
|
||||
thread_state.remove_connection(connection_id);
|
||||
if thread_state.subscribed_connection_ids().is_empty() {
|
||||
thread_state.clear_listener();
|
||||
tracing::debug!(
|
||||
connection_id = ?connection_id,
|
||||
listener_generation = thread_state.listener_generation,
|
||||
"retaining thread listener after connection disconnect left zero subscribers"
|
||||
);
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
|
@ -265,7 +283,12 @@ impl ThreadStateManager {
|
|||
let mut thread_state = thread_state.lock().await;
|
||||
thread_state.remove_connection(connection_id);
|
||||
if thread_state.subscribed_connection_ids().is_empty() {
|
||||
thread_state.clear_listener();
|
||||
tracing::debug!(
|
||||
thread_id = %thread_id,
|
||||
connection_id = ?connection_id,
|
||||
listener_generation = thread_state.listener_generation,
|
||||
"retaining thread listener after connection disconnect left zero subscribers"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue