Skip to content

fix(text-editor): re-run the mention search when fulltext indexing advances - #11012

Closed
clayrisser wants to merge 1 commit into
hcengineering:developfrom
clayrisser:fix/mention-popup-reruns-on-indexing-update
Closed

fix(text-editor): re-run the mention search when fulltext indexing advances#11012
clayrisser wants to merge 1 commit into
hcengineering:developfrom
clayrisser:fix/mention-popup-reruns-on-indexing-update

Conversation

@clayrisser

Copy link
Copy Markdown

Problem

MentionPopup.svelte issues its fulltext query exactly once per query change and never retries:

// plugins/text-editor-resources/src/components/MentionPopup.svelte:213,225
const updateItems = reduceCalls(async function (localQuery: string): Promise<void> {
  …
})
$: void updateItems(query)

Fulltext indexing is asynchronous. A document created seconds earlier is routinely absent from that one result, and when it is, the popup sits on "No results" until the user changes the query — deleting a character and retyping it is the usual workaround, if the user knows to try it.

So typing @ and the name of a channel, issue or document you just created shows you nothing, and keeps showing you nothing, even after the index has caught up and the server has said so.

The client is already told when the index advances. The server broadcasts TxWorkspaceEvent with WorkspaceEvent.IndexingUpdate, and the client already delivers it to tx listeners. ActionsPopup subscribes to exactly this to refresh its own fulltext results (plugins/view-resources/src/components/ActionsPopup.svelte:265-272):

function txListener (txes: Tx[]): void {
  if (
    txes.some(
      (it) =>
        it._class === core.class.TxWorkspaceEvent && (it as TxWorkspaceEvent).event === WorkspaceEvent.IndexingUpdate
    )
  ) {
    void updateItems(search, filteredActions)

MentionPopup does not. That is the whole difference.

Fix

Register the same listener for the lifetime of the popup, using the same addTxListener / removeTxListener pair from @hcengineering/presentation (packages/presentation/src/utils.ts:85,96) that ActionsPopup uses:

  // The fulltext index is written asynchronously, so a document created moments ago
  // is routinely missing from the first 'mention' search. Re-run the query when the
  // server broadcasts that indexing advanced, the same way ActionsPopup does.
  function txListener (txes: Tx[]): void {
    if (
      txes.some(
        (it) =>
          it._class === core.class.TxWorkspaceEvent && (it as TxWorkspaceEvent).event === WorkspaceEvent.IndexingUpdate
      )
    ) {
      void updateItems(query)
    }
  }

  onMount(() => {
    addTxListener(txListener)
    return () => {
      removeTxListener(txListener)
    }
  })

The predicate is copied from ActionsPopup deliberately, so the two popups agree about what "indexing advanced" means and a future change to that event shape shows up in both places at once.

Scope and residual risk

  • The listener is registered on mount and removed on destroy, so it lives exactly as long as the popup.
  • updateItems is already wrapped in reduceCalls, so a burst of indexing events collapses rather than issuing a query per event.
  • Re-running the query is idempotent from the user's point of view: it replaces the result list, which is what a keystroke already does.
  • No change to the query itself, to the result rendering, or to the empty state.

Verification

Verified against develop @ 1be6047c8: MentionPopup.svelte:225 is still a bare $: void updateItems(query) with no tx listener, the ActionsPopup precedent is still at :265-272, and both addTxListener and removeTxListener are still exported from @hcengineering/presentation. git apply is clean.

No automated test is offered. plugins/text-editor-resources has no jest project, and the behaviour is a race between the fulltext pod and a Svelte component. Manual check: create a channel or document, immediately type @ plus its name into a message box, and watch the popup populate when indexing catches up instead of staying on "No results".

Related

The end-to-end symptom of this also shows up in the sanity suite. tests/sanity's sendMention has a three-attempt retry that is currently unreachable for an unrelated reason, so this indexing delay turns into a hard failure there rather than a retried one. I have opened that separately as a test-only change; the two are independent and can land in either order.

Provenance

Found while chasing an intermittent chat-backlinks failure on a self-hosted deployment: the mention popup would show "No results" for a document that existed and was searchable a moment later. The indexing-delay mechanism above is read from the code and matched against the ActionsPopup precedent; the timing window varies with index load and I have not characterised it beyond "seconds".

MentionPopup issues exactly one searchFor('mention', query) per keystroke
and never retries. Fulltext indexing is asynchronous, so a document
created seconds earlier is routinely absent from that one result and the
popup sits on "No results" until the user retypes the query.

The server already broadcasts TxWorkspaceEvent/WorkspaceEvent.IndexingUpdate
when the index advances, and the client already delivers it to tx
listeners; ActionsPopup uses precisely this to refresh its own fulltext
results. MentionPopup now registers the same listener for the lifetime of
the popup.

Co-authored-by: Cursor <cursoragent@cursor.com>
Signed-off-by: Clay Risser <clayrisser@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
@clayrisser
clayrisser force-pushed the fix/mention-popup-reruns-on-indexing-update branch from 0284da8 to fc7911b Compare August 13, 2026 06:47
@clayrisser

Copy link
Copy Markdown
Author

Closing — this was opened by an automated agent without my intent. Apologies for the noise.

@clayrisser clayrisser closed this Aug 14, 2026
@clayrisser
clayrisser deleted the fix/mention-popup-reruns-on-indexing-update branch August 14, 2026 20:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant