mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-10-25 08:03:45 +00:00
fix(sessions): record a missed seed when it happens, not after the write
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KcyBRxE8j3ujCYkum9KrC4
This commit is contained in:
co-authored by
Claude Opus 5
parent
a939a12d11
commit
82cf519606
@@ -64,7 +64,10 @@ export function toolReloadEffect(name: string, args: any): ToolReloadEffect {
|
||||
}
|
||||
|
||||
function itemPath(args: any): string | undefined {
|
||||
return typeof args?.path === 'string' && args.path ? args.path : undefined
|
||||
// write_trigger carries the item under `config` (see writeTriggerDraft), unlike
|
||||
// every other tool here, which names it at the top level.
|
||||
const p = args?.path ?? args?.config?.path
|
||||
return typeof p === 'string' && p ? p : undefined
|
||||
}
|
||||
|
||||
/** One item mutation from a chat round, as the preview needs to read it back. */
|
||||
|
||||
@@ -124,6 +124,9 @@ export type ClearLiveEditorDraftOptions = UserDraftOptions & {
|
||||
}
|
||||
|
||||
const entries = new Map<string, DraftEntry>()
|
||||
// Cells whose last `seed` found no live entry (see `takeSeedMiss`). Bounded by
|
||||
// the seeds that missed and not yet been read back, and each entry is one key.
|
||||
const seedMisses = new Set<string>()
|
||||
const liveEditorDrafts = new Map<string, LiveEditorDraft>()
|
||||
/**
|
||||
* Map keys whose entry should start `syncSuspended` on acquire. Lets
|
||||
@@ -395,27 +398,35 @@ export const UserDraft = {
|
||||
* is still needed when a write fans out across components (e.g. an
|
||||
* editor's `initContent` cascading into the bound value).
|
||||
*
|
||||
* No-op if the entry isn't live yet (acquire via `use`/`useMany` first).
|
||||
* No-op if the entry isn't live yet (acquire via `use`/`useMany` first) —
|
||||
* recorded for {@link takeSeedMiss}, since the value then reached the server
|
||||
* without reaching the editor that will show it.
|
||||
*/
|
||||
/**
|
||||
* Whether a mounted editor currently holds this cell — i.e. whether {@link seed}
|
||||
* would reach one rather than no-op. An editor acquires its cell only once its
|
||||
* first load resolves, so this is false while one is still loading, and a
|
||||
* caller that seeded then has to reconcile the editor some other way.
|
||||
*/
|
||||
hasLiveEntry(itemKind: UserDraftItemKind, path: string, opts?: UserDraftOptions): boolean {
|
||||
return entries.has(mapKey(resolveWorkspace(opts), itemKind, path))
|
||||
},
|
||||
|
||||
seed<V>(itemKind: UserDraftItemKind, path: string, value: V, opts?: UserDraftOptions): void {
|
||||
const ws = resolveWorkspace(opts)
|
||||
const mk = mapKey(ws, itemKind, path)
|
||||
const entry = entries.get(mk)
|
||||
if (!entry) return
|
||||
if (!entry) {
|
||||
seedMisses.add(mk)
|
||||
return
|
||||
}
|
||||
seedMisses.delete(mk)
|
||||
entry.seedNextWrite = true
|
||||
entry.state.val = snapshotDraftValue(value)
|
||||
},
|
||||
|
||||
/**
|
||||
* Whether the last {@link seed} for this cell found no live entry, clearing the
|
||||
* record. An editor acquires its cell only once its first load resolves, so a
|
||||
* seed during that window reaches nothing and the value lands on the server
|
||||
* alone — a caller showing that editor has to make it re-read. Recorded at the
|
||||
* seed rather than asked afterwards: by then the editor may have acquired the
|
||||
* cell, hiding the very miss this reports.
|
||||
*/
|
||||
takeSeedMiss(itemKind: UserDraftItemKind, path: string, opts?: UserDraftOptions): boolean {
|
||||
return seedMisses.delete(mapKey(resolveWorkspace(opts), itemKind, path))
|
||||
},
|
||||
|
||||
/**
|
||||
* Currently-mounted live entries for `workspace` (in-tab only — for a
|
||||
* workspace-wide view call `DraftService` directly).
|
||||
|
||||
@@ -621,10 +621,11 @@
|
||||
if (pages.length === 0) return
|
||||
for (const p of pages) pendingPages.add(p)
|
||||
// A write reaches a hosted editor through the draft cell it holds, but an
|
||||
// editor still loading holds none yet and `seed` no-opped past it — so ask
|
||||
// whether the cell was live, and refresh the ones the write missed.
|
||||
// editor still loading holds none yet and the seed no-opped past it. The
|
||||
// miss is recorded when it happens — asking now would be too late, since
|
||||
// the editor can have acquired the cell during the write's round-trip.
|
||||
const kind = path ? entityKindForPage(pages[0]) : undefined
|
||||
const seedReachedEditor = !kind || !path || UserDraft.hasLiveEntry(kind, path, { workspace })
|
||||
const seedReachedEditor = !kind || !path || !UserDraft.takeSeedMiss(kind, path, { workspace })
|
||||
const effect = effectForWrite(entity, seedReachedEditor)
|
||||
if (effect !== 'none') pendingMutations.push({ pages, effect, path, workspace })
|
||||
clearTimeout(reloadHandle)
|
||||
|
||||
Reference in New Issue
Block a user