fix(informix): resolve metadata owners correctly
This commit is contained in:
10 files changed
+530
-79
No files matched your search
@@ -46,6 +46,20 @@ describe("TreeNodeLoadRegistry", () => {
|
||||
).toBe(db);
|
||||
});
|
||||
|
||||
it("does not let a user-cancelled load reclaim ownership", () => {
|
||||
const registry = new TreeNodeLoadRegistry();
|
||||
const node: TreeNodeLike = { id: "c1:db:schema", connectionId: "c1", isLoading: false, children: [] };
|
||||
const load = registry.begin(node);
|
||||
|
||||
registry.cancelPrefix("c1:db");
|
||||
node.isLoading = false;
|
||||
const reclaimed = load.reclaim(node);
|
||||
|
||||
expect(reclaimed).toBe(load);
|
||||
expect(reclaimed.isCurrent()).toBe(false);
|
||||
expect(node.isLoading).toBe(false);
|
||||
});
|
||||
|
||||
it("invalidates pruned descendant generations even when root no longer contains them", () => {
|
||||
const registry = new TreeNodeLoadRegistry();
|
||||
const db: TreeNodeLike = { id: "c1:db", connectionId: "c1", isLoading: false, children: [] };
|
||||
|
||||
@@ -28,12 +28,13 @@ export type TreeNodeLoadEpoch = {
|
||||
|
||||
export class TreeNodeLoadRegistry {
|
||||
private readonly generations = new Map<string, number>();
|
||||
private readonly cancellationGenerations = new Map<string, number>();
|
||||
|
||||
begin(node: TreeNodeLike): TreeNodeLoadHandle {
|
||||
const generation = (this.generations.get(node.id) ?? 0) + 1;
|
||||
this.generations.set(node.id, generation);
|
||||
node.isLoading = true;
|
||||
return this.createHandle(node.id, generation);
|
||||
return this.createHandle(node.id, generation, this.cancellationGenerations.get(node.id) ?? 0);
|
||||
}
|
||||
|
||||
/** Snapshot the current generation without claiming ownership (no spinner). */
|
||||
@@ -61,6 +62,22 @@ export class TreeNodeLoadRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* User cancellation is stronger than ordinary invalidation: a load waiting for
|
||||
* connection recovery must not reclaim ownership after its node was collapsed.
|
||||
*/
|
||||
cancelPrefix(nodeId: string): void {
|
||||
const prefix = `${nodeId}:`;
|
||||
const affectedIds = new Set<string>([nodeId]);
|
||||
for (const id of this.generations.keys()) {
|
||||
if (id.startsWith(prefix)) affectedIds.add(id);
|
||||
}
|
||||
for (const id of affectedIds) {
|
||||
this.cancellationGenerations.set(id, (this.cancellationGenerations.get(id) ?? 0) + 1);
|
||||
}
|
||||
this.invalidatePrefix(nodeId);
|
||||
}
|
||||
|
||||
/** Bump recorded generations for descendants only (not the parent load itself). */
|
||||
invalidateDescendants(parentId: string): void {
|
||||
const prefix = `${parentId}:`;
|
||||
@@ -90,7 +107,7 @@ export class TreeNodeLoadRegistry {
|
||||
return this.generations.get(nodeId) === generation;
|
||||
}
|
||||
|
||||
private createHandle(nodeId: string, generation: number): TreeNodeLoadHandle {
|
||||
private createHandle(nodeId: string, generation: number, cancellationGeneration: number): TreeNodeLoadHandle {
|
||||
const registry = this;
|
||||
return {
|
||||
nodeId,
|
||||
@@ -99,6 +116,9 @@ export class TreeNodeLoadRegistry {
|
||||
return registry.isCurrent(nodeId, generation);
|
||||
},
|
||||
reclaim(node: TreeNodeLike) {
|
||||
if (!registry.isCurrent(nodeId, generation) && (registry.cancellationGenerations.get(nodeId) ?? 0) !== cancellationGeneration) {
|
||||
return this;
|
||||
}
|
||||
if (node.id !== nodeId) {
|
||||
return registry.begin(node);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user