feat: cancel in-flight source.gather on new input events via AbortSignal#176
Merged
feat: cancel in-flight source.gather on new input events via AbortSignal#176
Conversation
- Add `signal?: AbortSignal` to `GatherArguments` in base/source.ts (backward compatible) - Modify `callSourceGather` in ext.ts to accept signal and use Promise.race with an abort promise; the abort error has name='DdcCallbackCancelError' so the existing isDdcCallbackCancelError guard silently discards it - Add `#currentGatherController` field and `abortCurrentGather()` to Ddc class - `doCompletion` now creates a new AbortController on each call and aborts the previous one, cancelling in-flight gathers immediately - `_onEvent` in app.ts calls `ddc.abortCurrentGather()` alongside `cbContext.revoke()` so rapid input cancels previous gathers at event time - Add unit tests in tests/gather_cancel_test.ts covering both signal and no-signal paths Agent-Logs-Url: https://github.com/Shougo/ddc.vim/sessions/afa28fc1-f849-4683-b8bd-fd0866840455 Co-authored-by: Shougo <41495+Shougo@users.noreply.github.com>
- Add exported createGatherAbortError() to build a DdcCallbackCancelError-named Error - Add exported createAbortPromise() using the helper, eliminating duplication - Update gather_cancel_test.ts to import createAbortPromise from ext.ts instead of duplicating the logic Agent-Logs-Url: https://github.com/Shougo/ddc.vim/sessions/afa28fc1-f849-4683-b8bd-fd0866840455 Co-authored-by: Shougo <41495+Shougo@users.noreply.github.com>
- Use `(_, rej)` in createAbortPromise instead of `(_res, rej)`
- Use `() => {}` in test instead of `(_resolve) => {}`
Agent-Logs-Url: https://github.com/Shougo/ddc.vim/sessions/afa28fc1-f849-4683-b8bd-fd0866840455
Co-authored-by: Shougo <41495+Shougo@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Add abort signal to ddc.vim source.gather for improved cancellation
feat: cancel in-flight source.gather on new input events via AbortSignal
Apr 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rapid input causes stale
source.gathercalls to run to completion unnecessarily, wasting CPU. This adds opt-inAbortSignalsupport so gathers are abandoned immediately when a new input event arrives.Changes
denops/ddc/base/source.tssignal?: AbortSignaltoGatherArguments— optional, fully backward compatible with existing source implementationsdenops/ddc/ext.tscreateGatherAbortError(): creates anErrorwithname = 'DdcCallbackCancelError'so the existing error guard silently swallows aborts without loggingcreateAbortPromise(signal): exported helper returning a Promise that rejects when the signal firescallSourceGather: accepts optionalsignal; when present, wraps the gather inPromise.race([gatherPromise, createAbortPromise(signal)])— cancels even sources that don't check the signal themselvesdenops/ddc/ddc.tsDdcgains#currentGatherController: AbortControllerandabortCurrentGather()doCompletioncreates a freshAbortControllerper call, aborting the previous one before startinggatherResultsthreads the signal through tocallSourceGatherdenops/ddc/app.tsddc.abortCurrentGather()is called alongside the existingcbContext.revoke()in_onEvent, so previous gathers are cancelled at event-arrival time rather than waiting for the nextdoCompletiondenops/ddc/tests/gather_cancel_test.tsPromise.race, no-signal legacy path, and non-aborted signal resolving normallyExample: source opt-in
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
dl.deno.land/usr/bin/curl curl -s REDACTED(dns block)jsr.io/tmp/deno_bin/deno /tmp/deno_bin/deno test -A denops/ddc/tests/loader_concurrent_test.ts denops/ddc/ddc.ts denops/ddc/callback.ts denops/ddc/utils.ts denops/ddc/context.ts(dns block)/tmp/deno_bin/deno /tmp/deno_bin/deno cache --config deno.json callback.ts(dns block)/tmp/deno_bin/deno /tmp/deno_bin/deno test --no-check -A callback.ts(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
目的:
要求仕様:
denops/ddc/types.ts
denops/ddc/ext.ts
denops/ddc/ddc.ts
denops/ddc/callback.ts
変更の詳細(差分レベルの案)
A) types.ts
B) ext.ts の callSourceGather の変更(要旨)
C) ddc.ts 側(doCompletion / gatherResults)
注意点
作業手順
よろしければこの内容で PR を作成します。
The following is the prior conversation context from the user's chat exploration (may be truncated):
User: Shougo/ddc.vim のパフォーマンスを改善したいです。特にユーザーが素早く入力したときに CPU 使用率が上がってしまう問題があります
Assistant: 続行するには先ほどのツール呼び出しの許可ダイアログで応答していただく必要があるため、ご返答をお待ちしています。
User: @copilot Accepted Confirmation: Are you sure?
Assistant: 結論(まずやるべきこと)
やることの流れ(短く)
今すぐ試せる緩和策(優先度高)
簡単な計測(ユーザー側で素早くできること)
This pull request was created from Copilot chat.