Compare commits

...
Author SHA1 Message Date
Alexey Potsetsuev dba38703d2 dbeaver/pro#6617 fix: remove default value for key parameter in useResourceTracker (#3665)
* dbeaver/pro#6617 fix: remove default value for key parameter in useResourceTracker

* fix: re-subscribe on resource

* fix: ensure subscription removed
2025-08-15 23:28:12 +08:00
Alexey Potsetsuev db08bd1df8 dbeaver/pro#6592 fix: resources loading (#3660) 2025-08-13 22:54:04 +08:00
2 changed files with 32 additions and 14 deletions
@@ -8,25 +8,39 @@
import type { Resource, ResourceKey } from '@cloudbeaver/core-resource';
import { useObjectRef } from '../useObjectRef.js';
import { toJS } from 'mobx';
import { reaction, toJS } from 'mobx';
import { useEffect } from 'react';
export function useResourceTracker<TKey>(resource: Resource<any, TKey, any, any>, key: ResourceKey<TKey> | null = null): void {
export function useResourceTracker<TKey>(resource: Resource<any, TKey, any, any>, key: ResourceKey<TKey> | null): void {
const state = useObjectRef(
() => ({
key: null as ResourceKey<TKey> | null,
id: null as string | null,
use(key: ResourceKey<TKey> | null): void {
sub: null as (() => void) | null,
use(key: ResourceKey<TKey> | null, resub = false): void {
key = toJS(key);
if (key !== null && this.key !== null && this.resource.isEqual(key, this.key)) {
if (!resub && key !== null && this.key !== null && this.resource.isEqual(key, this.key)) {
return;
}
this.free();
this.id = key === null ? null : this.resource.useTracker.use(key);
const id = key === null ? null : this.resource.useTracker.use(key);
this.id = id;
this.key = key;
if (id) {
this.sub = reaction(
() => this.resource.useTracker.hasUseId(id),
value => {
if (!value) {
this.use(key, true);
}
},
);
}
},
free() {
this.sub?.();
if (this.key !== null && this.id !== null && this.resource.useTracker.hasUseId(this.id)) {
this.resource.useTracker.free(this.key, this.id);
this.key = null;
@@ -336,29 +336,33 @@ export abstract class CachedResource<
return this.scheduler.wait();
}
// TODO: this method repeats isLoaded checks, maybe we can call just `this.isLoaded`
isOutdated(param?: ResourceKey<TKey>, includes?: TInclude): boolean {
if (param === undefined) {
param = CachedResourceParamKey;
}
if (!this.metadata.has(param)) {
return true;
}
const pageKey = this.aliases.isAlias(param, CachedResourceOffsetPageKey) || this.aliases.isAlias(param, CachedResourceOffsetPageListKey);
if (pageKey) {
const pageInfo = this.offsetPagination.getPageInfo(pageKey);
if (isOffsetPageOutdated(pageInfo?.pages || [], pageKey.options)) {
if (!pageInfo || !isOffsetPageInRange(pageInfo, pageKey.options) || isOffsetPageOutdated(pageInfo.pages, pageKey.options)) {
return true;
}
}
// TODO: this.metadata.size for some reason returns 0 when there is values
const size = [...this.metadata.values()].length;
return (
size === 0 ||
this.metadata.some(
param,
metadata => !metadata.loaded || metadata.outdated || !!includes?.some(include => metadata.outdatedIncludes.includes(include)),
)
return this.metadata.some(
param,
metadata =>
!metadata.loaded ||
metadata.outdated ||
!!includes?.some(include => metadata.outdatedIncludes.includes(include)) ||
!(!includes || includes.every(include => metadata.includes.includes(include))),
);
}