291
292
watch(resource: URI, opts: IWatchOptions): IDisposable {
294
>
// connection may have to wait for a (re)registration and the
295
>
// underlying AHP `createResourceWatch` + `subscribe` round-trip
296
>
// is itself async. Additionally, watchers are long-lived: every
297
>
// time the active connection for `authority` changes (reconnect,
298
>
// fallback to an older registration, eviction followed by a fresh
299
>
// registration, ...) we tear down any existing remote handle and
300
>
// re-attach against the new connection. The class-level
301
>
// {@link _onDidChangeConnection} event keeps us informed across
302
>
// the full entry-eviction cycle.
303
>
const store = new DisposableStore();
304
>
const handleHolder = store.add(new MutableDisposable<IDisposable>());
305
>
const authority = resource.authority;
306
>
const params: CreateResourceWatchParams = {
307
>
channel: ROOT_STATE_URI,
308
>
uri: this._decodeUri(resource).toString(),
309
>
recursive: opts.recursive,
310
>
...(opts.excludes.length > 0 ? { excludes: { items: [...opts.excludes] } } : {}),
311
>
...(opts.includes && opts.includes.length > 0
312
? { includes: { items: opts.includes.map(p => typeof p === 'string' ? p : p.pattern) } }
313
: {}),
315
>
316
>
// Track which connection the current handle was created against
317
>
// so we ignore spurious change events that don't represent a
318
>
// real swap (e.g. a stale registration disposal).
319
>
let attached: IRemoteFilesystemConnection | undefined;
320
>
let attaching = false;
321
>
let pendingReattach = false;
322
>
323
>
const reattach = async (): Promise<void> => {
324
>
if (store.isDisposed) {
325
return;
326
}
328
pendingReattach = true;
329
return;
330
}
332
>
const next = entry?.connections.at(-1);
333
>
if (next === attached) {
334
return;
335
}
337
>
attached = undefined;
338
>
const watchResource = next?.watchResource;
339
>
if (!next || !watchResource) {
340
return;
341
}
343
>
const target = next;
344
>
try {
345
>
const handle = await watchResource.call(target, params);
346
if (store.isDisposed) {
347
handle.dispose();